У нескольких полей один и тот же столбец Имя Android Room

У меня 3 таблицы русер, аккаунты, accountgroup. У каждого есть один и тот же столбец под названием rsuerId.

Я создал класс POJO с 3 встроенными объектами, как показано ниже.

class GroupChatItem(
    @Embedded
    val rUserDto: RUserDto,
    @Embedded
    val account: AccountDto,
    @Embedded
    val accountGroup: AccountGroupDto
)

Теперь я хочу сделать запрос, который извлекает GroupChatItem с заданными rUserId и accountGroupId, как показано ниже.

@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.

Я пытался добавить префикс к каждому встроенному объекту, но также получаю сообщение об ошибке. Я не хочу получать столбцы один за другим, потому что их много. Есть что-нибудь, что я пропустил ... ?? Спасибо


person james04    schedule 16.10.2019    source источник
comment
Нет, вам нужно извлекать их один за другим, использование select * в производственном коде обычно считается плохой практикой.   -  person Uueerdo    schedule 16.10.2019
comment
Какая часть сообщения об ошибке вам непонятна? У вас есть несколько столбцов с одинаковыми именами.   -  person Eric    schedule 16.10.2019


Ответы (2)


В качестве альтернативы вы можете использовать атрибут префикса встроенной аннотации:

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

а затем псевдоним всех столбцов каждой сущности в вашем SQL-запросе.

Я думаю, что атрибут префикса является недавним обновлением, но я не уверен

person Geist 5000    schedule 06.06.2020
comment
я пробовал это и это не работает - person james04; 27.03.2021

Я не верю, что у вас есть другой вариант, кроме как иметь / использовать: -

  • a) иметь разные имена столбцов в таблицах, которые должны быть включены в объединения (тогда нет необходимости добавлять префиксы к именам столбцов),

or

  • б) переименовать столбцы с помощью 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"), он вернет либо 0 (первый), если он выйдет из цикла, либо 2, если он продолжится, а не выйдет из цикла (я считаю, что он не выходит из цикла ).

person MikeT    schedule 16.10.2019
comment
Проблема с попыткой иметь отдельные имена столбцов в таблицах заключается в том, что они обычно в конечном итоге становятся отличными за счет добавления префиксов, которых стараются избежать; затем база данных растет, и префикс имеет отношение к нескольким таблицам, поэтому вам нужно запомнить, какая таблица использовала какой префикс, и в конечном итоге вам придется уточнять имена с таблицами / псевдонимами, которые вы изначально пытались избежать, поэтому запросы заканчиваются выглядит как ....runbigdata AS rbg JOIN runbaddata AS rbd ON rbg.rbdvalue = rbd.rbdvalue.... - person Uueerdo; 16.10.2019
comment
@Uueerdo Я не собираюсь обсуждать, поддерживать плохой дизайн или нет. Если вы считаете, что плохой дизайн следует учесть в Room, обратитесь к ответственным за номер. - person MikeT; 16.10.2019
comment
Ну, есть ли способ исключить определенные столбцы из запроса ...? - person james04; 19.10.2019
comment
@ james04 Вы можете исключить столбцы, специально включив другие столбцы, но тогда у вас могут возникнуть проблемы с невозможностью создания базовых объектов. - person MikeT; 19.10.2019