【问题标题】:is there any way to run nested query in room database有没有办法在房间数据库中运行嵌套查询
【发布时间】:2019-12-20 10:08:15
【问题描述】:

我正在将旧的Android 项目迁移到新标准,我被困在room database 之间,无法找到如何使用SQLite 执行这两个SQLite 命令。我有 2 个以嵌套方式工作的查询,因此使用 room 获得相同的结果是否有任何可能。

    default public ArrayList getOfflineRoomsAndObjectsByParentIds(String parentId, String site_id, Context context) {

        databaseHandler = new DatabaseHandler(context);
        Cursor cr = null;
        ArrayList<Room> offlineRoomNamesList = new ArrayList<>();
        try {

           **sqLiteDatabase = databaseHandler.getReadableDatabase();
            String query = "SELECT * FROM " + Constants.TABLE_ROOM_NAMES
                    + " WHERE " + Constants.SITE_ID + " = '" + site_id + "' AND " + Constants.PARENT_ID + "='" + parentId + "'";**

            cr = sqLiteDatabase.rawQuery(query, null);
            if (cr.moveToFirst()) {

                do {

                    Room room = new Room();
                    **room.setId(cr.getString(cr.getColumnIndex(Constants.KEY_ROOM_ID)));
                    query = "SELECT * FROM " + Constants.TABLE_OFFLINE_ROOM_OBJECTS
                            + " WHERE " + Constants.KEY_ROOM_KEY + " = ?"
                            + " AND " + Constants.SITE_ID + " = ? ORDER BY " + Constants.KEY_OBJECT_NAME;**

                    Cursor cursor = sqLiteDatabase.rawQuery(query, new String[]{cr.getString(cr.getColumnIndex(Constants.KEY_ROOM_KEY)), site_id});
                    if (cursor.moveToFirst()) {
                        do {
                            RoomObject roomObject = new RoomObject();
                            roomObject.setRoomKey(cursor.getString(cursor.getColumnIndex(Constants.KEY_ROOM_KEY)));
                            roomObject.setId(cursor.getInt(cursor.getColumnIndex(Constants.KEY_ID)));
                            roomObject.setInstanceNumber(cursor.getInt(cursor.getColumnIndex(Constants.KEY_INSTANCE_NUMBER)));
                            roomObject.setObjectType(cursor.getString(cursor.getColumnIndex(Constants.KEY_OBJECT_TYPE)));


                            String mergeKey = AppSharedPreference.getString(AppSharedPreference.MERGE_KEY, "", context);
                            if (roomObject.getObjectName().contains(mergeKey) && !TextUtils.isEmpty(mergeKey)) {
                                room.addMergeableObjectsInList(roomObject);
                            } else {
                                room.addRoomObjectsInList(roomObject);
                            }


                        }
                        while (cursor.moveToNext());
                    }
                    if (room.getRoomObjectsList().size() > 0)
                        offlineRoomNamesList.add(room);
                    cursor.close();
                } while (cr.moveToNext());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                cr.close();
                sqLiteDatabase.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return offlineRoomNamesList;
    }

我现在看到的唯一可能性是两个定义 2 个不同的查询并以嵌套方式执行它们。

@Dao
public interface ControllerRoomObjectDao {



    @Query("SELECT * FROM room_names WHERE site_id=:siteId AND parentId=:parentId")
    Single<List<Room>>getOfflineRoomsAndObjectsByParentId(String siteId, String parentId);


    @Query("SELECT * FROM offline_objects WHERE site_id=:siteId AND parentId=:parentId")
    Single<List<RoomObject>>getOfflineObjectsByParentId(String siteId, String parentId);

}

【问题讨论】:

  • 它会帮助你:stackoverflow.com/a/48298192
  • 你能描述两个表之间的关系以及每个表的属性吗?是联合还是联合?
  • 我已经更新了我的表结构。

标签: android sqlite android-room


【解决方案1】:

您可以将 databaseView 用于您的用例 例如:

@DatabaseView("SELECT user.id, user.name, user.departmentId," +
        "department.name AS departmentName FROM user " +
        "INNER JOIN department ON user.departmentId = department.id")

public class UserDetail {
    public long id;
    public String name;
    public long departmentId;
    public String departmentName;
}

更多信息https://developer.android.com/training/data-storage/room/creating-views#java

【讨论】:

    【解决方案2】:

    不确定这是否完全符合您的要求,但它可能会帮助其他具有相同一般要求的人。

    基本上,我接受了this example 的建议,该建议显示了如何在 MySQL 中执行嵌套查询/子查询。

    使用相同的语法,我能够从以下位置更改我的基本 DAO 查询:

    @Transaction
    @Query("SELECT * FROM `events` WHERE `item_id` = :currentItemId AND `event_datetime` > :datetimeFrom ORDER BY `event_datetime` ASC LIMIT 1")
    LiveData<Event> getNextEventWithSameItemId(long currentItemId, String datetimeFrom);
    

    @Transaction
    @Query("SELECT * FROM `events` WHERE `item_id` IN (SELECT `item_id` FROM `events` WHERE `_id` = :currentEventId) AND `event_datetime` > :datetimeFrom ORDER BY `event_datetime` ASC LIMIT 1")
    LiveData<Event> getNextEventWithSameEventId(long currentEventId, String datetimeFrom);
    

    我的事件实体在哪里

    @Entity(tableName = "events")
    public class Event {
    
        @PrimaryKey
        @ColumnInfo(name = "_id")
        public long id;
    
        @ColumnInfo(name = "item_id") // Relates to `items`.`_id`
        public long itemId;
    
        @ColumnInfo(name = "event_datetime")
        public String eventDatetime;
        
        ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-10
      • 1970-01-01
      • 2017-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多