Android Room Embedded Relation 忽略 where 条件

Android Room Embedded Relation ignores where condition

我有一组有点复杂的带有@Relations 的table。这是我的第一个 table:

@Entity(tableName = "commodity")
class Commodity(@NotNull @PrimaryKey val id : String,
            val __typename : String,
            val name : String,
            val isometricDrawingUrl : String,
            val startDate : OffsetDateTime?,
            val endDate : OffsetDateTime?,
            val numberOfBlocks : Int,
            val numberOfRejects : Int)

第二个table:

@Entity(tableName = "milestone")
class Milestone(@NotNull @PrimaryKey val id : String,
            val commodityId : String,
            val __typename: String,
            val name: String,
            val earnableHours: Double,
            val currentStatusI18n: MilestoneStatus,
            val approved: OffsetDateTime?,
            val claimed: OffsetDateTime?
)

这是我的第一个@Embedded 符号:

class CommoditiesAndAllMilestones {

    @Embedded
    var commodity: Commodity? = null

    @Relation(
    parentColumn = "id",
    entityColumn = "commodityId",
    entity = Milestone::class
    )
    var milestones: List<MileStonesAndAllBlocks> = ArrayList()

    override fun equals(other: Any?): Boolean {
        return this === other
    }

}

第二个嵌入关系:

class MileStonesAndAllBlocks {

    @Embedded
    var milestone: Milestone? = null

    @Relation(
        entity = Block::class,
        parentColumn = "id",
        entityColumn = "milestoneId"
    )
    var blocks: List<Block> = ArrayList()

    @Relation(
        parentColumn = "id",
        entity = ApprovedBy::class,
        entityColumn = "milestoneId"
    )
    var approvedBy : List<ApprovedBy> = ArrayList()

    @Relation(
       parentColumn = "id",
       entity = ClaimedBy::class,
       entityColumn = "milestoneId"
    )
    var claimedBy : List<ClaimedBy> = ArrayList()

}

问题是我不能做一个简单的查询:

@Transaction
@Query("Select * from commodity WHERE name LIKE '%' || :typeName || '%' AND numberOfBlocks > 0")
fun getCommodities(typeName: String) : DataSource.Factory<Int,CommoditiesAndAllMilestones>

运行 此查询 returns table 中的所有值。它似乎忽略了 where 子句,尽管嵌入式关系有效 - 列表结构就像我所期望的那样。如果您使用 Room Relations,您可以在 where 子句中设置条件吗?

编辑

我已经创建了这个测试文件,显然您可以使用 Where 子句进行查询。

@Query("Select * from commodity WHERE name LIKE '%' || :typeName || '%' AND numberOfBlocks > 0")
fun getCommoditiesBasic(typeName: String) : List<CommoditiesAndAllMilestones>

