【问题标题】:Android Room Database: How to embed multiple entitiesAndroid Room Database:如何嵌入多个实体
【发布时间】:2019-01-22 10:55:39
【问题描述】:

我正在为我的新项目使用空间,但我正在努力解决如何干净地访问一对一值
我有地址、所有者和网站的实体,所有者和网站都有关联的地址,每个网站都有一个所有者
是否可以干净地访问这些,例如site.owner.address.l1

我已经查看了@Relation,尽管它返回的列表不太理想

实体

@Entity(tableName="addresses")
data class Address(
    @PrimaryKey
    @ColumnInfo(name="address_id")
    val id: Int,

    @ColumnInfo(name="address_l1")
    val l1: String
)

@Entity(tablename="owners")
data class Owner(
    @PrimaryKey
    @ColumnInfo(name="owner_id")
    val id: Int,

    @ColumnInfo(name="owner_name")
    val name: String
)

@Entity(tableName="sites")
data class Site(
    @PrimaryKey
    @ColumnInfo(name="site_id")
    val id: Int,

    @ColumnInfo(name="site_addressid")
    val addressid: Int

    @ColumnInfo(name="site_ownerid")
    val ownerid: Int
)

道的

@Query("SELECT * FROM sites")
fun getSites(): List<Site>

@Query("SELECT * FROM owners")
fun getOwners(): List<Owner>

@Query("SELECT * FROM addresses")
fun getAddresses(): List<Address>

@Query("SELECT * FROM sites JOIN address ON sites.site_addressid = address.address_id JOIN owners ON sites.site_ownerid = owners.owner_id JOIN address ON owners.owner_addressid = address.address_id WHERE sites.site_id = :siteid")
fun getSiteByIdWithDetails(siteid): Site

我只能看到多个 POJO 的方法来完成这项工作,例如
无效但大致正确

data class OwnerAddress(
    @Embedded
    val owner: Owner,

    @Embedded
    val address: Address
)

data class SiteAddress(
    @Embedded
    val site: Site,

    @Embedded
    val owner: OwnerAddress,

    @Embedded
    val address: Address
}

并通过

@Query("SELECT * FROM sites JOIN address ON sites.site_addressid = address.address_id JOIN owners ON sites.site_ownerid = owners.owner_id JOIN address ON owners.owner_addressid = address.address_id WHERE sites.site_id = :siteid")
fun getSiteByIdWithDetails(siteid): SiteAddress

【问题讨论】:

  • 你的问题解决了吗?
  • 你解决了吗?

标签: database kotlin persistence android-room


【解决方案1】:

您是否尝试过在您的实体之间建立关系? Android Documentation for Relationships

@Entity(tableName="addresses")
data class Address(
    @PrimaryKey
    @ColumnInfo(name="address_id")
    val id: Int,

    @ColumnInfo(name="address_l1")
    val l1: String
)

@Entity(tablename="owners")
data class Owner(
    @PrimaryKey
    @ColumnInfo(name="owner_id")
    val id: Int,

    @ColumnInfo(name="owner_name")
    val name: String

    @ColumnInfo(name="owner_adress")
    @Entity val adress: Address
)

@Entity(tableName="sites")
data class Site(
    @PrimaryKey
    @ColumnInfo(name="site_id")
    val id: Int,

    @ColumnInfo(name="site_owner")
    @Embedded val owner: Owner

    @ColumnInfo(name="site_address")
    @Embedded val address: Address
)

所以现在您的站点有一个地址和一个所有者(有它的地址)。您的sites 表和owners 表都将包含地址列。

【讨论】:

  • 嗨,欢迎来到 SO。提供链接很好,但它是一个很好的做法,可以提供关于它如何回答最初问题的额外解释
  • 添加了对应的代码sn-p,希望能澄清我的回答。
【解决方案2】:

您可以将 TypeConverter 和 Gson 库用于您的范围。

将您的数据类定义为

@Entity(tableName="addresses")
data class Address(
    @PrimaryKey
    @ColumnInfo(name="address_id")
    val id: Int,

    @ColumnInfo(name="address_l1")
    val l1: String
)

@Entity(tablename="owners")
data class Owner(
    @PrimaryKey
    @ColumnInfo(name="owner_id")
    val id: Int,

    @ColumnInfo(name="owner_name")
    val name: String
)

@Entity(tableName="sites")
data class Site(
    @PrimaryKey
    @ColumnInfo(name="site_id")
    val id: Int,

    @ColumnInfo(name="site_address")
    val address: Address,

    @ColumnInfo(name="site_owner")
    val owner: Owner
)

然后创建一个DatabaseConverter 类

class DatabaseConverter 
{
    @TypeConverter
    fun ownerFromJson(jsonString: String) : Owner {
        val ownerType = object : TypeToken<Owner>() { }.type
        return Gson().fromJson(jsonString, ownerType)
    }

    @TypeConverter
    fun jsonFromOwner(owner: Owner) : String = Gson().toJson(owner)

    @TypeConverter
    fun addressFromJson(jsonString: String) : Address {
        val addressType = object : TypeToken<Address>() { }.type
        return Gson().fromJson(jsonString, addressType)
    }

    @TypeConverter
    fun jsonFromAddress(address: Address) : String = Gson().toJson(address)
}

然后将其附加到您的 RoomDatabase 实例类

@Database(entities = [ ... ], version = ...)
@TypeConverters(DatabaseConverter::class)
abstract class YourDatabaseClass: RoomDatabase() {
    ...
}

您现在应该可以使用

访问您的子实体实例了
site.site_address.id 
site.site_owner.id

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-12
    • 2019-11-13
    • 2017-11-23
    • 1970-01-01
    • 1970-01-01
    • 2020-05-27
    • 1970-01-01
    • 2021-10-10
    相关资源
    最近更新 更多