[英]Android Room FOREIGN KEY constraint failed when delete room table
[英]Android Room FOREIGN KEY constraint failed
我試圖在Android SQLite中設計和實現文件夾樹結構,借助Google在I / O 2017中引入的Android Room Persistence(一種ORM)。在我的設計中,文件夾可以包含其他文件夾和文件。 這是我的文件夾和文件的代碼:
文件模型:
@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
}
這是文件夾代碼:
@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;
}
父ID的ID列上有一個外鍵。
這里是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);
}
但是當我創建一個文件夾對象並嘗試插入它時:
AsyncTask.execute(new Runnable() {
@Override
public void run() {
Folder folder = new Folder();
folder.setName("All");
DatabaseInstance.getInstance(getApplicationContext()).folderDAO().insertFolder(folder);
}
});
得到這個錯誤:
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)
有誰知道什么是錯的或建議我的項目表的另一個設計?
我得到了這個工作,但沒有使用int
主鍵。 我不是那種ORM場景的忠實粉絲,只是因為這些問題。
所以,這是一個自引用的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;
}
}
現在你可以使用DAO方法:
@Query("SELECT * FROM categories WHERE parentId IS NULL")
Category findRootCategory();
@Query("SELECT * FROM categories WHERE parentId=:parentId")
List<Category> findChildCategories(String parentId);
我花了很長時間才發現擁有一個自動生成的主鍵的parentColumns
元素似乎根本不被允許,即使它是使用具有默認值的Kotlin數據類的uuid,如下所示:
MyClass{
//Don't do this
@PrimaryKey(autoGenerate = true)
var uuid: String = UUID.randomUUID()
}
始終確保您直接指定父列。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.