房间 Android、select 两张桌子

Room Android, select on two tables

我是 Room 的新手,我正在努力使用它。 我想对名为 Project 和 Tasks 的两个表做一个简单的 select。这是两个 classes 和第三个到 link 他们:


    @Entity
    public class Project {
        @PrimaryKey(autoGenerate = true)
        private final long id;
        @NonNull
        private final String name;
        @ColorInt
        private final Integer color;
       }
    
    @Entity(foreignKeys = @ForeignKey(entity = Project.class, parentColumns = "id", childColumns = "projectId"))
    public class Task {
    
        @PrimaryKey(autoGenerate = true)
        private long idTask;
    
        // clé commune
        private long projectId;
    
        @NonNull
        private String nameTask;
    
        public long creationTimestamp;
    // constructor, getters, setters
       }
    
    public class TaskWithProject {
        @Embedded public Project project;
        @Relation(parentColumn = "id", entityColumn = "projectId")
        public Task task;
    }

我在 Dao 中尝试了很多东西 class。这是其中两个:


    @Dao
    public interface TaskDao {
    (...)
    
    // Solution 1
    @Query("SELECT * FROM Task t JOIN Project p ON t.projectId = p.id")
        LiveData<List<TaskWithProject>> getTaskWithProject();
    
    // Solution 2 from https://developer.android.com/training/data-storage/room/relationships
    @Transaction
    @Query("SELECT * FROM Task")
    LiveData<List<TaskWithProject>> getTaskWithProject();

我的数据库中填充了这些数据(在数据库检查器中没有问题):


    projectDao.insertProject(new Project(0, "Projet Tartampion", 0xFFEADAD1));
                    projectDao.insertProject(new Project(0, "Projet Lucidia", 0xFFB4CDBA));
                    projectDao.insertProject(new Project(0, "Projet " + "Circus", 0xFFA3CED2));
                    taskDao.insertTask(new Task(0, 1, "Task 1 - Tartampion"));
                    taskDao.insertTask(new Task(0, 1, "Task 2 - Tartampion"));
                    taskDao.insertTask(new Task(0, 2, "Task 1 - Lucidia"));

我用这个函数获取数据:


    public LiveData<List<TaskViewStateItem>> getAllTasks() {
            return Transformations.map(repository.getTaskWithProject(), tasks -> {
                List<TaskViewStateItem> liststateitems = new ArrayList<>();
                    for (TaskWithProject t : tasks) {
                        Log.i(TAG, "getAllTasks: "+ t.toString());
                        liststateitems.add(new TaskViewStateItem(t.task.getIdTask(), t.task.getNameTask(), t.project.getName(), t.project.getColor(), t.task.getCreationTimestamp()));
                    }
                }
                return liststateitems;
            });
        }

使用上面的解决方案 1,我有 3 个条目,但有一个重复条目。


    I/Log ViewModel: getAllTasks: TaskWithProject{project=Project{id=1, name='Projet Tartampion', color=-1385775}, task=Task{idTask=2, projectId=1, nameTask='Task 2 - Tartampion', creationTimestamp=1634723235}}
    I/Log ViewModel: getAllTasks: TaskWithProject{project=Project{id=1, name='Projet Tartampion', color=-1385775}, task=Task{idTask=2, projectId=1, nameTask='Task 2 - Tartampion', creationTimestamp=1634723235}}
        getAllTasks: TaskWithProject{project=Project{id=2, name='Projet Lucidia', color=-4928070}, task=Task{idTask=3, projectId=2, nameTask='Task 1 - Lucidia', creationTimestamp=1634723235}}

方案2编译不通过


    error: Not sure how to convert a Cursor to this method's return type (com.cleanup.todoc.model.TaskWithProject).
        LiveData<List<TaskWithProject>> getTaskWithProject();
                                        ^

我不知道我做错了什么。所以非常感谢你能给我的任何帮助

由于您的 TaskWithProject class 嵌入了项目,因此它期望获取项目的列,然后从中构建任务,因此当您使用 SELECT * FROM Task 它时没有相关的列(它有连接但可能无法按预期工作)。

  • 真的 TaskWithProject 是 ProjectWithTask。

因此,要么使用 SELECT * FROM project,要么使用 POJO 嵌入任务和项目作为 @Relation(使用 SELECT * FROM task)。