所有的 _id 列都有相同的索引。
这里有什么解决方法吗?
可以使用唯一的列名,例如。
@Entity
data class User(@PrimaryKey(autoGenerate = true) val userid: Long = 0, val name: String)
@Entity
data class Book(@PrimaryKey(autoGenerate = true) valbookid: Long = 0, val bookName: String, val useridmap: Long)
或者
@Entity
data class User(@PrimaryKey(autoGenerate = true) @ColumnInfo(name="userid")val _id: Long = 0, val name: String)
@Entity
data class Book(@PrimaryKey(autoGenerate = true) @ColumnInfo(name="bookid")val _id: Long = 0, val bookName: String, val @ColumnInfo(name="userid_map")userId: Long)
否则,正如您可能已经注意到的那样,Room使用具有重复名称的最后找到的列的值,并且用户的_id是书籍_id列的值。
使用上述方法并使用以下数据进行复制:
db = TheDatabase.getInstance(this)
dao = db.getAllDao()
var currentUserId = dao.insert(User(name = "Eugene"))
dao.insert(Book(bookName = "Eugene's book #1", useridmap = currentUserId))
dao.insert(Book(bookName = "Eugene's book #2", useridmap = currentUserId))
dao.insert(Book(bookName = "Eugene's book #3", useridmap = currentUserId))
currentUserId = dao.insert(User(name = "notEugene"))
dao.insert(Book(bookName = "not Eugene's book #4", useridmap = currentUserId))
dao.insert(Book(bookName = "not Eugene's book #5", useridmap = currentUserId))
var mapping = dao.allUserBooks()
for(m: Map.Entry<User,List<Book>> in mapping) {
}
为了简便起见,在主线程上运行了上述内容而没有使用
Flow
。然后,我相信你所期望的结果是:-
补充
如果我们已经有了带有许多“_id”字段的数据库结构该怎么办?
那么你需要做一些决定。
你可以
- 进行迁移以重命名列以避免模糊/重复的列名称。
- 与更改提取输出列名称相结合使用替代POJO。
例如有:
data class Alt_User(val userId: Long, val name: String)
和
data class Alt_Book (val bookId: Long, val bookName: String, val user_id: Long)
随着:
@Query("SELECT user._id AS userId, user.name, book._id AS bookId, bookName, user_id " +
"FROM user JOIN book ON user._id = book.user_id")
fun allUserBooksAlt(): Map<Alt_User, List<Alt_Book>>
- 因此,根据Alt_User POJO,输出使用者的_id和名称
- 特定地输出其他列(尽管你可以像allUserBookAlt2那样使用*)
:-
@Query("SELECT *, user._id AS userId, book._id AS bookId " +
"FROM user JOIN book ON user._id = book.user_id")
fun allUserBooksAlt2(): Map<Alt_User, List<Alt_Book>>
- 与allUserBooksAlt相同,但还有额外的列
- 你将会收到一个警告:
warning: The query returns some columns [_id, _id] which are not used by any of [a.a.so70190116kotlinroomambiguouscolumnsfromdocs.Alt_User, a.a.so70190116kotlinroomambiguouscolumnsfromdocs.Alt_Book]. You can use @ColumnInfo annotation on the fields to specify the mapping. You can annotate the method with @RewriteQueriesToDropUnusedColumns to direct Room to rewrite your query to avoid fetching unused columns. You can suppress this warning by annotating the method with @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH). Columns returned by the query: _id, name, _id, bookName, user_id, userId, bookId. public abstract java.util.Map<a.a.so70190116kotlinroomambiguouscolumnsfromdocs.Alt_User, java.util.List<a.a.so70190116kotlinroomambiguouscolumnsfromdocs.Alt_Book>> allUserBooksAlt2();
- 由于请注意,如果查询具有多个与其名称相同的列,则Room不会重写该查询,因为它尚未有一种区分哪个列是必要的方式。
@RewriteQueriesToDropUnusedColumns
无法消除警告。
如果使用“:-”:
var mapping = dao.allUserBooksAlt() //<<<<<<<<<< BREAKPOINT HERE
for(m: Map.Entry<Alt_User,List<Alt_Book>> in mapping) {
}
这将导致:
可能还有其他选项。
然而,我建议通过迁移来解决这个问题,将列重命名为唯一名称。例如: