我有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)
创造这个的最佳方法是什么?
答案 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在数据发生变化时收到通知(但它不会神奇地更新您的对象)。