在 Kotlin Rooms 中插入多对多关系
Insert in Many-To-Many-Relations in Kotlin Rooms
我正在使用 Android Room 进行一个项目,但我有点坚持使用多对多关系。我发现 问题与我的有点相似,但我仍然无法解决它。
所以我基本上是按照Documentation做了一个Reciepe和Ingredient Relationship:
@Entity(tableName ="zutaten_table")
data class ZutatenData(
@PrimaryKey (autoGenerate = true) val zutatid : Int,
@ColumnInfo(name = "zutname") var zutname : String,
//and some more columns
)
@Entity(tableName = "rezepte_table")
data class RezepteData(
@PrimaryKey (autoGenerate = true) val rezeptid : Int,
@ColumnInfo(name = "rezname") var rezname : String,
@ColumnInfo(name = "bild") var bild:Int
)
@Entity(primaryKeys = ["zutatid", "rezeptid"])
data class RefZutatRezept(
val zutatid: Int,
val rezeptid: Int
)
data class ZutatenWithRezept(
@Embedded val zutat: ZutatenData,
@Relation(
parentColumn = "zutatid",
entity = RezepteData::class,
entityColumn = "rezeptid",
associateBy = Junction(value = RefZutatRezept::class,
parentColumn = "zutatid",
entityColumn = "rezeptid"
)
)
val rezepte: List<RezepteData>
)
data class RezeptWithZutat(
@Embedded val rezept: RezepteData,
@Relation(
parentColumn = "rezeptid",
entityColumn = "zutatid",
associateBy = Junction(RefZutatRezept::class)
)
val zutaten: List<ZutatenData>
)
我对每种数据类型都有一个 Dao(不确定这是正确的方法...)
@Dao
interface ZutatDao{
@Query("SELECT * FROM zutaten_table ORDER BY zutname ASC")
fun getAlphabetizedZutaten(): LiveData<List<ZutatenData>>
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(zutname: ZutatenData)
@Update
suspend fun update(zutname: ZutatenData)
@Query("DELETE FROM zutaten_table")
suspend fun deleteAll()
}
@Dao
interface RezeptDao{
@Query("SELECT * FROM rezepte_table ORDER BY rezname ASC")
fun getRezepte() : LiveData<List<RezepteData>>
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(rezepte : RezepteData) :Long
@Query("DELETE FROM rezepte_table")
suspend fun deleteAll()
}
@Dao
interface ZutatwithRezeptDao{
@Transaction
@Query("SELECT * FROM zutaten_table ORDER BY zutname ASC")
suspend fun getZutatenWithRezept(): List<ZutatenWithRezept>
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(join:RefZutatRezept)
}
@Dao
interface RezeptwithZutatDao {
@Transaction
@Query("SELECT * FROM rezepte_table ORDER BY rezname ASC")
suspend fun getRezeptwithZutat(): List<RezeptWithZutat>
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(join: RefZutatRezept)
}
我现在想插入一个 RezeptWithZutat(我现在正在 populateDatabase 函数中做。)
var ListZutatRez1 = listOf<ZutatenData>( z_kart, z_quark, z_lein)
var rez = RezepteData(0,"Kartoffeln mit Quark", R.drawable.kartoffelnquark)
var rezges =RezeptWithZutat(rez, ListZutatRez1)
rezzut.insert(rezges)
在最后一行我收到错误:“类型不匹配:推断的类型是 RezeptWithZutat,但 RefZutatRezept 是预期的”我尝试了一些方法,但它们都给我带来了不同的错误。
所以我的问题是:将 RezeptWithZutat 自动插入到 table 中的正确方法是什么(为 RezeptData 创建一个条目,为确实存在的所有 ZutatData 创建一个条目,并链接 RefZutatRezept 中的所有内容 table.)
这不是简单的一行修复。
首先,您需要能够检测 Zutaten 是否存在,并且可能是否存在 Rezepte(因此现有 Rezept 的 RezeptWithZutat 确实会创建一个新的,但会添加到现有的 Rezepte 中)。
所以前两个新刀
- 注意下面的代码使用抽象class而不是接口,所以使用抽象乐趣而不是乐趣。
- 所有的 dao 也被合并为一个抽象 class 即 AllDao.
- 注意我不做 LiveData 的事情所以代码不使用 LiveData 并且我复制的代码已经删除了所有 LiveData 以允许工作演示。
:-
@Query("SELECT zutatid FROM zutaten_table WHERE zutname=:zutname")
abstract fun getZutatenIdByName(zutname: String): Int
@Query("SELECT rezeptid FROM rezepte_table WHERE rezname=:rezname")
abstract fun getRezepteIDByName(rezname: String): Int
如果 zutaten/rezept 不存在,这些将 return id 或 0。
接下来是一个函数,在 AllDao(它直接使用 Dao 的)中插入 RezeptWithZutat:-
fun insertZutatenWithRezept(rezeptWithZutat: RezeptWithZutat) {
var rid = getRezepteIDByName(rezeptWithZutat.rezept.rezname)
/* find or insert Rezepte according to name */
if (rid < 1) {
rid = insert(RezepteData(0,rezeptWithZutat.rezept.rezname,rezeptWithZutat.rezept.bild)).toInt()
}
if (rid < 1) {
/*
could not find existing Rezepte or insert a new one?????
should not happen but in case do something here
*/
} else {
for (z in rezeptWithZutat.zutaten) {
var zid = getZutatenIdByName(z.zutname)
if (zid < 1) {
zid = insert(ZutatenData(0, z.zutname)).toInt()
}
if (zid < 1) {
/*
could not find existing Zutaten or insert new one?????
should not happen but in case do something here
*/
} else {
insert(RefZutatRezept(zutatid = zid, rezeptid = rid))
}
}
}
}
- 这不是最有效的方法,因为可以将不存在的 Zutatens 一起插入(但使用更复杂的代码),同样可以将 RefZutatRezept 一起插入(再次使用更复杂的代码)。
演示(运行 在 convenience/brevity 的主线程上)
使用以上内容和您的 code/dao(如上更改)然后在 Activity :-
db = TheDatabase.getInstance(this)
dao = db.getAllDao()
val r1 = dao.insert(RezepteData(rezeptid = 0,rezname = "REZ1",bild = 1))
val r2 = dao.insert(RezepteData(rezeptid = 0, rezname = "REZ2", bild = 1))
val milk = dao.insert(ZutatenData(zutatid = 0,zutname = "Milk"))
val sugar = dao.insert(ZutatenData(zutatid = 0,zutname = "Sugar"))
val flour = dao.insert(ZutatenData(zutatid = 0,zutname = "Flour"))
val eggs = dao.insert(ZutatenData(zutatid = 0,zutname = "Eggs"))
dao.insert(RefZutatRezept(milk.toInt(),r1.toInt()))
dao.insert(RefZutatRezept(flour.toInt(),r1.toInt()))
dao.insert(RefZutatRezept(eggs.toInt(),r1.toInt()))
Log.d("STAGE1", "data before adding R-With-Z")
showAllRezeptWithZutatsInDatabase()
var newRWithZ = RezeptWithZutat(
RezepteData(0,"REZ3",1),zutaten = listOf(
ZutatenData(0,"salt"),
ZutatenData(0,"nutmeg"),
ZutatenData(0,"cornflour"),
ZutatenData(0,"corriander"),
ZutatenData(0,"Milk"), // exists
ZutatenData(0,"Sugar"), // exists
ZutatenData(0,"More Sugar")
)
)
dao.insertZutatenWithRezept(newRWithZ)
Log.d("STAGE2", "data after adding R-With-Z")
showAllRezeptWithZutatsInDatabase()
newRWithZ = RezeptWithZutat(
RezepteData(0,"REZ3",1),
zutaten = listOf(
ZutatenData(0,"leek"),
ZutatenData(0,"apple"),
ZutatenData(0,"banana"),
ZutatenData(0,"pineapple"),
ZutatenData(0,"Milk"), // exists
ZutatenData(0,"Sugar"),
ZutatenData(0,"More Sugar")
) //Rezepte also exists
)
dao.insertZutatenWithRezept(newRWithZ)
Log.d("STAGE3", "data after adding R-With-Z")
showAllRezeptWithZutatsInDatabase()
}
fun showAllRezeptWithZutatsInDatabase() {
for(rzr: RezeptWithZutat in dao.getRezeptwithZutat()) {
Log.d("DBINFO","Rezept is ${rzr.rezept.rezname} Bild is ${rzr.rezept.bild} ID is ${rzr.rezept.rezeptid}")
for(z: ZutatenData in rzr.zutaten) {
Log.d("DBINFO","\tZutaten is ${z.zutname} ID is ${z.zutatid}")
}
}
}
当 运行(一次)时,日志包括:-
2021-10-25 20:55:47.370 D/STAGE1: data before adding R-With-Z
2021-10-25 20:55:47.377 D/DBINFO: Rezept is REZ1 Bild is 1 ID is 1
2021-10-25 20:55:47.377 D/DBINFO: Zutaten is Milk ID is 1
2021-10-25 20:55:47.377 D/DBINFO: Zutaten is Flour ID is 3
2021-10-25 20:55:47.377 D/DBINFO: Zutaten is Eggs ID is 4
2021-10-25 20:55:47.377 D/DBINFO: Rezept is REZ2 Bild is 1 ID is 2
2021-10-25 20:55:47.425 D/STAGE2: data after adding R-With-Z
2021-10-25 20:55:47.428 D/DBINFO: Rezept is REZ1 Bild is 1 ID is 1
2021-10-25 20:55:47.428 D/DBINFO: Zutaten is Milk ID is 1
2021-10-25 20:55:47.428 D/DBINFO: Zutaten is Flour ID is 3
2021-10-25 20:55:47.428 D/DBINFO: Zutaten is Eggs ID is 4
2021-10-25 20:55:47.428 D/DBINFO: Rezept is REZ2 Bild is 1 ID is 2
2021-10-25 20:55:47.428 D/DBINFO: Rezept is REZ3 Bild is 1 ID is 3
2021-10-25 20:55:47.428 D/DBINFO: Zutaten is salt ID is 5
2021-10-25 20:55:47.429 D/DBINFO: Zutaten is nutmeg ID is 6
2021-10-25 20:55:47.429 D/DBINFO: Zutaten is cornflour ID is 7
2021-10-25 20:55:47.429 D/DBINFO: Zutaten is corriander ID is 8
2021-10-25 20:55:47.429 D/DBINFO: Zutaten is Milk ID is 1
2021-10-25 20:55:47.429 D/DBINFO: Zutaten is Sugar ID is 2
2021-10-25 20:55:47.429 D/DBINFO: Zutaten is More Sugar ID is 9
2021-10-25 20:55:47.459 D/STAGE3: data after adding R-With-Z
2021-10-25 20:55:47.461 D/DBINFO: Rezept is REZ1 Bild is 1 ID is 1
2021-10-25 20:55:47.461 D/DBINFO: Zutaten is Milk ID is 1
2021-10-25 20:55:47.461 D/DBINFO: Zutaten is Flour ID is 3
2021-10-25 20:55:47.461 D/DBINFO: Zutaten is Eggs ID is 4
2021-10-25 20:55:47.461 D/DBINFO: Rezept is REZ2 Bild is 1 ID is 2
2021-10-25 20:55:47.461 D/DBINFO: Rezept is REZ3 Bild is 1 ID is 3
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is salt ID is 5
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is nutmeg ID is 6
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is cornflour ID is 7
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is corriander ID is 8
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is Milk ID is 1
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is Sugar ID is 2
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is More Sugar ID is 9
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is leek ID is 10
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is apple ID is 11
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is banana ID is 12
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is pineapple ID is 13
建议
- RefZutatRezept 的 rezeptid 列上的索引 table。
- rezname 和 zutname 的唯一索引(目前您可以有 Milk 的 id 为 1 和 Milk 的 id 为 2 等等)。
- RefZutatRezept 上的外键约束 table 以强制执行参照完整性并级联删除和更新
Cascade 会将父项的相关更改应用到子项。
例如如果您删除了 Zutaten,那么 RefZutatRezept 中引用 Zutaten 的所有行都将自动删除
- 没有你可能会遇到问题,因为会有对不存在的 Zutaten 的引用。同样对于任何 Rezepte 的
onUpdate 操作并不那么重要,因为您不太可能更改 zutatid 或 rezptid。
所以你不妨考虑以下几点:-
@Entity(
tableName ="zutaten_table",
indices = [ Index(value = ["zutname"],unique = true)]
)
data class ZutatenData(
@PrimaryKey(autoGenerate = true) val zutatid : Int,
@ColumnInfo(name = "zutname") var zutname : String
//and some more columns
)
和
@Entity(tableName = "rezepte_table",
indices = [Index(value = ["rezname"],unique = true)]
)
data class RezepteData(
@PrimaryKey(autoGenerate = true) val rezeptid : Int,
@ColumnInfo(name = "rezname") var rezname : String,
@ColumnInfo(name = "bild") var bild:Int
)
和
@Entity(
primaryKeys = ["zutatid", "rezeptid"],
indices = [Index(value = ["rezeptid"])],
foreignKeys = [
ForeignKey(
entity = ZutatenData::class,
parentColumns = ["zutatid"],
childColumns = ["zutatid"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
),
ForeignKey(
entity = RezepteData::class,
parentColumns = ["rezeptid"],
childColumns = ["rezeptid"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
)
]
)
data class RefZutatRezept(
val zutatid: Int,
val rezeptid: Int
)
我正在使用 Android Room 进行一个项目,但我有点坚持使用多对多关系。我发现
所以我基本上是按照Documentation做了一个Reciepe和Ingredient Relationship:
@Entity(tableName ="zutaten_table")
data class ZutatenData(
@PrimaryKey (autoGenerate = true) val zutatid : Int,
@ColumnInfo(name = "zutname") var zutname : String,
//and some more columns
)
@Entity(tableName = "rezepte_table")
data class RezepteData(
@PrimaryKey (autoGenerate = true) val rezeptid : Int,
@ColumnInfo(name = "rezname") var rezname : String,
@ColumnInfo(name = "bild") var bild:Int
)
@Entity(primaryKeys = ["zutatid", "rezeptid"])
data class RefZutatRezept(
val zutatid: Int,
val rezeptid: Int
)
data class ZutatenWithRezept(
@Embedded val zutat: ZutatenData,
@Relation(
parentColumn = "zutatid",
entity = RezepteData::class,
entityColumn = "rezeptid",
associateBy = Junction(value = RefZutatRezept::class,
parentColumn = "zutatid",
entityColumn = "rezeptid"
)
)
val rezepte: List<RezepteData>
)
data class RezeptWithZutat(
@Embedded val rezept: RezepteData,
@Relation(
parentColumn = "rezeptid",
entityColumn = "zutatid",
associateBy = Junction(RefZutatRezept::class)
)
val zutaten: List<ZutatenData>
)
我对每种数据类型都有一个 Dao(不确定这是正确的方法...)
@Dao
interface ZutatDao{
@Query("SELECT * FROM zutaten_table ORDER BY zutname ASC")
fun getAlphabetizedZutaten(): LiveData<List<ZutatenData>>
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(zutname: ZutatenData)
@Update
suspend fun update(zutname: ZutatenData)
@Query("DELETE FROM zutaten_table")
suspend fun deleteAll()
}
@Dao
interface RezeptDao{
@Query("SELECT * FROM rezepte_table ORDER BY rezname ASC")
fun getRezepte() : LiveData<List<RezepteData>>
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(rezepte : RezepteData) :Long
@Query("DELETE FROM rezepte_table")
suspend fun deleteAll()
}
@Dao
interface ZutatwithRezeptDao{
@Transaction
@Query("SELECT * FROM zutaten_table ORDER BY zutname ASC")
suspend fun getZutatenWithRezept(): List<ZutatenWithRezept>
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(join:RefZutatRezept)
}
@Dao
interface RezeptwithZutatDao {
@Transaction
@Query("SELECT * FROM rezepte_table ORDER BY rezname ASC")
suspend fun getRezeptwithZutat(): List<RezeptWithZutat>
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(join: RefZutatRezept)
}
我现在想插入一个 RezeptWithZutat(我现在正在 populateDatabase 函数中做。)
var ListZutatRez1 = listOf<ZutatenData>( z_kart, z_quark, z_lein)
var rez = RezepteData(0,"Kartoffeln mit Quark", R.drawable.kartoffelnquark)
var rezges =RezeptWithZutat(rez, ListZutatRez1)
rezzut.insert(rezges)
在最后一行我收到错误:“类型不匹配:推断的类型是 RezeptWithZutat,但 RefZutatRezept 是预期的”我尝试了一些方法,但它们都给我带来了不同的错误。
所以我的问题是:将 RezeptWithZutat 自动插入到 table 中的正确方法是什么(为 RezeptData 创建一个条目,为确实存在的所有 ZutatData 创建一个条目,并链接 RefZutatRezept 中的所有内容 table.)
这不是简单的一行修复。
首先,您需要能够检测 Zutaten 是否存在,并且可能是否存在 Rezepte(因此现有 Rezept 的 RezeptWithZutat 确实会创建一个新的,但会添加到现有的 Rezepte 中)。
所以前两个新刀
- 注意下面的代码使用抽象class而不是接口,所以使用抽象乐趣而不是乐趣。
- 所有的 dao 也被合并为一个抽象 class 即 AllDao.
- 注意我不做 LiveData 的事情所以代码不使用 LiveData 并且我复制的代码已经删除了所有 LiveData 以允许工作演示。
:-
@Query("SELECT zutatid FROM zutaten_table WHERE zutname=:zutname")
abstract fun getZutatenIdByName(zutname: String): Int
@Query("SELECT rezeptid FROM rezepte_table WHERE rezname=:rezname")
abstract fun getRezepteIDByName(rezname: String): Int
如果 zutaten/rezept 不存在,这些将 return id 或 0。
接下来是一个函数,在 AllDao(它直接使用 Dao 的)中插入 RezeptWithZutat:-
fun insertZutatenWithRezept(rezeptWithZutat: RezeptWithZutat) {
var rid = getRezepteIDByName(rezeptWithZutat.rezept.rezname)
/* find or insert Rezepte according to name */
if (rid < 1) {
rid = insert(RezepteData(0,rezeptWithZutat.rezept.rezname,rezeptWithZutat.rezept.bild)).toInt()
}
if (rid < 1) {
/*
could not find existing Rezepte or insert a new one?????
should not happen but in case do something here
*/
} else {
for (z in rezeptWithZutat.zutaten) {
var zid = getZutatenIdByName(z.zutname)
if (zid < 1) {
zid = insert(ZutatenData(0, z.zutname)).toInt()
}
if (zid < 1) {
/*
could not find existing Zutaten or insert new one?????
should not happen but in case do something here
*/
} else {
insert(RefZutatRezept(zutatid = zid, rezeptid = rid))
}
}
}
}
- 这不是最有效的方法,因为可以将不存在的 Zutatens 一起插入(但使用更复杂的代码),同样可以将 RefZutatRezept 一起插入(再次使用更复杂的代码)。
演示(运行 在 convenience/brevity 的主线程上)
使用以上内容和您的 code/dao(如上更改)然后在 Activity :-
db = TheDatabase.getInstance(this)
dao = db.getAllDao()
val r1 = dao.insert(RezepteData(rezeptid = 0,rezname = "REZ1",bild = 1))
val r2 = dao.insert(RezepteData(rezeptid = 0, rezname = "REZ2", bild = 1))
val milk = dao.insert(ZutatenData(zutatid = 0,zutname = "Milk"))
val sugar = dao.insert(ZutatenData(zutatid = 0,zutname = "Sugar"))
val flour = dao.insert(ZutatenData(zutatid = 0,zutname = "Flour"))
val eggs = dao.insert(ZutatenData(zutatid = 0,zutname = "Eggs"))
dao.insert(RefZutatRezept(milk.toInt(),r1.toInt()))
dao.insert(RefZutatRezept(flour.toInt(),r1.toInt()))
dao.insert(RefZutatRezept(eggs.toInt(),r1.toInt()))
Log.d("STAGE1", "data before adding R-With-Z")
showAllRezeptWithZutatsInDatabase()
var newRWithZ = RezeptWithZutat(
RezepteData(0,"REZ3",1),zutaten = listOf(
ZutatenData(0,"salt"),
ZutatenData(0,"nutmeg"),
ZutatenData(0,"cornflour"),
ZutatenData(0,"corriander"),
ZutatenData(0,"Milk"), // exists
ZutatenData(0,"Sugar"), // exists
ZutatenData(0,"More Sugar")
)
)
dao.insertZutatenWithRezept(newRWithZ)
Log.d("STAGE2", "data after adding R-With-Z")
showAllRezeptWithZutatsInDatabase()
newRWithZ = RezeptWithZutat(
RezepteData(0,"REZ3",1),
zutaten = listOf(
ZutatenData(0,"leek"),
ZutatenData(0,"apple"),
ZutatenData(0,"banana"),
ZutatenData(0,"pineapple"),
ZutatenData(0,"Milk"), // exists
ZutatenData(0,"Sugar"),
ZutatenData(0,"More Sugar")
) //Rezepte also exists
)
dao.insertZutatenWithRezept(newRWithZ)
Log.d("STAGE3", "data after adding R-With-Z")
showAllRezeptWithZutatsInDatabase()
}
fun showAllRezeptWithZutatsInDatabase() {
for(rzr: RezeptWithZutat in dao.getRezeptwithZutat()) {
Log.d("DBINFO","Rezept is ${rzr.rezept.rezname} Bild is ${rzr.rezept.bild} ID is ${rzr.rezept.rezeptid}")
for(z: ZutatenData in rzr.zutaten) {
Log.d("DBINFO","\tZutaten is ${z.zutname} ID is ${z.zutatid}")
}
}
}
当 运行(一次)时,日志包括:-
2021-10-25 20:55:47.370 D/STAGE1: data before adding R-With-Z
2021-10-25 20:55:47.377 D/DBINFO: Rezept is REZ1 Bild is 1 ID is 1
2021-10-25 20:55:47.377 D/DBINFO: Zutaten is Milk ID is 1
2021-10-25 20:55:47.377 D/DBINFO: Zutaten is Flour ID is 3
2021-10-25 20:55:47.377 D/DBINFO: Zutaten is Eggs ID is 4
2021-10-25 20:55:47.377 D/DBINFO: Rezept is REZ2 Bild is 1 ID is 2
2021-10-25 20:55:47.425 D/STAGE2: data after adding R-With-Z
2021-10-25 20:55:47.428 D/DBINFO: Rezept is REZ1 Bild is 1 ID is 1
2021-10-25 20:55:47.428 D/DBINFO: Zutaten is Milk ID is 1
2021-10-25 20:55:47.428 D/DBINFO: Zutaten is Flour ID is 3
2021-10-25 20:55:47.428 D/DBINFO: Zutaten is Eggs ID is 4
2021-10-25 20:55:47.428 D/DBINFO: Rezept is REZ2 Bild is 1 ID is 2
2021-10-25 20:55:47.428 D/DBINFO: Rezept is REZ3 Bild is 1 ID is 3
2021-10-25 20:55:47.428 D/DBINFO: Zutaten is salt ID is 5
2021-10-25 20:55:47.429 D/DBINFO: Zutaten is nutmeg ID is 6
2021-10-25 20:55:47.429 D/DBINFO: Zutaten is cornflour ID is 7
2021-10-25 20:55:47.429 D/DBINFO: Zutaten is corriander ID is 8
2021-10-25 20:55:47.429 D/DBINFO: Zutaten is Milk ID is 1
2021-10-25 20:55:47.429 D/DBINFO: Zutaten is Sugar ID is 2
2021-10-25 20:55:47.429 D/DBINFO: Zutaten is More Sugar ID is 9
2021-10-25 20:55:47.459 D/STAGE3: data after adding R-With-Z
2021-10-25 20:55:47.461 D/DBINFO: Rezept is REZ1 Bild is 1 ID is 1
2021-10-25 20:55:47.461 D/DBINFO: Zutaten is Milk ID is 1
2021-10-25 20:55:47.461 D/DBINFO: Zutaten is Flour ID is 3
2021-10-25 20:55:47.461 D/DBINFO: Zutaten is Eggs ID is 4
2021-10-25 20:55:47.461 D/DBINFO: Rezept is REZ2 Bild is 1 ID is 2
2021-10-25 20:55:47.461 D/DBINFO: Rezept is REZ3 Bild is 1 ID is 3
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is salt ID is 5
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is nutmeg ID is 6
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is cornflour ID is 7
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is corriander ID is 8
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is Milk ID is 1
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is Sugar ID is 2
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is More Sugar ID is 9
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is leek ID is 10
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is apple ID is 11
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is banana ID is 12
2021-10-25 20:55:47.462 D/DBINFO: Zutaten is pineapple ID is 13
建议
- RefZutatRezept 的 rezeptid 列上的索引 table。
- rezname 和 zutname 的唯一索引(目前您可以有 Milk 的 id 为 1 和 Milk 的 id 为 2 等等)。
- RefZutatRezept 上的外键约束 table 以强制执行参照完整性并级联删除和更新
Cascade 会将父项的相关更改应用到子项。
例如如果您删除了 Zutaten,那么 RefZutatRezept 中引用 Zutaten 的所有行都将自动删除
- 没有你可能会遇到问题,因为会有对不存在的 Zutaten 的引用。同样对于任何 Rezepte 的
onUpdate 操作并不那么重要,因为您不太可能更改 zutatid 或 rezptid。
所以你不妨考虑以下几点:-
@Entity(
tableName ="zutaten_table",
indices = [ Index(value = ["zutname"],unique = true)]
)
data class ZutatenData(
@PrimaryKey(autoGenerate = true) val zutatid : Int,
@ColumnInfo(name = "zutname") var zutname : String
//and some more columns
)
和
@Entity(tableName = "rezepte_table",
indices = [Index(value = ["rezname"],unique = true)]
)
data class RezepteData(
@PrimaryKey(autoGenerate = true) val rezeptid : Int,
@ColumnInfo(name = "rezname") var rezname : String,
@ColumnInfo(name = "bild") var bild:Int
)
和
@Entity(
primaryKeys = ["zutatid", "rezeptid"],
indices = [Index(value = ["rezeptid"])],
foreignKeys = [
ForeignKey(
entity = ZutatenData::class,
parentColumns = ["zutatid"],
childColumns = ["zutatid"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
),
ForeignKey(
entity = RezepteData::class,
parentColumns = ["rezeptid"],
childColumns = ["rezeptid"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.CASCADE
)
]
)
data class RefZutatRezept(
val zutatid: Int,
val rezeptid: Int
)