具有一对一关系的房间数据库

时间:2018-01-03 14:18:15

标签: android database entity android-room

我有2个实体,Coin和CoinRevenue。

基本上,硬币以其他货币为单位持有美元价格。

例如,带符号EUR的硬币,值为1.0356

@Entity(tableName = "coin")
data class Coin(
        @field:PrimaryKey(autoGenerate = false)
        var id: String = "",
        var symbol: String = "",
        var pricInUsd: Float = 0f)

CoinRevenue是一个实体,我用它来保存用户拥有的特定硬币的硬币数量。 例如,CoinRevenue与Coin Entity有关,EUR符号和金额为1000。

@Entity(tableName = "coinRevenue")
    data class CoinRevenueNew(
            @field:PrimaryKey(autoGenerate = true)
            var id: Int = 0,
            var coin: Coin? = null,
            var amount: Float = 0f)

现在我想从数据库中获取CoinRevenue并从数据库中获取更新的Coin。

例如,我用(EUR,1.0253)保存了硬币 而且用这枚硬币保存了一枚CoinRevenue。

之后我更新了硬币(EUR,2.522) 我希望CoinRevenue中的Coin对象也会更新。

我知道@Embedded只是将内部objet字段作为列添加到同一个父对象。 当我使用关系时,我必须使用List或Set。 但我在CoinRevenue中总是有1枚硬币。

我的硬币DAO:

@Query("select * from coin order by rank")
fun getAllCoins(): Flowable<List<CoinDB>>

@Query("select * from coin where rank = 1")
fun getFirstCoin(): Maybe<CoinDB>

@Query("select * from coin where favourite = 1 order by rank")
fun getAllFavouriteCoins(): Flowable<List<CoinDB>>

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertCoin(coinDB: CoinDB)

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertCoins(coinsList: List<CoinDB>)

// -----------------
// CoinRevenue
// -----------------

@Query("select * from coinRevenue order by rank")
fun getAllCoinsRevenue(): Flowable<List<CoinRevenue>>

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertCoinRevenue(coinRevenue: CoinRevenue)

@Delete()
fun deleteCoinRevenue(coinRevenue: CoinRevenue)

创造这个的最佳方法是什么?

3 个答案:

答案 0 :(得分:11)

经过多次尝试后,我设法让它发挥作用。

我更改了CoinRevenue对象以保存Coin id的外键

@Entity(tableName = "coinRevenue", foreignKeys = (arrayOf(ForeignKey(
        entity = CoinDB::class,
        onUpdate = ForeignKey.CASCADE,
        parentColumns = arrayOf("coinId"),
        childColumns = arrayOf("coinDbId"))))
)
data class CoinRevenue(
        @ColumnInfo(name = "mid")
        @PrimaryKey(autoGenerate = true)
        var id: Long = 0L,
        @ColumnInfo(name = "coinDbId")
        var coinDbId: String? = null,
        @ColumnInfo(name = "amount")
        var amount: Double = 0.toDouble()
)

我需要用这两个对象创建一个POJO:

class CoinRevenueWithCoin() : Parcelable {
@Embedded lateinit var coinDB: CoinDB
@Embedded lateinit var coinRevenue: CoinRevenue
}

和它的查询:

@Query("select * from coinRevenue, coin where coinRevenue.coinDbId = coin.coinId order by coin.rank")
fun getAllCoinsRevenueWithCoin(): Flowable<List<CoinRevenueWithCoin>>

那就是它。

此外,此查询与任何其他常规对象查询一样,如果“硬币”中有任何更改,则会发出对象。桌子或者硬币收入&#39;表

答案 1 :(得分:3)

您的解决方案有几个主要缺点。其中之一是表的列必须具有不同的名称。建议不要使用@Relationed。

@Entity(tableName = "coin")
data class Coin(
        @field:PrimaryKey(autoGenerate = false)
        var id: String = "",
        var symbol: String = "",
        var pricInUsd: Float = 0f)

@Entity(tableName = "coinRevenue", foreignKeys = (arrayOf(ForeignKey(
        entity = CoinDB::class,
        onUpdate = ForeignKey.CASCADE,
        parentColumns = arrayOf("coinId"),
        childColumns = arrayOf("coinDbId"))))
)
data class CoinRevenue(
        @ColumnInfo(name = "mid")
        @PrimaryKey(autoGenerate = true)
        var id: Long = 0L,
        @ColumnInfo(name = "coinDbId")
        var coinDbId: String? = null,
        @ColumnInfo(name = "amount")
        var amount: Double = 0.toDouble()
) 

我不熟悉Kotlin,所以解决方案是使用Java

class CoinRevenueExt extends CoinRevenue {
        @Relation(parentColumn = "coinDbId", entityColumn = "coinId" ) 
        List<Coin> coins;

        public Coin getCoin() {
            return coins.get(0);
        }

}

Dao很简单

@Query("select * from coinRevenue")
public Flowable<List<CoinRevenueExt>> getAllCoinsRevenueWithCoin();

答案 2 :(得分:0)

要说出你真正想要达到的目标有点难。而且,你的命名有点奇怪。硬币表似乎确实包含货币信息。 coinRevenueNew是分类帐条目或订单。如果您更容易选择示例,则会有更多人尝试阅读您的帖子。

此外,您要解决的问题有点不清楚。 - 您的问题是否在数据库中建模? - 当货币发生变化时,您想要自动更新所有金额的问题吗? - 当数据库发生变化时,您是否希望更新内存中的对象? - 使用Room的外键是否有问题?

其他人已经暗示了建模的第一个问题。您使用外键。有很多关于它的文章。

使用更易理解的域名,您可以拥有两个这样的表格:

create table currency (id integer primary key, exchange_rate float);
create table order (id integer primary key, int total, int currency_id, foreign key(currency_id) references currency(id));

您可以为每个人创建房间实体。您创建了一个结合两者的第三个类(不要用@Entity标记它)。您可以在此处使用注释@Embedded或@Relation。文档进一步解释了这一点:

https://developer.android.com/reference/android/arch/persistence/room/Relation.html

如果更改货币,存储系统将不会自动更新所有订单总计。如果你有一个&#34; total_in_foreign_currency&#34;和#34; total_in_master_currency&#34;的字段,数据库不会为您重新计算。您必须手动迭代每一行并重新计算它。

在内存中数据对象不会神奇地更新。您必须跟踪检索数据的时间以及现在是否仍然存在。您可以使用LiveData在数据发生变化时收到通知(但它不会神奇地更新您的对象)。