【问题标题】:Room Data-base how to implement item that needs columns from 2 entities房间数据库如何实现需要来自 2 个实体的列的项目
【发布时间】:2023-04-06 21:52:01
【问题描述】:

我已经使用带有 MVVM 的 Room 创建了数据库,我遇到了一个问题,希望您能帮我解决这个问题。

我有一个包含 3 个实体 PlayerGroupStandings 的数据库,其中排名是 PlayerGroup 之间的关系。 问题是我想展示排名,但Standings 只包含GroupPlayer 的ID,我希望它也显示Player 中的玩家姓名,我是使用LiveDataadaptersViewModels,所以当我返回LiveData<List<Standings>>的列​​表进行观察时,它不包含玩家的名字。

有人知道我也可以如何传递名字吗?

我能想到的唯一解决方案是创建一个新类,该类具有一个 Standing 和 name(String) 作为实例,然后将其返回以观察。

但这感觉不自然,所以我想我可以在这里找到一个更好、更优雅的解决方案。

     groupStandingsViewModel = ViewModelProviders.of(this, new GroupStandingsViewModelFactory(this.getApplication(), 0)).get(GroupStandingsViewModel.class);
    groupStandingsViewModel.getAllStandings().observe(this, new Observer<List<Standings>>() {
        @Override
        public void onChanged(List<Standings> standings) {
            adapter.setStanding(standings);
        }
    });

我希望能够同时获得在观察的onChanged 函数中给出的排名和名称。

