【问题标题】:Entity list relationships in Android RoomAndroid Room 中的实体列表关系
【发布时间】:2017-05-27 13:09:19
【问题描述】:

我正在尝试加载实体子列表,但我想避免进行 2 次查询。

我正在考虑在 TypeConverter 中进行查询,但我真的不知道这是否是个好主意。

我的实体:

@Entity
class Region(
        @PrimaryKey(autoGenerate = true)
        var id: Int = 0,
        var name: String = "",
        var locales: List<Locale> = listOf())

@Entity(foreignKeys = arrayOf(ForeignKey(
        entity = Region::class,
        parentColumns = arrayOf("id"),
        childColumns = arrayOf("regionId"),
        onDelete = CASCADE,
        onUpdate = CASCADE
)))
class Locale(
        @PrimaryKey(autoGenerate = true)
        var id: Int = 0,
        var regionId: Int = 0,
        var name: String = "")

DAO:

@Dao
interface RoomRegionDao{
    @Insert
    fun insert(region: Region)

    @Delete
    fun delete(region: Region)

    @Query("select * from region")
    fun selectAll(): Flowable<List<Region>>
}

@Dao
interface RoomLocaleDao{
    @Insert
    fun insert(locale: Locale)

    @Query("select * from locale where regionId = :arg0")
    fun selectAll(regionId: Int): List<Locale>
}

数据库:

@Database(entities = arrayOf(Region::class, Locale::class), version = 1)
@TypeConverters(RoomAppDatabase.Converters::class)
abstract class RoomAppDatabase : RoomDatabase() {
    abstract fun regionDao(): RoomRegionDao
    abstract fun localeDao(): RoomLocaleDao

    inner class Converters {
        @TypeConverter
        fun toLocales(regionId: Int): List<Locale> {
            return localeDao().selectAll(regionId)
        }

        @TypeConverter
        fun fromLocales(locales: List<Locale>?): Int {
            locales ?: return 0
            if (locales.isEmpty()) return 0

            return locales.first().regionId
        }
    }
}

它不起作用,因为不能将内部类用作转换器类。

  • 这是个好方法吗?
  • 当我执行RoomRegionDao.selectAll 时,如何在区域实体中自动加载“语言环境列表”?

【问题讨论】:

  • 就在我正要放弃 kotlin 和 Room 的时候,你的问题救了我。谢谢:)

标签: android database orm kotlin android-room


【解决方案1】:

我认为TypeConverter 仅适用于静态方法。 我是根据herehere 的例子说的

来自关系部分here

“因为 SQLite 是一个关系型数据库,你可以指定对象之间的关系。尽管大多数 ORM 库允许实体对象相互引用,但 Room 明确禁止这样做。”

所以我想最好在 locales 属性上添加 @Ignore 并在 RoomLocaleDao 上创建一个方法,即插入 List&lt;Locale&gt; 并在插入区域后调用它。

插入Region的方法可以返回inserted id

如果@Insert 方法只接收1 个参数,它可以返回一个long,即插入项的新rowId。如果参数是数组或集合,则应返回 long[] 或 List。 (https://developer.android.com/topic/libraries/architecture/room.html#daos-convenience)

【讨论】:

  • 是的,谢谢你的回答。唯一的方法是制作高级界面,所以我让 RegionDao 使用 RoomRegionDao 和 RoomLocaleDao 返回加载了语言环境的区域。
【解决方案2】:

您可以在每个Region 中获取所有RegionsLocales 列表,只需一个Query

您需要做的就是像这样创建一个新的Relation

data class RegionWithLocale(
    @Embedded
    val region: Region,
    @Relation(
        parentColumn = "id",
        entity = Locale::class,
        entityColumn = "regionId"
    )
    val locales: List<Locale>
)

后者在你的Dao 中得到这种关系,如下所示:

@Query("SELECT * FROM region WHERE id IS :regionId")
fun getRegions(regionId: Int): LiveData<RegionWithLocale>

@Query("SELECT * FROM region")
fun getAllRegions(): LiveData<List<RegionWithLocale>>

【讨论】:

    【解决方案3】:

    这个解决方案对我有用

    ListConvert.kt

    class ListConverter
    {
        companion object
        {
            var gson = Gson()
    
            @TypeConverter
            @JvmStatic
            fun fromTimestamp(data: String?): List<Weather>?
            {
                if (data == null)
                {
                    return Collections.emptyList()
                }
    
                val listType = object : TypeToken<List<String>>() {}.type
                return gson.fromJson(data, listType)
            }
    
            @TypeConverter
            @JvmStatic
            fun someObjectListToString(someObjects: List<Weather>?): String?
            {
                return gson.toJson(someObjects)
            }
        }
    }
    

    我的实体内部的属性

    @SerializedName("weather")
    @TypeConverters(ListConverter::class)
    val weather: List<Weather>,
    

    【讨论】:

    • 不建议这样做,因为如果需要,您不能直接从 SQL 查询Weather
    猜你喜欢
    • 2017-11-23
    • 2018-06-23
    • 1970-01-01
    • 2020-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多