Room 上的嵌套嵌入式列表
Nested embedded lists on Room
我正在尝试使用空间 Something
类型的对象,其中包含一个 Stuff
列表,并且该列表的每个项目都包含另一个 Things
列表。
data class rootWrapper(
@Embeded
var somethingEntity: SomethingEntity
@Relation(
parentColumn = "id",
entityColumn = "idSomething",
associatedBy = Junction(SomethingWithStuffEntity::class)
)
var listOfStuff: MutableList<StuffWithThingsInsideWrapper>
)
data class StuffWithThingsInsideWrapper(
@Embeded
var stuff: stuffEntity
@Relation(
parentColumn = "id",
entityColumn = "idStuff",
associatedBy = Junction(StuffWithThingsEntity::class)
)
var listOfThings: MutableList<ThingsEntity>
)
问题是因为 StuffWithThingsInsided 没有 ID。我得到一个 Cannot find the parent entity column id in com.test.room.entity.StuffWithThingsWapper
。我不知道我想要达到的目标是否有可能,我在那里找不到任何例子。有什么建议吗?
I don't know if what I'm trying to achieve is even possible, I couldn't find any example out there. Any suggestion?
有可能。或许考虑以下。
当您 associateBy
时,您是在说您正在使用关联 table 访问父项和子项。
这样的 table 将至少有两列,在您的情况下,一列引用 stuffEntity,另一列引用相关的 ThingEntity。
因此,@Relation
和 associateBy
涉及 4 列:-
- 父级,即
@Embedded
- 子(ren)即
@Relation
- 关联 table 中引用
@Embedded
的列
- 关联 table 中引用
@Relation
的列
前两个根据@Relation 的父参数和实体参数,后两个根据'Junction'。
此外,当包含 hierarchy/levels 时,您遇到的情况更复杂,即变量匹配的列需要从属的 parent 实体,即不在下属。您需要将实体 class 指定为各自的实体,而不是被提取的 POJO 的 class。
所以你可以有类似的东西:-
data class StuffWithThingsInsideWrapper(
@Embedded
var stuff: StuffEntity,
@Relation(
entity = ThingsEntity::class,
parentColumn = "id",
entityColumn = "id",
associateBy = (
Junction(
value = StuffWithThingsEntity::class,
parentColumn = "idStuff",
entityColumn = "idThings"
)
)
)
var listOfThings: List<ThingsEntity>
)
和:-
data class RootWrapper(
@Embedded
var somethingEntity: SomethingEntity,
@Relation(
entity = StuffEntity::class, //<<<<< The entity behind a Something With Stuff
parentColumn = "id",
entityColumn = "id",
associateBy = (
Junction(
SomethingWithStuffEntity::class,
parentColumn = "idSomething",
entityColumn = "idStuff"
)
)
)
var listOfStuff: List<StuffWithThingsInsideWrapper>
)
- 注意 由于未包含基础实体,因此已猜测列名。
工作Example/Demo
除了上述之外,还使用了以下 classes :-
事物
@Entity
data class ThingsEntity(
@PrimaryKey
var id: Long? = null,
var name: String
)
东西
@Entity
data class StuffEntity(
@PrimaryKey
var id: Long? = null,
var name: String
)
某事
@Entity
data class SomethingEntity(
@PrimaryKey
var id: Long? = null,
var name: String
)
StuffWithThings
@Entity(
primaryKeys = ["idStuff","idThings"],
foreignKeys = [
ForeignKey(
entity = StuffEntity::class,
parentColumns = ["id"],
childColumns = ["idStuff"]
), ForeignKey(
entity = ThingsEntity::class,
parentColumns = ["id"],
childColumns = ["idThings"]
)
]
)
data class StuffWithThingsEntity(
var idStuff: Long,
@ColumnInfo(index = true)
var idThings: Long
)
- 外键是可选的,它们强制引用完整性
SomethingWithStuffEntity
@Entity(
primaryKeys = ["idSomething","idStuff"],
foreignKeys = [
ForeignKey(
entity = SomethingEntity::class,
parentColumns = ["id"],
childColumns = ["idSomething"]
), ForeignKey(
entity = StuffEntity::class,
parentColumns = ["id"],
childColumns = ["idStuff"])
]
)
data class SomethingWithStuffEntity(
var idSomething: Long,
@ColumnInfo(index = true)
var idStuff: Long
)
AllDao
@Dao
interface AllDao {
@Insert
fun insert(thingsEntity: ThingsEntity): Long
@Insert
fun insert(stuffEntity: StuffEntity): Long
@Insert
fun insert(somethingEntity: SomethingEntity): Long
@Insert
fun insert(stuffWithThingsEntity: StuffWithThingsEntity): Long
@Insert
fun insert(somethingWithStuffEntity: SomethingWithStuffEntity)
@Query("SELECT * FROM somethingentity")
fun getRootWrapperList(): List<RootWrapper>
}
数据库
@Database(entities = [ThingsEntity::class,StuffEntity::class,SomethingEntity::class,StuffWithThingsEntity::class,SomethingWithStuffEntity::class], version = 1)
abstract class TheDatabase: RoomDatabase() {
abstract fun getAllDao(): AllDao
companion object {
private var instance: TheDatabase? = null
fun getInstance(context: Context): TheDatabase {
if (instance == null) {
instance = Room.databaseBuilder(
context,
TheDatabase::class.java,
"thedatabase.db"
)
.allowMainThreadQueries()
.build()
}
return instance as TheDatabase
}
}
}
- for brevity/convenience
.allowMainThreadQueries
已被使用。
最后把它们放在一起 activity :-
class MainActivity : AppCompatActivity() {
lateinit var db: TheDatabase
lateinit var dao: AllDao
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db = TheDatabase.getInstance(this)
dao = db.getAllDao()
val thing1Id = dao.insert(ThingsEntity(name = "Thing1"))
val thing2Id = dao.insert(ThingsEntity(name = "Thing2"))
val thing3Id = dao.insert(ThingsEntity(name = "Thing3"))
val stuff1Id = dao.insert(StuffEntity(name = "Stuff1"))
val stuff2Id = dao.insert(StuffEntity(name = "Stuff2"))
val something1Id = dao.insert(SomethingEntity(name = "Something1"))
val something2Id = dao.insert(SomethingEntity(name = "Something2"))
val something3Id = dao.insert(SomethingEntity(name = "Something3"))
dao.insert(StuffWithThingsEntity(stuff1Id,thing1Id))
dao.insert(StuffWithThingsEntity(stuff1Id,thing2Id))
dao.insert(StuffWithThingsEntity(stuff1Id,thing3Id))
dao.insert(StuffWithThingsEntity(stuff2Id,thing3Id))
dao.insert(StuffWithThingsEntity(stuff2Id,thing2Id))
dao.insert(SomethingWithStuffEntity(something1Id,stuff1Id))
dao.insert(SomethingWithStuffEntity(something1Id,stuff2Id))
dao.insert(SomethingWithStuffEntity(something2Id,stuff2Id))
for(rw: RootWrapper in dao.getRootWrapperList()) {
Log.d("RWINFO","Something is ${rw.somethingEntity.name}")
for (swt: StuffWithThingsInsideWrapper in rw.listOfStuff) {
Log.d("RWINFO","\tStuff is ${swt.stuff.name}")
for (t: ThingsEntity in swt.listOfThings) {
Log.d("RWINFO","\t\tThings is ${t.name}")
}
}
}
}
}
运行上面(第一次)那么输出到日志的结果是:-
2021-11-25 07:04:58.828 D/RWINFO: Something is Something1
2021-11-25 07:04:58.828 D/RWINFO: Stuff is Stuff1
2021-11-25 07:04:58.828 D/RWINFO: Things is Thing1
2021-11-25 07:04:58.828 D/RWINFO: Things is Thing2
2021-11-25 07:04:58.828 D/RWINFO: Things is Thing3
2021-11-25 07:04:58.828 D/RWINFO: Stuff is Stuff2
2021-11-25 07:04:58.828 D/RWINFO: Things is Thing2
2021-11-25 07:04:58.828 D/RWINFO: Things is Thing3
2021-11-25 07:04:58.828 D/RWINFO: Something is Something2
2021-11-25 07:04:58.828 D/RWINFO: Stuff is Stuff2
2021-11-25 07:04:58.829 D/RWINFO: Things is Thing2
2021-11-25 07:04:58.829 D/RWINFO: Things is Thing3
2021-11-25 07:04:58.829 D/RWINFO: Something is Something3
我正在尝试使用空间 Something
类型的对象,其中包含一个 Stuff
列表,并且该列表的每个项目都包含另一个 Things
列表。
data class rootWrapper(
@Embeded
var somethingEntity: SomethingEntity
@Relation(
parentColumn = "id",
entityColumn = "idSomething",
associatedBy = Junction(SomethingWithStuffEntity::class)
)
var listOfStuff: MutableList<StuffWithThingsInsideWrapper>
)
data class StuffWithThingsInsideWrapper(
@Embeded
var stuff: stuffEntity
@Relation(
parentColumn = "id",
entityColumn = "idStuff",
associatedBy = Junction(StuffWithThingsEntity::class)
)
var listOfThings: MutableList<ThingsEntity>
)
问题是因为 StuffWithThingsInsided 没有 ID。我得到一个 Cannot find the parent entity column id in com.test.room.entity.StuffWithThingsWapper
。我不知道我想要达到的目标是否有可能,我在那里找不到任何例子。有什么建议吗?
I don't know if what I'm trying to achieve is even possible, I couldn't find any example out there. Any suggestion?
有可能。或许考虑以下。
当您 associateBy
时,您是在说您正在使用关联 table 访问父项和子项。
这样的 table 将至少有两列,在您的情况下,一列引用 stuffEntity,另一列引用相关的 ThingEntity。
因此,@Relation
和 associateBy
涉及 4 列:-
- 父级,即
@Embedded
- 子(ren)即
@Relation
- 关联 table 中引用
@Embedded
的列
- 关联 table 中引用
@Relation
的列
前两个根据@Relation 的父参数和实体参数,后两个根据'Junction'。
此外,当包含 hierarchy/levels 时,您遇到的情况更复杂,即变量匹配的列需要从属的 parent 实体,即不在下属。您需要将实体 class 指定为各自的实体,而不是被提取的 POJO 的 class。
所以你可以有类似的东西:-
data class StuffWithThingsInsideWrapper(
@Embedded
var stuff: StuffEntity,
@Relation(
entity = ThingsEntity::class,
parentColumn = "id",
entityColumn = "id",
associateBy = (
Junction(
value = StuffWithThingsEntity::class,
parentColumn = "idStuff",
entityColumn = "idThings"
)
)
)
var listOfThings: List<ThingsEntity>
)
和:-
data class RootWrapper(
@Embedded
var somethingEntity: SomethingEntity,
@Relation(
entity = StuffEntity::class, //<<<<< The entity behind a Something With Stuff
parentColumn = "id",
entityColumn = "id",
associateBy = (
Junction(
SomethingWithStuffEntity::class,
parentColumn = "idSomething",
entityColumn = "idStuff"
)
)
)
var listOfStuff: List<StuffWithThingsInsideWrapper>
)
- 注意 由于未包含基础实体,因此已猜测列名。
工作Example/Demo
除了上述之外,还使用了以下 classes :-
事物
@Entity
data class ThingsEntity(
@PrimaryKey
var id: Long? = null,
var name: String
)
东西
@Entity
data class StuffEntity(
@PrimaryKey
var id: Long? = null,
var name: String
)
某事
@Entity
data class SomethingEntity(
@PrimaryKey
var id: Long? = null,
var name: String
)
StuffWithThings
@Entity(
primaryKeys = ["idStuff","idThings"],
foreignKeys = [
ForeignKey(
entity = StuffEntity::class,
parentColumns = ["id"],
childColumns = ["idStuff"]
), ForeignKey(
entity = ThingsEntity::class,
parentColumns = ["id"],
childColumns = ["idThings"]
)
]
)
data class StuffWithThingsEntity(
var idStuff: Long,
@ColumnInfo(index = true)
var idThings: Long
)
- 外键是可选的,它们强制引用完整性
SomethingWithStuffEntity
@Entity(
primaryKeys = ["idSomething","idStuff"],
foreignKeys = [
ForeignKey(
entity = SomethingEntity::class,
parentColumns = ["id"],
childColumns = ["idSomething"]
), ForeignKey(
entity = StuffEntity::class,
parentColumns = ["id"],
childColumns = ["idStuff"])
]
)
data class SomethingWithStuffEntity(
var idSomething: Long,
@ColumnInfo(index = true)
var idStuff: Long
)
AllDao
@Dao
interface AllDao {
@Insert
fun insert(thingsEntity: ThingsEntity): Long
@Insert
fun insert(stuffEntity: StuffEntity): Long
@Insert
fun insert(somethingEntity: SomethingEntity): Long
@Insert
fun insert(stuffWithThingsEntity: StuffWithThingsEntity): Long
@Insert
fun insert(somethingWithStuffEntity: SomethingWithStuffEntity)
@Query("SELECT * FROM somethingentity")
fun getRootWrapperList(): List<RootWrapper>
}
数据库
@Database(entities = [ThingsEntity::class,StuffEntity::class,SomethingEntity::class,StuffWithThingsEntity::class,SomethingWithStuffEntity::class], version = 1)
abstract class TheDatabase: RoomDatabase() {
abstract fun getAllDao(): AllDao
companion object {
private var instance: TheDatabase? = null
fun getInstance(context: Context): TheDatabase {
if (instance == null) {
instance = Room.databaseBuilder(
context,
TheDatabase::class.java,
"thedatabase.db"
)
.allowMainThreadQueries()
.build()
}
return instance as TheDatabase
}
}
}
- for brevity/convenience
.allowMainThreadQueries
已被使用。
最后把它们放在一起 activity :-
class MainActivity : AppCompatActivity() {
lateinit var db: TheDatabase
lateinit var dao: AllDao
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db = TheDatabase.getInstance(this)
dao = db.getAllDao()
val thing1Id = dao.insert(ThingsEntity(name = "Thing1"))
val thing2Id = dao.insert(ThingsEntity(name = "Thing2"))
val thing3Id = dao.insert(ThingsEntity(name = "Thing3"))
val stuff1Id = dao.insert(StuffEntity(name = "Stuff1"))
val stuff2Id = dao.insert(StuffEntity(name = "Stuff2"))
val something1Id = dao.insert(SomethingEntity(name = "Something1"))
val something2Id = dao.insert(SomethingEntity(name = "Something2"))
val something3Id = dao.insert(SomethingEntity(name = "Something3"))
dao.insert(StuffWithThingsEntity(stuff1Id,thing1Id))
dao.insert(StuffWithThingsEntity(stuff1Id,thing2Id))
dao.insert(StuffWithThingsEntity(stuff1Id,thing3Id))
dao.insert(StuffWithThingsEntity(stuff2Id,thing3Id))
dao.insert(StuffWithThingsEntity(stuff2Id,thing2Id))
dao.insert(SomethingWithStuffEntity(something1Id,stuff1Id))
dao.insert(SomethingWithStuffEntity(something1Id,stuff2Id))
dao.insert(SomethingWithStuffEntity(something2Id,stuff2Id))
for(rw: RootWrapper in dao.getRootWrapperList()) {
Log.d("RWINFO","Something is ${rw.somethingEntity.name}")
for (swt: StuffWithThingsInsideWrapper in rw.listOfStuff) {
Log.d("RWINFO","\tStuff is ${swt.stuff.name}")
for (t: ThingsEntity in swt.listOfThings) {
Log.d("RWINFO","\t\tThings is ${t.name}")
}
}
}
}
}
运行上面(第一次)那么输出到日志的结果是:-
2021-11-25 07:04:58.828 D/RWINFO: Something is Something1
2021-11-25 07:04:58.828 D/RWINFO: Stuff is Stuff1
2021-11-25 07:04:58.828 D/RWINFO: Things is Thing1
2021-11-25 07:04:58.828 D/RWINFO: Things is Thing2
2021-11-25 07:04:58.828 D/RWINFO: Things is Thing3
2021-11-25 07:04:58.828 D/RWINFO: Stuff is Stuff2
2021-11-25 07:04:58.828 D/RWINFO: Things is Thing2
2021-11-25 07:04:58.828 D/RWINFO: Things is Thing3
2021-11-25 07:04:58.828 D/RWINFO: Something is Something2
2021-11-25 07:04:58.828 D/RWINFO: Stuff is Stuff2
2021-11-25 07:04:58.829 D/RWINFO: Things is Thing2
2021-11-25 07:04:58.829 D/RWINFO: Things is Thing3
2021-11-25 07:04:58.829 D/RWINFO: Something is Something3