@Database(entities = {Weight.class,Visits.class}, version = 1,exportSchema = false)
abstract class TheDatabase extends RoomDatabase {
abstract AllDao getAllDao();
private static TheDatabase INSTANCE;
static TheDatabase getINSTANCE(Context context) {
if (INSTANCE==null) {
INSTANCE = Room.databaseBuilder(
context,
TheDatabase.class,
"the_database.db"
)
.allowMainThreadQueries()
.addCallback(cb)
.build();
}
return INSTANCE;
}
/* Solution 2 - via SupportSQLiteDatabase */
void viaSupportSB(long date) {
SupportSQLiteDatabase db = this.getOpenHelper().getWritableDatabase();
db.beginTransaction();
db.execSQL("UPDATE visits SET date=? WHERE id=1",new String[]{String.valueOf(date)});
db.execSQL("DELETE FROM weight WHERE id_weight=-600");
db.setTransactionSuccessful();
db.endTransaction();
}
/* USING a TRIGGER (not intended to make sense/do anything useful just demo) */
private static final String CREATETRIGGERSQL = "CREATE TRIGGER IF NOT EXISTS theTrigger AFTER UPDATE ON visits BEGIN DELETE FROM weight WHERE id_weight=5; INSERT OR IGNORE INTO visits (date) VALUES(strftime('%s','now')); END";
static Callback cb = new Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
db.execSQL(CREATETRIGGERSQL);
}
@Override
public void onDestructiveMigration(@NonNull SupportSQLiteDatabase db) {
super.onDestructiveMigration(db);
}
@Override
public void onOpen(@NonNull SupportSQLiteDatabase db) {
super.onOpen(db);
db.execSQL(CREATETRIGGERSQL);
}
};
}
要實際利用上面的一些活動程式碼MainActivity
#
public class MainActivity extends AppCompatActivity {
TheDatabase roomInstance;
AllDao dao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
roomInstance = TheDatabase.getINSTANCE(this);
dao = roomInstance.getAllDao();
dao.insert(new Visits()); /* Insert a row */
/* Solution 2 - via Trigger */
dao.resetVisitData(System.currentTimeMillis() - (24 * 60 * 60 * 7 /* one week ago BUT OOOPS not divided by 1000 */));
/* Solution 1 - via abstract class aka method with body */
dao.doBoth(System.currentTimeMillis() / 1000);
/* Solution 3 - via SupportSQLiteDatabase */
roomInstance.viaSupportSB(System.currentTimeMillis() + (24 * 60 * 60 * 7 /*week in the future again OOOPS not divided by 1000*/));
/* Expected result
1. sinlge row inserted into visits
2. trigger adds another row into visits (row 2)
3. doBoth updates so another row added to visits (row 3)
4. via SupportSQLiteDatabase updates so another row added to visits (row 4)
So 4 rows in visits no rows in weight
*/
}
}
您所嘗試的操作在介面中是不可能的,因為您不能在介面中使用帶有主體的方法。
更具體地說,您嘗試執行多個語句(一條 UPDATE,然後一條 DELETE),但同時只能執行一條語句。
您的選擇是定義一個觸發器(更新後,如果可以從觸發器內確定權重行)或可能更可能使用抽象類,從而使用一個函數來執行多個語句或使用利用的方法(傳遞/或檢索)SupportSQliteDatabase(使用抽象類別更簡單)。
然後,要利用事務,您將在函數之前有一個虛擬的@Query。例如
#附加
這是一個工作演示,設計為僅運行一次,它使用所有三種方法。
首先是
@Entities
,基於程式碼中可用的內容,但已使用 long 來表示日期(而不是使用類型轉換器)。訪問
重量
@Dao
附註解的抽象類,具有普通的抽象方法和帶主體的方法(解決方案 1)。 insert 方法允許插入一些資料(僅一行)。現在,
@Database
帶註解的類別(使用單例)稍微複雜一些。這有一個回調來添加觸發器,觸發器過於複雜,因為它不僅在更新後進行刪除(不是刪除任何內容),而且還在訪問表中添加一個新行顯示TRIGGER 實際上正在被觸發(解決方案2)。
此外,由於需要更好的地方(或不取決於風格/實踐),包含一個函數來取得和使用 SupportSQLiteDatabase(解決方案 3)
要實際利用上面的一些活動程式碼MainActivity
#示範結果 透過 SppInspection
正如預期的重量表是空的:-
如預期的那樣,存取表中有 4 行:-
最後,架構(即 sqlite_master)顯示觸發器存在(必須新增額外的 3 行):-