@RunWith(AndroidJUnit4::class)
class ListCategoryDaoTest  {

@get:Rule
val rule: TestRule = InstantTaskExecutorRule()

private lateinit var database: CommoditiesDatabase
private lateinit var commodityDao: CommodityDao
private lateinit var approvedBy : ApprovedByDao
private lateinit var claimedByDao : ClaimedByDao
private lateinit var blockDao : BlockDao
private lateinit var milestoneDao : MilestoneDao
private val workPackageId : String = UUID.randomUUID().toString()
private var workPackage : WorkPackageByIdQuery.WorkPackage? = null
private lateinit var commodityRepository : CommodityRepository
private val mainThreadSurrogate = newSingleThreadContext("UI thread")

@Before
fun setup() {
    database = CommoditiesDatabase.newTestInstance(InstrumentationRegistry.getInstrumentation().context)
    commodityDao = database.commodityDao()
    approvedBy = database.approvedByDao()
    claimedByDao = database.claimedByDao()
    blockDao = database.blockDao()
    milestoneDao = database.milestoneDao()
    commodityRepository = CommodityRepository(approvedBy,blockDao,claimedByDao,commodityDao,milestoneDao)

    Dispatchers.setMain(mainThreadSurrogate)

}

@Test
fun addAndRetrieveVideoDataAndBookmarks() {

    runBlocking {
        launch(Dispatchers.Unconfined) {
            workPackage = workPackage(workPackageId).response
            workPackage.let {
                if (it != null) {
                    for (commodity in it.commodities()) {
                        commodityRepository.insertCommodity(commodity)
                    }
                }
            }
            val commodityData = commodityDao.getCommoditiesBasic(CommodityType.SPOOL.rawValue())
            for (i in commodityData.indices) {
                val commodity = commodityData[i].commodity
                if (commodity != null) {
                    Assert.assertTrue(commodity.numberOfBlocks > 0)
                    Assert.assertTrue(commodity.name == CommodityType.SPOOL.rawValue())

                }
            }


        }

    }

}

@After
fun tearDown() {
    database.close()
    Dispatchers.resetMain() // reset main dispatcher to the original Main dispatcher
    mainThreadSurrogate.close()

}


fun workPackage(
    workPackageId: String
): BpsResponse<WorkPackageByIdQuery.WorkPackage, PipefighterError>
    {

        var totalBlocks = 0
        val workPackage: WorkPackageByIdQuery.WorkPackage
        val commodities = mutableListOf<WorkPackageByIdQuery.Commodity>()
        val crew = mutableListOf<WorkPackageByIdQuery.Crew>()


        val commodityNames = listOf(CommodityType.SPOOL, CommodityType.WELD, CommodityType.BULKPIPE)
        val milestoneTypes = listOf("Staged", "ELT", "Weldout", "Supports", "Punchlist")

        for (name in commodityNames) {
            val preIndex = commodityNames.indexOf(name) + 1
            // Create Commodities
            for (id in 1..8) {

                val milestones = mutableListOf<WorkPackageByIdQuery.Milestone>()
                for (index in 0 until 5) {

                    val status: MilestoneStatus
                    val blocks = if (id % 2 == 0 && milestoneTypes[index] == "Staged") {
                        totalBlocks++
                        status = MilestoneStatus.`$UNKNOWN`
                        listOf(WorkPackageByIdQuery.Block("Block", UUID.randomUUID().toString()))
                    } else {
                        status = MilestoneStatus.values()[Random.nextInt(4)]
                        listOf()
                    }

                    WorkPackageByIdQuery.Milestone(
                        "Milestone",
                        milestoneTypes[index],
                        Random.nextInt(101).toDouble(),
                        status,
                        if (status == MilestoneStatus.APPROVED) OffsetDateTime.now() else null,
                        if (status == MilestoneStatus.APPROVED) WorkPackageByIdQuery.ApprovedBy("ApprovedBy", UUID.randomUUID().toString(), "Mock Approver") else null,
                        if (status != MilestoneStatus.UNCLAIMED) OffsetDateTime.now() else null,
                        if (status != MilestoneStatus.UNCLAIMED) WorkPackageByIdQuery.ClaimedBy("ClaimedBy", UUID.randomUUID().toString(), "Mock Claimer") else null,
                        blocks
                    ).also {
                        milestones.add(it)
                    }
                }

                WorkPackageByIdQuery.Commodity(
                    "Commodity",
                    "1FX20000X-5D-130045-${String.format("%02d", preIndex)}-${String.format("%02d", id)}",
                    name.rawValue(),
                    "https://file-examples.com/wp-content/uploads/2017/10/file-sample_150kB.pdf",
                    OffsetDateTime.now().plusDays(id - 1L),
                    OffsetDateTime.now().plusDays(id + 1L),
                    milestones
                ).also {
                    commodities.add(it)
                }
            }
        }

        // Create Crew
        for (id in 1..3) {
            WorkPackageByIdQuery.Crew(
                PipefighterClient.TYPE_CREW,
                UUID.randomUUID().toString(),
                "# $id Mock Tester"
            ).also {
                crew.add(it)
            }
        }

        WorkPackageByIdQuery.WorkPackage(
            PipefighterClient.TYPE_WORKPACKAGE,
            workPackageId,
            OffsetDateTime.now(),
            "https://file-examples.com/wp-content/uploads/2017/10/file-sample_150kB.pdf",
            OffsetDateTime.now(),
            OffsetDateTime.now().plusMonths(1),
            totalBlocks,
            0,
            commodityNames,
            commodities,
            crew
        ).also {
            workPackage = it
        }

        return BpsResponse(workPackage, null)
    }


}

Can you do conditions in where clauses if you are using Room Relations?

是的。

根据您的代码考虑以下内容:-

加载一些测试数据的代码:-

