//下一步呢?
那将是最后一次.
第一
data class CWithD(
@Embedded
val c: C,
@Relation(....)
val listD: List<D>
)
然后
data class BWithCWithD(
@Embedded
val b: B,
@Relation(....)
val listCwithD: List<CWithD>
)
然后 finally
data class Full(
@Embdded
val a: A,
@Relation(....)
val listBWithCWithD: List<BWithCWithD>
)
Working DEMO个
考虑以下实体、POJO、@Dao
个带注释的接口和@Database
个带注释的抽象类:
@Entity
data class A(
@PrimaryKey
val id: Long?=null,
val AName: String=""
)
@Entity
data class B(
@PrimaryKey
val id: Long?=null,
val parentId: Long,
val BName: String=""
)
@Entity
data class C(
@PrimaryKey
val id: Long?=null,
val parentId: Long,
val CName: String=""
)
@Entity
data class D(
@PrimaryKey
val id: Long?=null,
val parentId: Long,
val DName: String
)
data class CWithD(
@Embedded
val c: C,
@Relation(entity = D::class, entityColumn = "parentId", parentColumn = "id")
val listD: List<D>
)
data class BWithCWithD(
@Embedded
val b: B,
@Relation(entity = C::class, entityColumn = "parentId", parentColumn = "id")
val listCWithD: List<CWithD>
)
data class Full(
@Embedded
val a: A,
@Relation(entity = B::class, entityColumn = "parentId", parentColumn = "id")
val listBWithCWithD: List<BWithCWithD>
)
@Dao
interface MyDAOs {
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(a: A): Long
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(b: B): Long
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(c: C): Long
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(d: D): Long
@Transaction
@Query("SELECT * FROM a")
fun getFull(): List<Full>
}
@Database(entities = [A::class,B::class,C::class,D::class], version = 1, exportSchema = false)
abstract class MyDatabase: RoomDatabase() {
abstract fun getMyDAOs(): MyDAOs
companion object {
private var instance: MyDatabase?=null
fun getInstance(context: Context): MyDatabase {
if (instance==null) {
instance=Room.databaseBuilder(context,MyDatabase::class.java,"my.db")
.allowMainThreadQueries()
.build()
}
return instance as MyDatabase
}
}
}
然后是以下活动代码:-
const val DB_VERSION = 1
class MainActivity : AppCompatActivity() {
lateinit var db: MyDatabase
lateinit var dao: MyDAOs
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db = MyDatabase.getInstance(this)
dao = db.getMyDAOs()
val AId = dao.insert(A(AName = "A1"))
val B1Id = dao.insert(B(parentId = AId, BName = "B1"))
val B2Id = dao.insert(B(parentId = AId, BName = "B2"))
val C1Id = dao.insert(C(parentId = B1Id, CName = "C1"))
val C2Id = dao.insert(C(parentId = B2Id, CName = "C2"))
val C3Id = dao.insert(C(parentId = B1Id, CName = "C3"))
val C4Id = dao.insert(C(parentId = B1Id, CName = "C4"))
dao.insert(D(parentId = C1Id, DName = "D1"))
dao.insert(D(parentId = C2Id, DName = "D2"))
dao.insert(D(parentId = C3Id, DName = "D3"))
dao.insert(D(parentId = C4Id, DName = "D4"))
dao.insert(D(parentId = C1Id, DName = "D5"))
dao.insert(D(parentId = C1Id, DName = "D6"))
for (a in dao.getFull()) {
val sb_blist = StringBuilder()
for (b in a.listBWithCWithD) {
val sb_clist = StringBuilder()
for (c in b.listCWithD) {
val sb_dlist = StringBuilder()
for (d in c.listD) {
sb_dlist.append("\n\t\t\tDNAME is ${d.DName} ID is ${d.id} PARENT is ${d.parentId}")
}
sb_clist.append("\n\t\tCNAME is ${c.c.CName} ID is ${c.c.id} PARENT is ${c.c.parentId}. It has ${c.listD.size} D's; They Are:-${sb_dlist}")
}
sb_blist.append("\n\tBNAME is ${b.b.BName} ID is ${b.b.id} PARENT is ${b.b.parentId}. It has ${b.listCWithD.size} C's; They are:-${sb_clist}")
}
Log.d("DBINFO","ANAME is ${a.a.AName} ID is ${a.a.id}. It has ${a.listBWithCWithD.size} B's; They are:-${sb_blist}")
}
}
}
即
- 1A被插入,它已经;
- 2个B类 children ;
- 第一个B有3个C子代,第二个有1个C子代
- 4个C中的每一个都有一个D子项,第一个D有另外2个子项
使用Full POJO(以及继承的列表)的日志(log)输出证实了这一点:-
D/DBINFO: ANAME is A1 ID is 1. It has 2 B's; They are:-
BNAME is B1 ID is 1 PARENT is 1. It has 3 C's; They are:-
CNAME is C1 ID is 1 PARENT is 1. It has 3 D's; They Are:-
DNAME is D1 ID is 1 PARENT is 1
DNAME is D5 ID is 5 PARENT is 1
DNAME is D6 ID is 6 PARENT is 1
CNAME is C3 ID is 3 PARENT is 1. It has 1 D's; They Are:-
DNAME is D3 ID is 3 PARENT is 3
CNAME is C4 ID is 4 PARENT is 1. It has 1 D's; They Are:-
DNAME is D4 ID is 4 PARENT is 4
BNAME is B2 ID is 2 PARENT is 1. It has 1 C's; They are:-
CNAME is C2 ID is 2 PARENT is 2. It has 1 D's; They Are:-
DNAME is D2 ID is 2 PARENT is 2
使用App判断和您引用的原始查询(调整以显示所有数据,并考虑到我省略了列名中的下划线),这表明:-
Additional re comment个
你说
试试看.如果我只使用"CWithD",它就会起作用.如果我添加"BWithCWithD",我得到错误:1.在CWithD中找不到子实体列Parent_id.2.[ksp]:类必须是@Entity或@DatabaseView.3.BWithCWithD:Entity和POJO必须有一个可用的公共构造函数.可以有一个空的构造函数,也可以有一个参数与字段匹配(按名称和类型)的构造函数.
我试过了,比如上面的演示.
您的问题是,您已经隐式或显式地给出了一个没有@Entity
个注释的类(并且是通过@Database
注释的Entities参数定义的).
更具体地说,使用entity
参数或缺少该参数来确定要查询的表(Room等效于联接).
如果你提供了entity = ?::class
个,那么?必须是用@Entity
和NOT注释为POJO的相关类.
if you have not specified a class via the entity
parameter, then the class associated with the variable will be considered the class. In the case that the @Relation
is for a POJO. 然后 Room assumes that the table name will be derived from the class.
如果显式或隐式类是POJO,则Room将发出Not an Entity类(基本上与DataView相同,因此消息也满足该场景).