all the _id columns have the same index there.
Is there a chance to do something here?
Yes, use unique column names e.g.
@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)
- as used in the example below.
or
@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)
Otherwise, as you may have noticed, Room uses the value of the last found column with the duplicated name and the User's _id is the value of the Book's _id column.
Using the above and replicating your data using :-
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() //<<<<<<<<<< BREAKPOINT HERE
for(m: Map.Entry<User,List<Book>> in mapping) {
}
- for convenience and brevity a
Flow
hasn't been used and the above was run on the main thread.
Then the result is what I believe you are expecting :-

Additional
What if we already have the database structure with a lot of "_id" fields?
Then you have some decisions to make.
You could
- do a migration to rename columns to avoid the ambiguous/duplicate column names.
- use alternative POJO's in conjunction with changing the extract output column names accordingly
e.g. have :-
data class Alt_User(val userId: Long, val name: String)
and
data class Alt_Book (val bookId: Long, val bookName: String, val user_id: Long)
along with :-
@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>>
- so user._id is output with the name as per the Alt_User POJO
- other columns output specifically (although you could use * as per 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>>
- same as allUserBooksAlt but also has the extra columns
- you would get a warning
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();
- Due to Note that Room will not rewrite the query if it has multiple columns that have the same name as it does not yet have a way to distinguish which one is necessary. the
@RewriteQueriesToDropUnusedColumns
doesn't do away with the warning.
if using :-
var mapping = dao.allUserBooksAlt() //<<<<<<<<<< BREAKPOINT HERE
for(m: Map.Entry<Alt_User,List<Alt_Book>> in mapping) {
}
Would result in :-

However, I'd suggest fixing the issue once and for all by using a migration to rename columns to all have unique names. e.g.