【问题标题】:Android Room doesn't allow me to do the one-to-N relationship multiple timesAndroid Room 不允许我多次建立一对 N 关系
【发布时间】:2021-08-27 12:31:18
【问题描述】:

我已经实现了一个数据库,其中我有两个一对多的关系,但似乎房间不允许这样做。是这样吗?

实体是:

@Entity(tableName = "arete_sheet")
data class EAreteSheet(
    @PrimaryKey val id: Long,
    @ColumnInfo(name = "sheet") val form: Sheets,
    @ColumnInfo(name = "version") val version: Int,
)

@Entity(tableName = "arete_sheet_paragraph")
data class EAreteSheetParagraph(
    @PrimaryKey val id: Long,
    @ColumnInfo(name = "arete_sheet_id") val sheet: Long,
    @ColumnInfo(name = "name") val name: String
)

@Entity(tableName = "arete_sheet_form")
data class EAreteSheetForm(
    @PrimaryKey val id: Long,
    @ColumnInfo(name = "arete_sheet_paragraph_id") val paragraph: Long,
    @ColumnInfo(name = "fieldType") val fieldType: FieldType,
    @ColumnInfo(name = "cell") val cell: String,
    @ColumnInfo(name = "label") val label: String
)

为了解决架构问题,我实现了这些连接类:

data class EAreteSheetWithParagraph(
    @Embedded val sheet: EAreteSheet,
    @Relation(
        parentColumn = "id",
        entityColumn = "arete_sheet_id"
    )
    val paragraph: List<EAreteSheetParagraphWithForm>
)
data class EAreteSheetParagraphWithForm(
    @Embedded val paragraph: EAreteSheetParagraph,
    @Relation(
        parentColumn = "id",
        entityColumn = "arete_sheet_paragraph_id"
    )
    val forms: List<EAreteSheetForm>
)

这是 DAO 实现:

  @Transaction
    @Query("SELECT * FROM arete_sheet")
    suspend fun getSheetWithParagraphsAndForms(): List<EAreteSheetWithParagraph>

这是他在构建阶段给我的错误:

app/build/generated/source/kapt/debug/it/ximplia/agri2000/model/db/dao/AreteSheetDAO_Impl.java:203: error: constructor EAreteSheetWithParagraph in class EAreteSheetWithParagraph cannot be applied to given types;
              _item = new EAreteSheetWithParagraph();
                      ^
  required: EAreteSheet,List<EAreteSheetParagraphWithForm>
  found: no arguments
  reason: actual and formal argument lists differ in length
app/build/generated/source/kapt/debug/it/ximplia/agri2000/model/db/dao/AreteSheetDAO_Impl.java:204: error: sheet has private access in EAreteSheetWithParagraph
              _item.sheet = _tmpSheet;

我认为 Room 不允许级联解决依赖关系,但我想知道是否有人成功,或者我在更改代码之前是否犯了错误。

