为什么仪器室测试得到错误 FOREIGN KEY constraint failed
Why instrumented room test get error FOREIGN KEY constraint failed
我不明白这个错误,我有两个实体任务和项目,一个任务分配给一个项目(见下面的代码)。
但是当我想测试添加一个任务时,我有这个错误:
android.database.sqlite.SQLiteConstraintException: FOREIGN KEY 约束失败(代码 787 SQLITE_CONSTRAINT_FOREIGNKEY)
我尝试将 onDelete = CASCADE
添加到 FOREIGNKEY 但我的测试不起作用:/
任务Class
@Entity(tableName = "task_table",
foreignKeys = @ForeignKey(entity = Project.class,
parentColumns = "id",
childColumns = "projectId"))
public class Task {
/**
* The unique identifier of the task
*/
@PrimaryKey(autoGenerate = true)
public long id;
private long projectId;
@SuppressWarnings("NullableProblems")
@NonNull
private String name.
private long creationTimestamp;
public Task(long projectId, @NonNull String name, long creationTimestamp) {
this.setProjectId(projectId);
this.setName(name);
this.setCreationTimestamp(creationTimestamp);
}
...
TaskDao
@Dao
public interface TaskDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Task task);
@Query("DELETE FROM task_table WHERE id = :id")
void delete(long id);
@Query("SELECT * FROM task_table ORDER BY id ASC")
LiveData<List<Task>> getAllTasks();
@Query("SELECT * FROM task_table WHERE id = :id")
LiveData<Task> getTaskById(long id);
}
项目Class
@Entity(tableName = "project_table")
public class Project {
/**
* The unique identifier of the project
*/
@PrimaryKey(autoGenerate = true)
public long id;
@NonNull
private String name;
@ColorInt
private int color;
public Project(@NonNull String name, @ColorInt int color) {
this.name = name;
this.color = color;
}
ProjectDao
@Dao
public interface ProjectDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
void insert(Project project);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(List<Project> projects);
@Query("SELECT * FROM project_table")
LiveData<List<Project>> getAllProjects();
@Query("SELECT * FROM project_table WHERE id = :id")
LiveData<Project> getProjectById(long id);
}
测试仪器:
@Before
public void createDb() {
this.database = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(),
AppDatabase.class)
.allowMainThreadQueries()
.build();
taskDao = database.taskDao();
projectDao = database.projectDao();
}
@After
public void closeDb() {
database.close();
}
@Test
public void addTask() {
Project project = new Project("toto", 0xFFB4CDBA);
this.projectDao.insert(project);
long projectId = project.getId();
assertThat(projectId, equalTo(project.getId()));
Task task = new Task(projectId, "tâche 1", new Date().getTime());
this.taskDao.insert(task);
}
如果有人能帮忙就太好了,我不知道怎么解决。
非常感谢您的帮助
当您使用long projectId = project.getId();
.
时,由于没有根据插入的值进行设置,项目id将为0
因此,当插入任务作为项目的 id 列时,外键冲突将由 SQLite 生成,并且不会为 0(它将为 1 或更大)。
改变
@Insert(onConflict = OnConflictStrategy.IGNORE)
void insert(Project project);
to(获取实际生成的id)
@Insert(onConflict = OnConflictStrategy.IGNORE)
long insert(Project project); // will return the id that has been generated
然后使用 :-
Project project = new Project("toto", 0xFFB4CDBA);
long projectId = this.projectDao.insert(project); //<<<<< returns the actual id
project.setId(projectId); // sets project id according to the inserted id BUT only if inserted and not ignored when returned value will be -1
// You should really check for -1 and handle accordingly
assertThat(projectId, equalTo(project.getId())); // not really of any use
Task task = new Task(projectId, "tâche 1", new Date().getTime());
this.taskDao.insert(task);
- 注意,以上为in-principle代码,未编译或run/tested。因此它可能包含一些错误。
我不明白这个错误,我有两个实体任务和项目,一个任务分配给一个项目(见下面的代码)。
但是当我想测试添加一个任务时,我有这个错误: android.database.sqlite.SQLiteConstraintException: FOREIGN KEY 约束失败(代码 787 SQLITE_CONSTRAINT_FOREIGNKEY)
我尝试将 onDelete = CASCADE
添加到 FOREIGNKEY 但我的测试不起作用:/
任务Class
@Entity(tableName = "task_table",
foreignKeys = @ForeignKey(entity = Project.class,
parentColumns = "id",
childColumns = "projectId"))
public class Task {
/**
* The unique identifier of the task
*/
@PrimaryKey(autoGenerate = true)
public long id;
private long projectId;
@SuppressWarnings("NullableProblems")
@NonNull
private String name.
private long creationTimestamp;
public Task(long projectId, @NonNull String name, long creationTimestamp) {
this.setProjectId(projectId);
this.setName(name);
this.setCreationTimestamp(creationTimestamp);
}
...
TaskDao
@Dao
public interface TaskDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Task task);
@Query("DELETE FROM task_table WHERE id = :id")
void delete(long id);
@Query("SELECT * FROM task_table ORDER BY id ASC")
LiveData<List<Task>> getAllTasks();
@Query("SELECT * FROM task_table WHERE id = :id")
LiveData<Task> getTaskById(long id);
}
项目Class
@Entity(tableName = "project_table")
public class Project {
/**
* The unique identifier of the project
*/
@PrimaryKey(autoGenerate = true)
public long id;
@NonNull
private String name;
@ColorInt
private int color;
public Project(@NonNull String name, @ColorInt int color) {
this.name = name;
this.color = color;
}
ProjectDao
@Dao
public interface ProjectDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
void insert(Project project);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(List<Project> projects);
@Query("SELECT * FROM project_table")
LiveData<List<Project>> getAllProjects();
@Query("SELECT * FROM project_table WHERE id = :id")
LiveData<Project> getProjectById(long id);
}
测试仪器:
@Before
public void createDb() {
this.database = Room.inMemoryDatabaseBuilder(ApplicationProvider.getApplicationContext(),
AppDatabase.class)
.allowMainThreadQueries()
.build();
taskDao = database.taskDao();
projectDao = database.projectDao();
}
@After
public void closeDb() {
database.close();
}
@Test
public void addTask() {
Project project = new Project("toto", 0xFFB4CDBA);
this.projectDao.insert(project);
long projectId = project.getId();
assertThat(projectId, equalTo(project.getId()));
Task task = new Task(projectId, "tâche 1", new Date().getTime());
this.taskDao.insert(task);
}
如果有人能帮忙就太好了,我不知道怎么解决。
非常感谢您的帮助
当您使用long projectId = project.getId();
.
因此,当插入任务作为项目的 id 列时,外键冲突将由 SQLite 生成,并且不会为 0(它将为 1 或更大)。
改变
@Insert(onConflict = OnConflictStrategy.IGNORE)
void insert(Project project);
to(获取实际生成的id)
@Insert(onConflict = OnConflictStrategy.IGNORE)
long insert(Project project); // will return the id that has been generated
然后使用 :-
Project project = new Project("toto", 0xFFB4CDBA);
long projectId = this.projectDao.insert(project); //<<<<< returns the actual id
project.setId(projectId); // sets project id according to the inserted id BUT only if inserted and not ignored when returned value will be -1
// You should really check for -1 and handle accordingly
assertThat(projectId, equalTo(project.getId())); // not really of any use
Task task = new Task(projectId, "tâche 1", new Date().getTime());
this.taskDao.insert(task);
- 注意,以上为in-principle代码,未编译或run/tested。因此它可能包含一些错误。