【问题讨论】:

    标签: android android-recyclerview android-room dao android-livedata


    【解决方案1】:

    我能想到的唯一解决方案是创建一个新的类 有一个 Standing 和 name(String) 作为实例,然后返回 它来观察。

    但这感觉不自然,所以我想我可以在这里找到更好的, 更优雅的解决方案。

    这可能听起来不自然,但您需要一些新代码,那么还有什么? (P.S. 这是修辞)。

    我建议一个新课程是这样的:-

    public class PlayerGroupStanding {
    
        @Embedded
        Standings standing;
        String playerName;
        long playerId;
        String groupName;
        long groupId;
    
        public PlayerGroupStanding() {
        }
    
        public Standings getStanding() {
            return standing;
        }
    
        public void setStanding(Standings standing) {
            this.standing = standing;
        }
    
        public long getPlayerId() {
            return playerId;
        }
    
        public void setPlayerId(long playerId) {
            this.playerId = playerId;
        }
    
        public String getPlayerName() {
            return playerName;
        }
    
        public void setPlayerName(String playerName) {
            this.playerName = playerName;
        }
    
        public long getGroupId() {
            return groupId;
        }
    
        public void setGroupId(long groupId) {
            this.groupId = groupId;
        }
    
        public String getGroupName() {
            return groupName;
        }
    
        public void setGroupname(String groupname) {
            this.groupName = groupname;
        }
    }
    

    这可以与道查询结合使用:-

    @Query("SELECT * FROM standings JOIN player ON mapToPlayer = playerId JOIN `group` ON mapToGroup = groupId")
    List<PlayerGroupStanding> getAllStandingsWithPlayerAndGroupDetails();
    
    • 请注意,尽管给定的名称应该是不言自明的,但上面对名称做出了许多假设。
    • 请注意变量的名称,例如playerName 应该与查询返回的列名匹配。

    附加

    重新评论

    SELECT 在查询中返回什么对象。我知道如果我使用 SELECT * 那么对象将属于 FROM 中的类。但是当我返回列时,我需要在 LiveData> 中提及的对象是什么?如果可以在哪里找到有关它的信息?提前非常感谢您:D

    SELECT实际上返回一个Cursor,它是注释然后编写代码,根据根据类的成员名称映射列的方法的定义来提取列以返回对象,如果存在其他列,则它们被忽略. FROM 子句不会根据从该方法返回的类型确定 @Query 之后返回该方法的结果对象。

    在项目生成的代码中例如构建(Ctrl + F9)后可以找到实际代码。

    因此对于上面的示例,在 Dao 的代码中生成的相应方法(即带有 _impl 的 Dao 后缀)是:-

    @Override
      public List<PlayerGroupStandings> getAllPlayerGroupStandings() {
        final String _sql = "SELECT * FROM standings JOIN player ON mapToPlayer = playerId JOIN `group` ON mapToGroup = groupId";
        final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
        __db.assertNotSuspendingTransaction();
        final Cursor _cursor = DBUtil.query(__db, _statement, true, null);
        try {
          final int _cursorIndexOfMapToPlayer = CursorUtil.getColumnIndexOrThrow(_cursor, "mapToPlayer");
          final int _cursorIndexOfMapToGroup = CursorUtil.getColumnIndexOrThrow(_cursor, "mapToGroup");
          final LongSparseArray<ArrayList<Player>> _collectionPlayers = new LongSparseArray<ArrayList<Player>>();
          final LongSparseArray<ArrayList<Group>> _collectionGroup = new LongSparseArray<ArrayList<Group>>();
          while (_cursor.moveToNext()) {
            if (!_cursor.isNull(_cursorIndexOfMapToPlayer)) {
              final long _tmpKey = _cursor.getLong(_cursorIndexOfMapToPlayer);
              ArrayList<Player> _tmpPlayersCollection = _collectionPlayers.get(_tmpKey);
              if (_tmpPlayersCollection == null) {
                _tmpPlayersCollection = new ArrayList<Player>();
                _collectionPlayers.put(_tmpKey, _tmpPlayersCollection);
              }
            }
            if (!_cursor.isNull(_cursorIndexOfMapToGroup)) {
              final long _tmpKey_1 = _cursor.getLong(_cursorIndexOfMapToGroup);
              ArrayList<Group> _tmpGroupCollection = _collectionGroup.get(_tmpKey_1);
              if (_tmpGroupCollection == null) {
                _tmpGroupCollection = new ArrayList<Group>();
                _collectionGroup.put(_tmpKey_1, _tmpGroupCollection);
              }
            }
          }
          _cursor.moveToPosition(-1);
          __fetchRelationshipplayerAsarmAndroidroommigrationsPlayer(_collectionPlayers);
          __fetchRelationshipgroupAsarmAndroidroommigrationsGroup(_collectionGroup);
          final List<PlayerGroupStandings> _result = new ArrayList<PlayerGroupStandings>(_cursor.getCount());
          while(_cursor.moveToNext()) {
            final PlayerGroupStandings _item;
            final Standings _tmpStandings;
            if (! (_cursor.isNull(_cursorIndexOfMapToPlayer) && _cursor.isNull(_cursorIndexOfMapToGroup))) {
              _tmpStandings = new Standings();
              final Long _tmpMapToPlayer;
              _tmpMapToPlayer = _cursor.getLong(_cursorIndexOfMapToPlayer);
              _tmpStandings.setMapToPlayer(_tmpMapToPlayer);
              final Long _tmpMapToGroup;
              _tmpMapToGroup = _cursor.getLong(_cursorIndexOfMapToGroup);
              _tmpStandings.setMapToGroup(_tmpMapToGroup);
            }  else  {
              _tmpStandings = null;
            }
            ArrayList<Player> _tmpPlayersCollection_1 = null;
            if (!_cursor.isNull(_cursorIndexOfMapToPlayer)) {
              final long _tmpKey_2 = _cursor.getLong(_cursorIndexOfMapToPlayer);
              _tmpPlayersCollection_1 = _collectionPlayers.get(_tmpKey_2);
            }
            if (_tmpPlayersCollection_1 == null) {
              _tmpPlayersCollection_1 = new ArrayList<Player>();
            }
            ArrayList<Group> _tmpGroupCollection_1 = null;
            if (!_cursor.isNull(_cursorIndexOfMapToGroup)) {
              final long _tmpKey_3 = _cursor.getLong(_cursorIndexOfMapToGroup);
              _tmpGroupCollection_1 = _collectionGroup.get(_tmpKey_3);
            }
            if (_tmpGroupCollection_1 == null) {
              _tmpGroupCollection_1 = new ArrayList<Group>();
            }
            _item = new PlayerGroupStandings();
            _item.standings = _tmpStandings;
            _item.players = _tmpPlayersCollection_1;
            _item.group = _tmpGroupCollection_1;
            _result.add(_item);
          }
          return _result;
        } finally {
          _cursor.close();
          _statement.release();
        }
      }
    

    【讨论】:

    • 首先,非常感谢您的回答:)其次,我有一个后续问题,SELECT在查询中返回什么对象。我知道如果我使用 SELECT * 那么对象将属于 FROM 中的类。但是当我返回列时,我需要在 LiveData> 中提及的对象是什么?如果可以在哪里找到有关它的信息?非常感谢您:D
    • @YohaiM 我已经更新了答案来解释。如果发现答案有帮助,请勾选它作为答案。
    • 首先谢谢你,这是非常好的解释。是否可以“告诉”Dao 如何映射返回的对象中的列?这样我就可以自己适应PlayerGroupStanding? Room 支持吗?
    • @YohaiM 我不确定你是怎么做的,你可以使用 AS 通过 SELECT 重命名提取的列。例如假设您有一个名为 FRED 的列,并且您希望它适合名为 Mary 的变量然后 SELECT FRED as Mary .... 如果您的意思是类型,那么这可能是不可靠的,但您可以执行 SELECT CAST(FRED AS REAL) 但可能会得到意想不到的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多