Próbuję zaprojektować i zaimplementować strukturę drzewa folderów w Android SQLite za pomocą Android Room Persistence (ORM), którą Google wprowadził w I/O 2017. W moim projekcie, folder może zawierać inne foldery i pliki. Oto moje kody do folderu i pliku:Ograniczenie FORAIGN KEY FORTE zabronione
Plik 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
}
I Oto kod Folder:
@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;
}
Jakie masz klucza obcego w kolumnie ID nim samo dla rodzica .
i tu jest 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);
}
Ale kiedy robię obiekt folderu i spróbuj go wstawić:
AsyncTask.execute(new Runnable() {
@Override
public void run() {
Folder folder = new Folder();
folder.setName("All");
DatabaseInstance.getInstance(getApplicationContext()).folderDAO().insertFolder(folder);
}
});
dostać ten błąd:
FOREIGN KEY ograniczenia udało
--------- 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)
D Ktoś wie, co jest nie tak lub zaproponować inny projekt dla mojego stołu projektu?
„Robię obiekt folderu i spróbuj go wstawić "- edytuj swoje pytanie i opublikuj ten kod wraz z kompletnym śledzeniem stosu Java. – CommonsWare
@CommonsWars Edytowane. –
Nie określono folderu nadrzędnego i domyślam się, że właśnie to powoduje ten błąd. Oczywiście * nie możesz * określić folderu nadrzędnego dla pierwszego folderu, ponieważ nie ma rodzica do wskazania. [Self-referencyjne klucze obce działają w SQLite] (https://stackoverflow.com/q/15967146/115145), chociaż wygląda na to [musisz jawnie użyć 'NULL' dla wartości, gdy jej brakuje) (https: //stackoverflow.com/a/6518551/115145). Nie wiem, co generuje pokój dla instrukcji "INSERT" tutaj. – CommonsWare