Linked Questions

Popular Questions

Polymorphic entities in Room

Asked by At

There are 3 entities in my Room DB:

Album, PhotosMediaItem and VideosMediaItem.

VideosMediaItem and PhotosMediaItem inherit from MediaItem.

MediaItem is not an entity in the DB, it's just an abstract base class.

I would like to create a query that returns all the photos and videos media items in a specific album with descending order based on their creation date.

So the query will create a list of MediaItems but with the derived types. (PhotoMediaItem or VideoMediaItem) in a polymorphic way.

Here's what I've tried:

    @Query("SELECT * FROM PhotosMediaItem WHERE PhotosMediaItem = :albumId " +
        "UNION SELECT * FROM VideosMediaItem WHERE VideosMediaItem = :albumId" +
        " ORDER by CreationDate DESC")
    List<MediaItem> getAllMediaInAlbum(int albumId);

This won't work obviously, because it tries to initiate MediaItem object, and it is not my intention. I want this query to initiate the derived class, PhotoMediaItem or VideoMediaItem

Here's how my query looked like before the migration to Room, using the regular SQLiteHelper, and it worked just fine:

public ArrayList<MediaItem> getMediaListByAlbumId(int palbumId)
{
    Cursor cursor = null;
    try{
        ArrayList<MediaItem> mediaList = new ArrayList<>();
        String selectQuery = "SELECT "+ mPhotoId +","+ mPhotoCreationDate +", 0 AS mediaType, '' FROM "+ mPhotosTableName + " WHERE " + this.mPhotoAlbumId + "="+palbumId +
                " UNION " +
                "SELECT "+ mVideoId +","+ mVideoCreationDate + " ,1 AS mediaType, " + mVideoLength + " FROM " + mVideosTableName + " WHERE " + this.mVideoAlbumId +"="+palbumId +
                " ORDER BY CreationDate DESC";
        cursor = mDB.rawQuery(selectQuery, null);
        // looping through all rows and adding to list
        if (cursor.moveToFirst()){
            do {
                // MediaHolder consists of the media ID and its type
                int mediaType = cursor.getInt(2);
                MediaItem mediaItem = null;
                if (mediaType == 0) {
                    mediaItem = new PhotoMediaItem(cursor.getInt(0), null, palbumId);
                } else if (mediaType == 1) {
                    mediaItem = new VideoMediaItem(cursor.getInt(0), null, palbumId, cursor.getLong(3));
                }
                mediaList.add(mediaItem);
            }
            while (cursor.moveToNext());
        }
        return mediaList;
    }
    finally  {
        if(cursor != null){
            cursor.close();
        }
    }

}

How can I achieve the same effect using Room then?

Related Questions