【问题讨论】:

    标签: android sql kotlin android-room


    【解决方案1】:

    EAreteSheetWithParagraph 中,您指定了 EAreteSheetParagraphWithForm 的列表

    根据:-

    val paragraph: List<EAreteSheetParagraphWithForm>
    

    @Relation 将尝试根据 EAreteSheetParagraphWithForm 表单类确定列,该类不是实体。您应该更改 @Relation 以使用 entity 参数指定适当的实体(即 EAreteSheetParagraph)。

    所以 EAreteSheetWithParagraph 应该是这样的:-

    data class EAreteSheetWithParagraph(
        @Embedded val sheet: EAreteSheet,
        @Relation(
            entity = EAreteSheetParagraph::class,
            parentColumn = "id",
            entityColumn = "arete_sheet_id" 
        )
        val paragraph: List<EAreteSheetParagraphWithForm>
    )
    

    但是,我不相信您已经走到了这一步,因为这些消息似乎在抱怨具有表格类型的 sheet 变量(并且该变量是私有的)。

    如果不添加 entity= 参数,那么编译,如果达到那个阶段,将会失败:-

    > Task :app:kaptDebugKotlin FAILED
    error: The class must be either @Entity or @DatabaseView. - a.a.so68953488kotlinroommany1_n.EAreteSheetParagraphWithForm
    E:\AndroidStudioApps\SO68953488KotlinRoomMany1N\app\build\tmp\kapt3\stubs\debug\a\a\so68953488kotlinroommany1_n\EAreteSheetWithParagraph.java:12: error: Cannot find the child entity column `arete_sheet_id` in a.a.so68953488kotlinroommany1_n.EAreteSheetParagraphWithForm. Options: 
        private final java.util.List<a.a.so68953488kotlinroommany1_n.EAreteSheetParagraphWithForm> paragraph = null;
                                                                                                   ^
    The class must be either @Entity or @DatabaseView. - a.a.so68953488kotlinroommany1_n.EAreteSheetParagraphWithForm
    

    我认为 Room 不允许在级联中解决依赖关系,但我想知道是否有人成功,或者我在更改代码之前是否犯了错误。

    如上所述,我认为问题出在错误上:-

    概念证明

    根据您的代码,以下显示嵌套/多个 1-n 确实有效:-

    使用您的代码但进行以下更改(以避免问题并简化):-

    @Entity(tableName = "arete_sheet_form")
    data class EAreteSheetForm(
        @PrimaryKey val id: Long,
        @ColumnInfo(name = "arete_sheet_paragraph_id") val paragraph: Long,
        @ColumnInfo(name = "fieldType") val fieldType: /* FieldType */ String, // changed for convenience/brevity
        @ColumnInfo(name = "cell") val cell: String,
        @ColumnInfo(name = "label") val label: String
    )
    
    • fieldType 的类型从 FieldType 更改为 String,因此无需额外的类和类型转换器。

    @Entity(tableName = "arete_sheet")
    data class EAreteSheet(
        @PrimaryKey val id: Long,
        @ColumnInfo(name = "sheet") val form: /*Sheets*/ String, // changed for convenience/brevity
        @ColumnInfo(name = "version") val version: Int,
    )
    
    • 用字符串替换的表格类型

    EAreteSheetWithParagraph 同上

    EAreteSheetParagraphWithForm 改为

    data class EAreteSheetParagraphWithForm(
        @Embedded val paragraph: EAreteSheetParagraph,
        @Relation(
            parentColumn = "id",
            entityColumn = "arete_sheet_paragraph_id",
            entity = EAreteSheetForm::class
        )
        val forms: List<EAreteSheetForm>
    )
    
    • 即根据我的偏好添加了实体参数,以便始终对实体参数进行编码。

    使用AreteSheetDao :-

    @Dao
    abstract class AreteSheetDAO {
    
        @Insert
        abstract fun insert(eAreteSheet: EAreteSheet): Long
        @Insert
        abstract fun insert(eAreteSheetParagraph: EAreteSheetParagraph): Long
        @Insert
        abstract fun insert(eAreteSheetForm: EAreteSheetForm): Long
    
        @Transaction
        @Query("SELECT * FROM arete_sheet")
        abstract fun getSheetWithParagraphsAndForms(): List<EAreteSheetWithParagraph>
    
    }
    

    活动中的代码:-

    class MainActivity : AppCompatActivity() {
    
        lateinit var db: TheDatabase
        lateinit var dao: AreteSheetDAO
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            db = TheDatabase.getInstance(this)
            dao = db.getDao()
    
            var s1 = dao.insert(EAreteSheet(10,"Sheet1",1))
            var s2 = dao.insert(EAreteSheet(20,"Sheet2",1))
            var p1 = dao.insert(EAreteSheetParagraph(100,s1,"Para1 (Sheet1)"))
            var p2 = dao.insert(EAreteSheetParagraph(101,s1,"Para2 (Sheet1)"))
            var p3 = dao.insert(EAreteSheetParagraph(201,s2,"Para3 (Sheet2)"))
            var p4 = dao.insert(EAreteSheetParagraph(202,s2,"Para4 (Sheet2)"))
            var f1 = dao.insert(EAreteSheetForm(1000,p1,"typex","cellx","Form1"))
            var f2 = dao.insert(EAreteSheetForm(1001,p1,"typex","cellx","Form2"))
            var f3 = dao.insert(EAreteSheetForm(1002,p1,"typex","cellx","Form3"))
            var f4 = dao.insert(EAreteSheetForm(1010,p2,"typex","cellx","Form4"))
            var f5 = dao.insert(EAreteSheetForm(1011,p2,"typex","cellx","Form5"))
            var f6 = dao.insert(EAreteSheetForm(1020,p3,"typex","cellx","Form6"))
            val TAG = "ARETEINFO"
            for(sw: EAreteSheetWithParagraph in dao.getSheetWithParagraphsAndForms()) {
                Log.d(TAG,"Sheet ID is ${sw.sheet.id} Form is ${sw.sheet.form} Version is ${sw.sheet.version}" )
                for(pf: EAreteSheetParagraphWithForm in sw.paragraph) {
                    Log.d(TAG,"\tPara is ${pf.paragraph.name} etc")
                    for(f: EAreteSheetForm in pf.forms) {
                        Log.d(TAG,"\t\tForm is ${f.label}")
                    }
                }
            }
        }
    }
    

    可以看出,加载了一些数据,2张Sheets,每张有2个段落,然后4个表格分布不均匀(3到para1,2到para2,1到para3,0到para4)。

    然后提取数据(作为EAreteSheetWithParagraph的数组),遍历数组(遍历段落中的底层数组和表格)并输出到日志结果是:-

    D/ARETEINFO: Sheet ID is 10 Form is Sheet1 Version is 1
    D/ARETEINFO:    Para is Para1 (Sheet1) etc
    D/ARETEINFO:        Form is Form1
    D/ARETEINFO:        Form is Form2
    D/ARETEINFO:        Form is Form3
    D/ARETEINFO:    Para is Para2 (Sheet1) etc
    D/ARETEINFO:        Form is Form4
    D/ARETEINFO:        Form is Form5
    D/ARETEINFO: Sheet ID is 20 Form is Sheet2 Version is 1
    D/ARETEINFO:    Para is Para3 (Sheet2) etc
    D/ARETEINFO:        Form is Form6
    D/ARETEINFO:    Para is Para4 (Sheet2) etc
    

    【讨论】:

      猜你喜欢
      • 2022-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-27
      • 1970-01-01
      • 2018-06-23
      • 2018-07-04
      相关资源
      最近更新 更多