android 如何使用sql从多对多关系表中获取所需对象?

okxuctiv  于 2023-01-11  发布在  Android
关注(0)|答案(1)|浏览(125)

我是Android初学者开发人员.我正在创建stationArrivalInformation应用程序.

@Entity
data class StationEntity(
    @PrimaryKey val stationName: String,
    val isFavorite: Boolean = false
)

@Entity
data class SubwayEntity(
    @PrimaryKey val subwayId: Int
)

@Entity(primaryKeys = ["stationName", "subwayId"])
data class StationSubwayCrossRefEntity(
    val stationName: String,
    val subwayId: Int
)

data class StationWithSubwaysEntity(
    @Embedded val station: StationEntity,
    @Relation(
        parentColumn = "stationName",
        entityColumn = "subwayId",
        entity = SubwayEntity::class,
        associateBy = Junction(
            StationSubwayCrossRefEntity::class,
            parentColumn = "stationName",
            entityColumn = "subwayId"
        )
    )
    val subways: List<SubwayEntity>
)

我构建了一个具有多对多关系的数据类。
1.测站表
enter image description here
2.地铁站台
enter image description here
3.对照表
enter image description here
如果你查看DAO文件:
x一个一个一个一个x一个一个二个x
1.在这里,stationDao. getStationWithSubways()的结果为null。2我参考了Android官方文档并应用了它,但我没有得到想要的结果。3为什么?
我期望在一个车站乘多条地铁
enter image description here

lmvvr0a8

lmvvr0a81#

〈参数的类型必须是一个用@Entity标注的类或者它的集合/数组。〉-〉如何解决?
房间没有任何关于类的东西(根据所示的类),因此它不知道如何处理:-

@Update
suspend fun updateStation(station: Station)

因为没有这样的@Entity注解类。
我认为解决办法是

@Update
suspend fun updateStation(station: StationEntity)
  • 如果这是你要更新的
    但是,由于构建日志中的警告,您可能会遇到问题:-
warning: The affinity of child column (subwayId : INTEGER) does not match the type affinity of the junction child column (subwayId : TEXT). - subways in a.a.so75052787kotlinroomretrievefrommanytomany.StationWithSubwaysEntity

您可能需要考虑的另一个警告是

warning: The column subwayId in the junction entity a.a.so75052787kotlinroomretrievefrommanytomany.StationSubwayCrossRefEntity is being used to resolve a relationship but it is not covered by any index. This might cause a full table scan when resolving the relationship, it is highly advised to create an index that covers this column. - subwayId in a.a.so75052787kotlinroomretrievefrommanytomany.StationSubwayCrossRefEntity

如果您使用以下选项,则两者都不会显示:-

@Entity(primaryKeys = ["stationName", "subwayId"])
data class StationSubwayCrossRefEntity(
    val stationName: String,
    //val subwayId: String
    @ColumnInfo(index = true)
    val subwayId: Int
)
  • 注解掉行,保留在中,仅显示之前/之后

然后,您必须用途:-

@Transaction
@Insert(onConflict = REPLACE)
fun insertStationSubways(stationSubways: List<Pair<StationEntity, SubwayEntity>>) {
    insertStations(stationSubways.map { it.first })
    insertSubways(stationSubways.map { it.second })
    insertCrossRef(stationSubways.map { (station, subway) ->
        StationSubwayCrossRefEntity(
            station.stationName, subway.subwayId
        )
    })
}
  • subway.subwayId而不是subway.subwayId.toString()

我希望在正常运营的情况下,
您会的。使用上面建议的更改(以及其他一些为了简洁/方便而在主线程上运行的更改),一个适当的@Database注解类如下:-

@Database(entities = [SubwayEntity::class,StationEntity::class, StationSubwayCrossRefEntity::class], version = 1, exportSchema = false)
abstract class TheDatabase: RoomDatabase() {
    abstract fun getStationDao(): StationDao

    companion object {
        private var instance: TheDatabase?=null
        fun getInstance(context: Context): TheDatabase {
            if (instance==null) {
                instance = Room.databaseBuilder(context,TheDatabase::class.java,"the_database.db")
                    .allowMainThreadQueries()
                    .build()
            }
            return instance as TheDatabase
        }
    }
}

以及活动中的以下内容,以证明:

class MainActivity : AppCompatActivity() {
    lateinit var dbInstance: TheDatabase
    lateinit var dao: StationDao
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        dbInstance = TheDatabase.getInstance(this)
        dao = dbInstance.getStationDao()

        dao.insertStationSubways(listOf(Pair(StationEntity("Station1",false),SubwayEntity(1))))
        dao.insertStationSubways(listOf(Pair(StationEntity("Station1",false),SubwayEntity(2))))
        dao.insertStationSubways(listOf(Pair(StationEntity("Station1",false),SubwayEntity(3))))
        dao.insertStationSubways(listOf(Pair(StationEntity("Station2",false),SubwayEntity(4))))
        dao.insertStationSubways(listOf(Pair(StationEntity("Station2",false),SubwayEntity(5))))
        dao.insertStationSubways(listOf(Pair(StationEntity("Station2",false),SubwayEntity(6))))

        val sb = StringBuilder()
        for (sws in dao.getStationWithSubways()) {
            sb.clear()
            for (subway in sws.subways) {
                sb.append("\n\tSubway is ${subway.subwayId}")
            }
            Log.d("DBINFO","Station is ${sws.station.stationName} it has ${sws.subways.size} subways. They are:-${sb}")
        }
    }
}

然后日志(第一次运行时)包括(如预期):-

D/DBINFO: Station is Station1 it has 3 subways. They are:-
        Subway is 1
        Subway is 2
        Subway is 3
D/DBINFO: Station is Station2 it has 3 subways. They are:-
        Subway is 4
        Subway is 5
        Subway is 6

相关问题