我有這樣的 DAO
@Dao
public interface ActivityDAO {
@Insert
void insert(Activity activity);
物體是這樣定義的
@Entity(indices = {@Index(value = {"`id_from_client`"},
unique = true)})
public class Activity {
@PrimaryKey(autoGenerate = true)
public int id;
@NotNull
@ColumnInfo(name = "id_from_client")
public String id_from_client;
盡管id_from_client在我嘗試使用相同id_from_client的物件保存物件時設定了索引,但插入并沒有被拒絕并且行被添加。為什么 Room 不強制執行 UNIQUE 索引約束?
我可以通過匯出資料庫并在資料庫瀏覽器上查看是否創建了索引,有一個帶有 create 陳述句CREATE UNIQUE INDEX index_Activity_id_id_from_client ONActivity (id , id_from_client的索引)。
uj5u.com熱心網友回復:
由于包含在 `. 結果訊息是:-
error: `id_from_client` referenced in the index does not exists in the Entity. Available column names:id, id_from_client
public class Activity {
^
改用:-
@Entity(indices = {@Index(value = {"id_from_client"}, /*<<<<<<<<<< removed enclosing `` */
unique = true)})
編譯成功,生成的 java 具有適當的 CREATE INDEX,如下所示:-
@Override
public void createAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("CREATE TABLE IF NOT EXISTS `Activity` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `id_from_client` TEXT NOT NULL)");
_db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS `index_Activity_id_from_client` ON `Activity` (`id_from_client`)");
_db.execSQL("CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)");
_db.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'c0bc90551cfa5dbc362321d550999680')");
}
- 生成的 java 可以使用 Android View 定位。相應的類是與使用@Database 注解但以_Impl 為后綴的類相同的類。
建議的行動
- 洗掉包圍索引列的`
- 使用最新的 Room 庫依賴項 (2.4.3)。
演示
通過上述更改,插入非唯一 id_from_client 的嘗試按預期失敗。考慮以下旨在對此進行測驗的內容:-
public class MainActivity extends AppCompatActivity {
TheDatabase db;
ActivityDAO dao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = TheDatabase.getInstance(this);
dao = db.getActivityDAO();
Activity a1 = new Activity();
a1.id=0;
a1.id_from_client = "100";
dao.insert(a1);
a1.id_from_client = "200";
dao.insert(a1);
SupportSQLiteDatabase sdb = db.getOpenHelper().getWritableDatabase();
Cursor csr = sdb.query("SELECT * FROM sqlite_master");
DatabaseUtils.dumpCursor(csr);
dao.insert(a1);
csr = sdb.query("SELECT * FROM sqlite_master");
DatabaseUtils.dumpCursor(csr);
csr.close();
}
}
也就是說,當運行前 2 個 Activity 行時,應該插入模式(又名 sqlite_master 將被提取并轉儲到日志中)。但是,由于 UNIQUE 沖突,id_from_client 仍然為 200 的第三次插入將失敗(在所有三個插入中,id 為 0 將導致生成 id 列)。
- 請注意,
.allowMainThreadQueries已用于簡潔和方便
build.gradle(Module ....)用于演示的依賴項(in )是:-
dependencies {
....
implementation 'androidx.room:room-runtime:2.4.3'
....
annotationProcessor 'androidx.room:room-compiler:2.4.3'
}
運行上述結果的日志是:-
2022-11-01 06:33:57.745 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@17eeb83
2022-11-01 06:33:57.746 I/System.out: 0 {
2022-11-01 06:33:57.746 I/System.out: type=table
2022-11-01 06:33:57.746 I/System.out: name=android_metadata
2022-11-01 06:33:57.746 I/System.out: tbl_name=android_metadata
2022-11-01 06:33:57.746 I/System.out: rootpage=3
2022-11-01 06:33:57.746 I/System.out: sql=CREATE TABLE android_metadata (locale TEXT)
2022-11-01 06:33:57.746 I/System.out: }
2022-11-01 06:33:57.746 I/System.out: 1 {
2022-11-01 06:33:57.746 I/System.out: type=table
2022-11-01 06:33:57.746 I/System.out: name=Activity
2022-11-01 06:33:57.746 I/System.out: tbl_name=Activity
2022-11-01 06:33:57.746 I/System.out: rootpage=4
2022-11-01 06:33:57.746 I/System.out: sql=CREATE TABLE `Activity` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `id_from_client` TEXT NOT NULL)
2022-11-01 06:33:57.746 I/System.out: }
2022-11-01 06:33:57.746 I/System.out: 2 {
2022-11-01 06:33:57.746 I/System.out: type=table
2022-11-01 06:33:57.746 I/System.out: name=sqlite_sequence
2022-11-01 06:33:57.746 I/System.out: tbl_name=sqlite_sequence
2022-11-01 06:33:57.747 I/System.out: rootpage=5
2022-11-01 06:33:57.747 I/System.out: sql=CREATE TABLE sqlite_sequence(name,seq)
2022-11-01 06:33:57.747 I/System.out: }
2022-11-01 06:33:57.747 I/System.out: 3 {
2022-11-01 06:33:57.747 I/System.out: type=index
2022-11-01 06:33:57.747 I/System.out: name=index_Activity_id_from_client
2022-11-01 06:33:57.747 I/System.out: tbl_name=Activity
2022-11-01 06:33:57.747 I/System.out: rootpage=6
2022-11-01 06:33:57.747 I/System.out: sql=CREATE UNIQUE INDEX `index_Activity_id_from_client` ON `Activity` (`id_from_client`)
2022-11-01 06:33:57.747 I/System.out: }
2022-11-01 06:33:57.747 I/System.out: 4 {
2022-11-01 06:33:57.747 I/System.out: type=table
2022-11-01 06:33:57.747 I/System.out: name=room_master_table
2022-11-01 06:33:57.747 I/System.out: tbl_name=room_master_table
2022-11-01 06:33:57.747 I/System.out: rootpage=7
2022-11-01 06:33:57.747 I/System.out: sql=CREATE TABLE room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)
2022-11-01 06:33:57.747 I/System.out: }
2022-11-01 06:33:57.747 I/System.out: <<<<<
2022-11-01 06:33:57.748 D/AndroidRuntime: Shutting down VM
2022-11-01 06:33:57.755 E/AndroidRuntime: FATAL EXCEPTION: main
Process: a.a.so74267661javaroomuniqueindex, PID: 28425
java.lang.RuntimeException: Unable to start activity ComponentInfo{a.a.so74267661javaroomuniqueindex/a.a.so74267661javaroomuniqueindex.MainActivity}: android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: Activity.id_from_client (code 2067 SQLITE_CONSTRAINT_UNIQUE)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: Activity.id_from_client (code 2067 SQLITE_CONSTRAINT_UNIQUE)
at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:938)
at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:790)
at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:88)
at androidx.sqlite.db.framework.FrameworkSQLiteStatement.executeInsert(FrameworkSQLiteStatement.java:51)
at androidx.room.EntityInsertionAdapter.insert(EntityInsertionAdapter.java:64)
at a.a.so74267661javaroomuniqueindex.ActivityDAO_Impl.insert(ActivityDAO_Impl.java:44)
at a.a.so74267661javaroomuniqueindex.MainActivity.onCreate(MainActivity.java:33)
at android.app.Activity.performCreate(Activity.java:7994)
at android.app.Activity.performCreate(Activity.java:7978)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/525571.html
上一篇:如何減小資料庫的大小?
下一篇:如何用Null填充缺失的數字?
