我有3个表ruser,帐户,帐户组。每个人都有一个称为rsuerId的同一列。
我创建了一个带有3个嵌入式对象的POJO类,如下所示。
class GroupChatItem(
@Embedded
val rUserDto: RUserDto,
@Embedded
val account: AccountDto,
@Embedded
val accountGroup: AccountGroupDto
)
现在,我想进行如下查询,该查询使用给定的rUserId和accountGroupId来获取GroupChatItem,如下所示。
@Query("""
Select ruser.*, accounts.*, accountgroup.*
from ruser
inner join accounts on accounts.rUserId = ruser.rUserId and accounts.active = 1
inner join accountgroup on accountgroup.rUserId = :rUserId and accountGroup.accountGroupId = :accountGroupId
where ruser.rUserId = :rUserId
""")
suspend fun getGroupChatItem(rUserId: Long, accountGroupId: Int): GroupChatItem
不幸的是,我收到以下错误。
Multiple fields have the same columnName: rUserId. Field names: rUserDto > rUserId, account > rUserId, accountGroup > rUserId.
我试图为每个嵌入式对象添加一个前缀,但是我也遇到了一个错误。我不想一一检索列,因为它们很多。
有什么我想念的吗... ??
谢谢
最佳答案
我不相信您除了拥有/使用之外别无选择:
a)在要包含在联接中的表中具有不同的列名(因此,无需在列名前添加前缀),
要么
b)提取值时,应使用AS重命名列,并在嵌入实体时确保其名称匹配时使用前缀。
我相信a)将是更简单的选择,因为这样会减少无意中使用错误的列名的可能性。
据我了解,列名称必须与Room匹配,才能知道如何能够从基础结果集中复制值,而这并不能指示值是从哪个表中返回的对象中的值或对象。
这是类似情况3嵌入式实体(用户,办公室和位置)的生成代码的示例,其中某些列名称相同。它们每个都有一个id列,而User和Places都有一个名为name的列。
@Override
public UserOfficePlacesCombined getAllUserOfficePlacesCombined() {
final String _sql = "SELECT user.id AS userid, user.name AS username, office.id AS officeid, office.address AS officeaddress, places.id AS placesid, places.name AS placesname FROM User JOIN Office ON User.id = Office.id JOIN Places ON User.id = Places.id";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
__db.assertNotSuspendingTransaction();
final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
try {
final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(_cursor, "userid");
final int _cursorIndexOfName = CursorUtil.getColumnIndexOrThrow(_cursor, "username");
final int _cursorIndexOfId_1 = CursorUtil.getColumnIndexOrThrow(_cursor, "officeid");
final int _cursorIndexOfAddress = CursorUtil.getColumnIndexOrThrow(_cursor, "officeaddress");
final int _cursorIndexOfId_2 = CursorUtil.getColumnIndexOrThrow(_cursor, "placesid");
final int _cursorIndexOfName_1 = CursorUtil.getColumnIndexOrThrow(_cursor, "placesname");
final UserOfficePlacesCombined _result;
if(_cursor.moveToFirst()) {
final User _tmpUser;
if (! (_cursor.isNull(_cursorIndexOfId) && _cursor.isNull(_cursorIndexOfName))) {
final long _tmpId;
_tmpId = _cursor.getLong(_cursorIndexOfId);
final String _tmpName;
_tmpName = _cursor.getString(_cursorIndexOfName);
_tmpUser = new User(_tmpId,_tmpName);
} else {
_tmpUser = null;
}
final Office _tmpOffice;
if (! (_cursor.isNull(_cursorIndexOfId_1) && _cursor.isNull(_cursorIndexOfAddress))) {
final long _tmpId_1;
_tmpId_1 = _cursor.getLong(_cursorIndexOfId_1);
final String _tmpAddress;
_tmpAddress = _cursor.getString(_cursorIndexOfAddress);
_tmpOffice = new Office(_tmpId_1,_tmpAddress);
} else {
_tmpOffice = null;
}
final Places _tmpPlaces;
if (! (_cursor.isNull(_cursorIndexOfId_2) && _cursor.isNull(_cursorIndexOfName_1))) {
final long _tmpId_2;
_tmpId_2 = _cursor.getLong(_cursorIndexOfId_2);
final String _tmpName_1;
_tmpName_1 = _cursor.getString(_cursorIndexOfName_1);
_tmpPlaces = new Places(_tmpId_2,_tmpName_1);
} else {
_tmpPlaces = null;
}
_result = new UserOfficePlacesCombined();
_result.setUser(_tmpUser);
_result.setOffice(_tmpOffice);
_result.setPlaces(_tmpPlaces);
} else {
_result = null;
}
return _result;
} finally {
_cursor.close();
_statement.release();
}
}
关键线是这样的:
final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(_cursor, "userid")
它用于在游标(也称为结果集)中搜索列的名称,并将偏移量返回到该列,然后使用索引从游标中获取实际值。
在您的方案中,结果集将包含一些类似
rUserId rUserId rUserId *
它应用于哪一个?您可能知道/理解第一个是ruser.rUserId,第二个是account.rUserId,第三个是accountgroup.rUserId,但是就目前而言,Room不会在生成代码时知道。因此,在使用
getColumnIndex("rUserId")
的所有3种情况下,它都会返回0(第一个)它退出循环,或者返回2(如果它继续而不是退出循环)(我相信它不会退出循环)循环)。