Android房间多对多关系返回多个结果

问题描述 投票:0回答:1

我在 android room 中定义了多对多关系。连接表包含附加属性,但我认为这在这里并不重要。

当我执行数据库查询时,我得到了很多结果。对于许多人来说,我的意思是由于错误的关系而导致我不期望的结果。显然,我的数据库中有一堆

Event
TrackedArtist
行。另外我还有一些
EventArtistCrossRef
行。可以说

  1. EventArtistCrossRef(事件Id = 1,艺术家Id = 1)
  2. EventArtistCrossRef(事件Id = 1,艺术家Id = 2)
  3. EventArtistCrossRef(事件Id = 2,艺术家Id = 1)
  4. EventArtistCrossRef(事件Id = 2,艺术家Id = 3)
  5. EventArtistCrossRef(事件Id = 2,艺术家Id = 4)

现在当我拨打

getAllEventsWithEventsAndArtists()
时,我得到两个结果。一种根据 id 1 的事件,另一种根据 id 2 的事件。
event
trackedArtists
是正确的。但是
artistsAtEvent
包含“错误”条目。在 id 为 2 的事件示例中,我想要获取行 3、4 和 5,但我还获取行 2

我需要向 @Relation 或 @Query 添加一些内容吗?或者我是否必须编写一个自定义@Query,因为房间不适合这个用例?

这是我的代码:

@Entity(tableName = "event_table")
data class Event(

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo("event_id")
    var eventId: Long = 0L,

    @ColumnInfo("name")
    var name: String = "",

    // Other attributes ...
)
@Entity(tableName = "tracked_artist_table")
data class TrackedArtist(

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo("artist_id")
    var artistId: Long = 0L,

    @ColumnInfo(name = "name")
    var name: String = "",

    // other attributes ...
)
@Entity(
    primaryKeys = ["event_id", "artist_id"],
    foreignKeys = [
        ForeignKey(
            entity = Event::class,
            parentColumns = ["event_id"],
            childColumns = ["event_id"],
            onDelete = ForeignKey.CASCADE
        ),
        ForeignKey(
            entity = TrackedArtist::class,
            parentColumns = ["artist_id"],
            childColumns = ["artist_id"],
            onDelete = ForeignKey.CASCADE
        )
    ]
)
data class EventArtistCrossRef(
    @ColumnInfo("event_id", index = true)
    var eventId: Long,

    @ColumnInfo("artist_id", index = true)
    var artistId: Long,

    // the mentioned before other attributes on junction table
)
data class EventWithEventsAndArtists(
    @Embedded
    var event: Event,

    @Relation(
        parentColumn = "event_id",
        entityColumn = "artist_id",
        associateBy = Junction(EventArtistCrossRef::class)
    )
    val artists: List<TrackedArtist>,

    @Relation(
        parentColumn = "event_id",
        entityColumn = "artist_id",
        associateBy = Junction(
            value = EventArtistCrossRef::class,
            parentColumn = "event_id",
            entityColumn = "artist_id"
        )
    )
    var artistsAtEvent: List<EventArtistCrossRef>

)
@Dao
interface EventDao {
    @Transaction
    @Query("SELECT * from event_table ORDER BY lower(name) ASC")
    fun getAllEventsWithEventsAndArtists(): LiveData<List<EventWithEventsAndArtists>>

    // other queries ...
}

android many-to-many android-room
1个回答
0
投票

我认为您的问题是您告诉 Room 从 event_table 中选择事件,并将 eventartistcrossref 表与 event_table 作为连接点连接起来,然后再次连接 eventartistcrossref 表,因此排列大于预期。

使用您的代码和以下活动代码(注意

.allowMainThreadQueries
是为了简洁和方便而使用的)来模仿您正在做的事情,但始终使用唯一的 id(艺术家 id 为 10、20、30 和 40,而不是 1-4): -

lateinit var db: TheDatabase
lateinit var dao: EventDao
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    db = TheDatabase.getInstance(this)
    dao = db.getEventDao()

    dao.insert(Event(1,"Event1"))
    dao.insert(Event(2,"Event2"))
    dao.insert(TrackedArtist(10,"TA10"))
    dao.insert(TrackedArtist(20,"TA20"))
    dao.insert(TrackedArtist(30,"TA30"))
    dao.insert(TrackedArtist(40,"TA40"))

    dao.insert(EventArtistCrossRef(1,10))
    dao.insert(EventArtistCrossRef(1,20))

    dao.insert(EventArtistCrossRef(2,10))
    dao.insert(EventArtistCrossRef(2,30))
    dao.insert(EventArtistCrossRef(2,40))

    for(eweaa in dao.getAllEventsWithEventsAndArtists()) {
        val taoutput = StringBuilder()
        for (ta in eweaa.artists) {
            taoutput.append("\n\tNames is ${ta.name} artistId is ${ta.artistId}")
        }
        val aaeoutput = StringBuilder()
        for (aae in eweaa.artistsAtEvent) {
            aaeoutput.append("\n\tEventID=${aae.eventId} ArtistId=${aae.artistId}")
        }
        Log.d("DBINFO","Event Name is ${eweaa.event.name} Event ID is ${eweaa.event.eventId}" +
                ".\nThere are ${eweaa.artists.size} tacked artists; they are ${taoutput}" +
                ".\nThere are ${eweaa.artistsAtEvent.size} artistsAtEvents; they are ${aaeoutput}")
    }
}

结果是:-

D/DBINFO: Event Name is Event1 Event ID is 1.
    There are 2 tacked artists; they are 
        Names is TA10 artistId is 10
        Names is TA20 artistId is 20.
    There are 3 artistsAtEvents; they are 
        EventID=1 ArtistId=10
        EventID=2 ArtistId=10
        EventID=1 ArtistId=20
D/DBINFO: Event Name is Event2 Event ID is 2.
    There are 3 tacked artists; they are 
        Names is TA10 artistId is 10
        Names is TA30 artistId is 30
        Names is TA40 artistId is 40.
    There are 4 artistsAtEvents; they are 
        EventID=1 ArtistId=10
        EventID=2 ArtistId=10
        EventID=2 ArtistId=30
        EventID=2 ArtistId=40

即跟踪的艺术家符合预期,但由于使用交叉引用作为连接点的交叉引用的非常规(如果这是正确的词)连接产生了意想不到的结果(我相信,由于与交叉引用的艺术家两个事件).

很难准确理解你想要实现的目标。

© www.soinside.com 2019 - 2024. All rights reserved.