[英]Android Room FOREIGN KEY constraint failed
I'm trying to design and implement a folder tree structure in Android SQLite with help of Android Room Persistence (an ORM) which Google introduced in I/O 2017. In my design, a folder can contain another folders and files. 我试图在Android SQLite中设计和实现文件夹树结构,借助Google在I / O 2017中引入的Android Room Persistence(一种ORM)。在我的设计中,文件夹可以包含其他文件夹和文件。 Here are my codes for folder and file:
这是我的文件夹和文件的代码:
File Model: 文件模型:
@Entity(tableName = "files", foreignKeys = @ForeignKey(entity = Folder.class,
parentColumns = "id",
childColumns = "parent_id",
onDelete = CASCADE))
public class File {
@PrimaryKey(autoGenerate = true)
private int id;
private String title;
private Date creationDate;
@ColumnInfo(name = "parent_id")
public int parentId;
//here setters and getters skipped but exist in original code
}
And Here is Folder Code: 这是文件夹代码:
@Entity(tableName = "folders", foreignKeys = @ForeignKey(entity = Folder.class,
parentColumns = "id",
childColumns = "parent_id",
onDelete = CASCADE,onUpdate = SET_NULL))
public class Folder {
@PrimaryKey(autoGenerate = true)
private int id;
private String name;
@ColumnInfo(name = "parent_id")
private int parentId;
}
Which have a foreign key on ID column of it self for parent. 父ID的ID列上有一个外键。
and here is FolderDAO: 这里是FolderDAO:
@Dao
public interface FolderDAO {
@Insert(onConflict = OnConflictStrategy.REPLACE)
public void insertFolder(Folder... folders);
@Update
public void updateFolder(Folder... folders);
@Delete
public void deleteFolders(Folder... folders);
@Query("SELECT * FROM folders")
List<Folder> getAll();
@Query("SELECT * FROM folders WHERE id IN (:folderIds)")
List<Folder> loadAllByIds(int[] folderIds);
}
But when I make a folder object and try to insert it: 但是当我创建一个文件夹对象并尝试插入它时:
AsyncTask.execute(new Runnable() {
@Override
public void run() {
Folder folder = new Folder();
folder.setName("All");
DatabaseInstance.getInstance(getApplicationContext()).folderDAO().insertFolder(folder);
}
});
get this error: 得到这个错误:
FOREIGN KEY constraint failed FOREIGN KEY约束失败
--------- beginning of crash
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: sahraei.hamidreza.com.note, PID: 1835
android.database.sqlite.SQLiteConstraintException: FOREIGN KEY constraint failed (code 787)
at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:782)
at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
at android.arch.persistence.db.framework.FrameworkSQLiteStatement.executeInsert(FrameworkSQLiteStatement.java:80)
at android.arch.persistence.room.EntityInsertionAdapter.insert(EntityInsertionAdapter.java:80)
at sahraei.hamidreza.com.note.DAO.FolderDAO_Impl.insertFolder(FolderDAO_Impl.java:80)
at sahraei.hamidreza.com.note.ItemListActivity$1.run(ItemListActivity.java:62)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Does anyone know what's wrong or suggest another design for my project table? 有谁知道什么是错的或建议我的项目表的另一个设计?
I got this to work, but not using int
primary keys. 我得到了这个工作,但没有使用
int
主键。 I'm not a huge fan of those for this sort of ORM scenario, just because of these sorts of problems. 我不是那种ORM场景的忠实粉丝,只是因为这些问题。
So, here's a self-referential Category
class that uses a UUID
for its primary key: 所以,这是一个自引用的
Category
类,它使用UUID
作为其主键:
/***
Copyright (c) 2017 CommonsWare, LLC
Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
by applicable law or agreed to in writing, software distributed under the
License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
OF ANY KIND, either express or implied. See the License for the specific
language governing permissions and limitations under the License.
*/
package com.commonsware.android.room.dao;
import android.arch.persistence.room.Entity;
import android.arch.persistence.room.ForeignKey;
import android.arch.persistence.room.Ignore;
import android.arch.persistence.room.Index;
import android.arch.persistence.room.PrimaryKey;
import java.util.UUID;
import static android.arch.persistence.room.ForeignKey.CASCADE;
@Entity(
tableName="categories",
foreignKeys=@ForeignKey(
entity=Category.class,
parentColumns="id",
childColumns="parentId",
onDelete=CASCADE),
indices=@Index(value="parentId"))
public class Category {
@PrimaryKey
public final String id;
public final String title;
public final String parentId;
@Ignore
public Category(String title) {
this(title, null);
}
@Ignore
public Category(String title, String parentId) {
this(UUID.randomUUID().toString(), title, parentId);
}
public Category(String id, String title, String parentId) {
this.id=id;
this.title=title;
this.parentId=parentId;
}
}
Now you can have DAO methods like: 现在你可以使用DAO方法:
@Query("SELECT * FROM categories WHERE parentId IS NULL")
Category findRootCategory();
@Query("SELECT * FROM categories WHERE parentId=:parentId")
List<Category> findChildCategories(String parentId);
It took me a loong time to figure out that having a parentColumns
element which is an autogenerated primary key does not seem to be allowed at all, even if it is a uuid using a Kotlin data class with a default value like this: 我花了很长时间才发现拥有一个自动生成的主键的
parentColumns
元素似乎根本不被允许,即使它是使用具有默认值的Kotlin数据类的uuid,如下所示:
MyClass{
//Don't do this
@PrimaryKey(autoGenerate = true)
var uuid: String = UUID.randomUUID()
}
Always make sure the parent column is specified directly by you. 始终确保您直接指定父列。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.