Search code examples
androidkotlinandroid-roomandroid-databaseandroid-components

Insert an object inside an object using android room persistence library


Directory

@Entity(tableName = "directory")
class Directory(@PrimaryKey(autoGenerate = false) var id: Int? = null,
                @ColumnInfo(name = DIR_NAME) var dirName: String? = null,
                @Ignore var dirImages: List<Images>? = null

) : Serializable {
    companion object {
        const val DIR_NAME = "dirName"
        const val DIR_IMAGES = "dirImages"
    }
}

Image model

@Entity(foreignKeys = arrayOf(ForeignKey(entity = Directory::class,
        parentColumns = arrayOf("id"),
        childColumns = arrayOf("id"),
        onDelete = ForeignKey.CASCADE)))

data class Images(
        @PrimaryKey(autoGenerate = false) val id: Int? = null,
        @ColumnInfo(name = "image") val images: String
) {

}

Directory Dao

@Dao
interface DirectoryDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertAll(directory: ArrayList<Directory>?)

}

How to insert list of images in directory? Should I create a separate Dao for images?


Solution

  • Why not make your list of Images a simple list of String ? (you can use typealias in kotlin if you want to stick to image)

    You have 2 options, depending on how you need to access your Image Objects. Are you okay to only get the list of Images from your Directory object or you do you need to some queries on your images in the DB? (such as count, findBy etc...)

    1st option, if you just want to get your list of Images in your Directory object (probably the best for your case) :

    @Entity(tableName = "directory")
    class Directory(@PrimaryKey(autoGenerate = false) var id: Int,
                    @ColumnInfo(name = DIR_NAME) var dirName: String,
                    @ColumnInfo(name = "images")
                    @TypeConverters(ImagesConverters::class)
                     var dirImages: List<Images>)
    

    where ImagesConverters.kt :

    public class ImagesConverters {
    
        /**
         * Convert a a list of Images to a Json
         */
        @TypeConverter
        fun fromImagesJson(stat: List<Images>): String {
            return Gson().toJson(stat)
        }
    
        /**
         * Convert a json to a list of Images
         */
        @TypeConverter
        fun toImagesList(jsonImages: String): List<Images> {
            val notesType = object : TypeToken<List<Images>>() {}.type
            return Gson().fromJson<List<Images>>(jsonImages, notesType)
        }
    }
    

    Don't forget to add gson in your gradle file :

    implementation 'com.google.code.gson:gson:2.8.4'
    

    In the your table "Directory", it will store the list of images directly into the col "images", in a json format.

    2nd option, if you just want to a different table for your images and execute queries on them.

    You will need to use a one to many relations and have 3 objects :

    // directory.kt
    @Entity(tableName = "directory")
    class Directory(@PrimaryKey(autoGenerate = false) var id: Int,
                    @ColumnInfo(name = DIR_NAME) var dirName: String)
    
    
    // image.kt
    @Entity(tableName = "images")
    class Image(@PrimaryKey(autoGenerate = false) var id: Int,
                @ColumnInfo(name ="images") var image: String,
                @ColumnInfo(name ="directoryId") var directoryId: Int)
    
    // directoryWithImages.kt
    public class DirectoryWithImages {
       @Embedded
       public Directory directory;
    
       @Relation(parentColumn = "id", entityColumn = "directoryId", entity = Image.class)
       public List<Image> images;
    }
    

    And finally your dao :

    @Dao
    public interface LoadDirectoryWithImagesDao {
        @Query("SELECT * FROM directory")
        public List<DirectoryWithImages> loadDirectoriesWithImages();
    }
    

    Hope this help !