多个字段具有相同的columnName Android Room

时间:2019-10-16 17:25:55

标签: mysql android-room pojo

我有3个表ruser,accounts,accountgroup。每个人都有一个称为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.

我试图为每个嵌入式对象添加一个前缀,但是我也遇到了一个错误。我不想一一检索列,因为它们很多。 有什么我想念的吗... ?? 谢谢

2 个答案:

答案 0 :(得分:1)

或者,您可以使用嵌入式注释的prefix attribute

class GroupChatItem(
    @Embedded(prefix = "user_")
    val rUserDto: RUserDto,
    @Embedded(prefix = "acc_")
    val account: AccountDto,
    @Embedded(prefix = "accgr_")
    val accountGroup: AccountGroupDto
)

,然后为SQL查询中每个实体的所有列加上别名。

我认为prefix属性是s最近的更新,但我不确定

答案 1 :(得分:0)

除了拥有/使用以外,我不相信您还有其他选择:-

  • a)在要包含在联接中的表中具有不同的列名(然后无需在列名前添加前缀),

  • b)在提取值时使用AS重命名列,并在嵌入实体以确保名称匹配时插入前缀。

我相信a)是更简单的选择,因为这样会减少无意中使用错误的列名的可能性。


据我了解,列名称必须与Room匹配,才能知道如何能够从基础结果集中复制一个值,而这并不能指示该值来自哪个表返回的一个或多个对象。

这是在类似场景3的嵌入式实体(用户办公室位置)中生成的代码的示例,其中一些列名称相同。它们每个都有一个 id 列,而“用户”和“位置”都有一个名为 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(如果它继续而不是退出循环(我相信它不会中断)跳出循环)。