fun addSomeTestingData() {
    mAllDao.deleteAllBlocks()
    mAllDao.deleteAllClaimedBys()
    mAllDao.deleteAllApprovedBys()
    mAllDao.deleteAllMileStones()
    mAllDao.deleteAllCommodities()
    val ab = ApprovedBy()
    ab.approvedBy = "Fred"
    ab.milestoneId = "M2"
    mAllDao.insertOneApprovedByRow(ab)
    ab.approvedBy = "Mary"
    ab.milestoneId = "M1"
    mAllDao.insertOneApprovedByRow(ab)
    ab.approvedBy = "Jane"
    ab.milestoneId = "M2"
    mAllDao.insertOneApprovedByRow(ab)

    val cb = ClaimedBy()
    cb.claimedBy = "Susan"
    cb.milestoneId = "M1"
    mAllDao.insertOneClaimedByRow(cb)
    cb.claimedBy = "Helen"
    cb.milestoneId = "M2"
    mAllDao.insertOneClaimedByRow(cb)
    cb.claimedBy = "Tom"
    cb.milestoneId = "M1"
    mAllDao.insertOneClaimedByRow(cb)

    val c1 = Commodity("C1","Typ1","C1T1","blah","2019-01-01","2019-03-01",10,0)
    mAllDao.insertOneCommodityRow(c1)
    val c2 = Commodity("C2","Typ2","C2T2","more blah","2019-01-20","2019-01-31",5,1)
    mAllDao.insertOneCommodityRow(c2)
    val c3 = Commodity("C3","Typ1","C3T1","blah blah","2019-01-15","2019-02-16",7,2)
    mAllDao.insertOneCommodityRow(c3)

    val m1 = Milestone("M1","C1","Typ1","M1C1T1",75.5,"INPROGRESS","2019-01-17","2")
    mAllDao.insertOneMilestoneRow(m1)
    val m2 = Milestone("M2","C2","Typ1","M2C3T1",35.6,"READY","2019-01-15","1")
    mAllDao.insertOneMilestoneRow(m2)

    val blk = Block()
    blk.block = "M1B1"
    blk.milestoneId = "M1"
    mAllDao.insertOneBlockRow(blk)
    blk.block = "M1B2"
    blk.milestoneId = "M1"
    mAllDao.insertOneBlockRow(blk)
    blk.block = "M1B3"
    blk.milestoneId = "M1"
    mAllDao.insertOneBlockRow(blk)
    blk.block = "M2B1"
    blk.milestoneId = "M2"
    mAllDao.insertOneBlockRow(blk)
    blk.block = "M2B2"
    blk.milestoneId = "M2"

}
  • 请注意,为方便起见,简化了实体,例如字符串而不是其他对象,例如 MilestoneStatus

详细结果代码:-

fun logCommoditiesAndMilstones(cmlist: List<CommoditiesAndAllMilestones>) {
    for (cm: CommoditiesAndAllMilestones in cmlist) {
        Log.d("CAMINFO","CommodityID is " + cm.commodity?.id)
        for (mab: MileStonesAndAllBlocks in cm.milestones) {
            if (mab.milestone != null) {
                Log.d("CAMINFO","\n\tMilestone is " + mab.milestone?.id)
            }
            for (b: Block in mab.blocks) {
                Log.d("CAMINFO","Block ID is " + b.id + " value is " + b.block)
            }
            for (ab: ApprovedBy in mab.approvedBy) {
                Log.d("CAMINFO","APPRV BY " + ab.approvedBy)
            }
            for (cb: ClaimedBy in mab.claimedBy) {
                Log.d("CAMINFO","CLMD BY " + cb.claimedBy)
            }
        }
    }
}

AllDao 提取物

@Transaction
@Query("Select * from commodity WHERE name LIKE '%' || :typeName || '%' AND numberOfBlocks > 0")
fun getCommodities(typeName: String) : List<CommoditiesAndAllMilestones>

主要测试代码:-

    mAppDatabase = Room.databaseBuilder(this,AppDatabase::class.java,"commodities")
        .allowMainThreadQueries()
        .build()
    mAllDao = mAppDatabase.allDao()

    addSomeTestingData()
    var cmlist: List<CommoditiesAndAllMilestones> = mAllDao.getCommodities("C2") //<<<<<<<<< 1st Query
    logCommoditiesAndMilstones(cmlist)
    cmlist = mAllDao.getCommodities("C1") //<<<<<<<<<< 2nd Query
    logCommoditiesAndMilstones(cmlist)

结果(日志)

2019-10-23 14:28:34.709 D/CAMINFO: CommodityID is C2
2019-10-23 14:28:34.709 D/CAMINFO:  Milestone is M2
2019-10-23 14:28:34.709 D/CAMINFO: Block ID is 24 value is M2B1
2019-10-23 14:28:34.709 D/CAMINFO: APPRV BY Fred
2019-10-23 14:28:34.709 D/CAMINFO: APPRV BY Jane
2019-10-23 14:28:34.709 D/CAMINFO: CLMD BY Helen


2019-10-23 14:28:34.716 D/CAMINFO: CommodityID is C1
2019-10-23 14:28:34.716 D/CAMINFO:  Milestone is M1
2019-10-23 14:28:34.717 D/CAMINFO: Block ID is 21 value is M1B1
2019-10-23 14:28:34.717 D/CAMINFO: Block ID is 22 value is M1B2
2019-10-23 14:28:34.717 D/CAMINFO: Block ID is 23 value is M1B3
2019-10-23 14:28:34.717 D/CAMINFO: APPRV BY Mary
2019-10-23 14:28:34.717 D/CAMINFO: CLMD BY Susan
2019-10-23 14:28:34.717 D/CAMINFO: CLMD BY Tom