我有一个基地.它有4张桌子.每个子元素都是彼此的父母. 我需要通过第一个(A)的ID获取所有其他内容,并同时删除所有内容.

A (id)
B(id, parentId) - (a.id = b.parentId)
C(id, parentId) (b.id = c.parentId
D(id, parentId) (c.id = d.parentId)

A -> list B -> list C -> list D

我用的是房间,我不明白如何创建这样一个普通的实体

在SQL中,如下所示:

SELECT  a._id, b._id, c._id, d._id from a 
LEFT JOIN  b on a._id = b.parent_id
LEFT JOIN  c on b._id = c.parent_id 
LEFT JOIN  d on c._id = d.parent_id 
WHERE a._id = 1


data class FullEntity(
    @Embedded
    val a: A,
    @Relation(parentColumn = "_id", entityColumn = "parent_id", entity = 
    B::class)
    val listB: List<B>

  // what next? 
)

推荐答案

//下一步呢?

那将是最后一次.

第一

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判断和您引用的原始查询(调整以显示所有数据,并考虑到我省略了列名中的下划线),这表明:-

enter image description here

Additional re comment

你说

试试看.如果我只使用"CWithD",它就会起作用.如果我添加"BWithCWithD",我得到错误:1.在CWithD中找不到子实体列Parent_id.2.[ksp]:类必须是@Entity或@DatabaseView.3.BWithCWithD:Entity和POJO必须有一个可用的公共构造函数.可以有一个空的构造函数,也可以有一个参数与字段匹配(按名称和类型)的构造函数.

我试过了,比如上面的演示.

您的问题是,您已经隐式或显式地给出了一个没有@Entity个注释的类(并且是通过@Database注释的Entities参数定义的).

更具体地说,使用entity参数或缺少该参数来确定要查询的表(Room等效于联接).

如果你提供了entity = ?::class个,那么?必须是用@EntityNOT注释为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相同,因此消息也满足该场景).

Sql相关问答推荐

如何查询一个名称是根据PL/pgSQL函数结果构建的表?

跨多列的PostgreSQL非不同对

GROUP BY与多个嵌套查询T—SQL

使用来自不同深度的嵌套组的值执行计算的干净方法?

为什么在postgres中,横向连接比相关子查询快?

如何根据给定条件PostgreSQL迭代减少组中的行数

对列进行排序后,基于两列删除重复行

关于Postgres横向联接的谓词

无法将发票与产品价格相关联

在迁移到.NET8后,使用Array.Containers的F#查询表达式失败

SQL中相同表内的VLOOKUP等价

使用 union 的有序结果获取行数

返回给定日期后的第 4 个工作日(不包括公众假期)

SQL 搜索 - 获取最大值日期的奇怪行为

SQL 中的第一个值和倒数第二个值

删除重复记录但保留最新的SQL查询

一次 Select 语句中按组累计的SQL累计数

连续期间的缺口

在sql server中创建唯一标识符列

为什么这是 AND,OR with NULL 的真值表?