![](/img/trans.png)
[英]Android Room JUnit testing: "AsyncTask #1" java.lang.IllegalStateException: Cannot perform this operation because there is no current transaction
[英]How to perform transaction operation in Room database to delete some tables android
我不熟悉房間數據庫。 我想在單擊按鈕時清除某些表中的數據。 我在 IOS 中有類似的代碼,但我不確定必須在哪里編寫此方法並調用此 delete function 以及如何訪問表。 任何人都可以在 android 中幫助我解決這個問題。
IOS 代碼:
class ApplicationResetManager: NSObject {
static let shared: ApplicationResetManager = ApplicationResetManager()
var cloSuccess:((_ isSuccessfull: Bool)->Void)?
func clearAllData(completion: (Bool) -> Void) {
let isSyncGoingOn = ApplicationManager.shared.isSyncGoingOn
if let currentUser = ApplicationManager.shared.currentUser, currentUser.id! > 0, isSyncGoingOn == false {
let dbQueue = DatabaseManager.shared.dbQueue!
do {
// 4. Access the database
try dbQueue.inTransaction { db in
do {
try UserLocations.deleteAll(db)
try LineLayoutEquipment.deleteAll(db)
try LineLayout.deleteAll(db)
try Survey.deleteAll(db)
try HealthCheck.deleteAll(db)
try HealthCheckData.deleteAll(db)
try ActionItem.deleteAll(db)
try Equipments.deleteAll(db)
try EquipmentIndustry.deleteAll(db)
try Comments.deleteAll(db)
try PlantAreas.deleteAll(db)
try PlantAreasIndustrys.deleteAll(db)
try Applications.deleteAll(db)
try ApplicationsIndustrys.deleteAll(db)
try SurveyLineLevel.deleteAll(db)
try HealthCheckLineLevel.deleteAll(db)
try ActionItemLineLevel.deleteAll(db)
try ActionItemLineLvlComments.deleteAll(db)
UserDefaults.standard.set([], forKey: arr_selected_company)
ApplicationManager.shared.currentUser.defaultCompanyId = nil
completion(true)
return .commit
} catch {
completion(false)
return .rollback
}
}
} catch {
completion(false)
}
} else {
print("Sync is already in progress")
}
}
}
如果使用 Room 你會有
@Entity
注釋類(表),
每個數據庫(很可能只是第一個)注釋為 class 的單個@Database
:-
1.通過entities
參數描述數據庫(實體列表(即表又名@Entity
注釋類))
@Dao
注釋的抽象方法(接口或抽象類) 一個或多個@Dao
注釋接口和/或抽象類
@Delete
、@ @Query
@Update
@Insert
由於您似乎想在單個事務中做很多事情,因此您需要一個調用這些許多操作的方法。
接口不能有帶函數的方法,因此您需要一個帶注釋的@Dao
class。
實際上,do many things 方法有點小技巧。
您首先有一個@Transaction
注釋。 由於 room 似乎不考慮此注釋,除非您使用注釋之一(並且唯一可以定制的注釋是@Query
),然后您告訴 Room 運行一個不執行任何操作的查詢,即使用@Query("")
。
您定義方法的主體可以調用@Dao
注釋摘要 class 中的其他方法。
所以你的代碼可能是這樣的:-
@Dao
abstract class MyDoitAllStuffDao {
@Query("DELETE FROM userLocations") /* no WHERE clauses = delete all rows. TO BE USED IN DO IT ALL METHOD*/
int deleteAllUserLocations();
@Query("DELETE FROM linelayoutequipment");
int deleteAllLineLayoutEquipment();
....
@Transaction
@Query("") /* trick room into think it is doing something */
void /* or some useful return type */ doLotsOfThingsInASingleTransaction() {
.... if you want to do preparotory stuff
int deleteAllUserLocations_count = deleteAllUserLocations();
int deleteAllLineLayout_count = deleteAllLineLayoutEquipment();
.... etc
}
}
然后在你的代碼中的某個地方你得到一個實例@Database
abstract class 構建了 RoomDatabase 然后檢索然后調用適當的方法( doLotsOfThinsInASingleTransaction
)通過@Database
注釋抽象中的抽象方法獲取相應的@Dao
注釋接口/類實例class。
這是一個示例(未運行但編譯成功)
一些@Entity
注釋類(非常基本,因為它與表的復雜性/設計無關):-
@Entity
class UserLocations {
@PrimaryKey Long id=null;
String user_name;
}
@Entity
class LineLayoutEquipment {
@PrimaryKey Long id=null;
String lle_name;
}
@Dao
注釋的抽象 class(而不是更典型的接口(抽象 class 由於帶有主體的方法更靈活)):-
@Dao
abstract class MyDoitAllStuffDao {
@Query("DELETE FROM userLocations")
abstract void deleteAllUserLocations();
@Query("DELETE FROM linelayoutequipment")
abstract void deleteAllLineLayoutEquipment();
@Transaction
@Query("")
void doLotsOfThingsInASingleTransaction() {
deleteAllUserLocations();
deleteAllLineLayoutEquipment();
}
}
@Database
注釋 class 之后編寫這些代碼,但在@Database
注釋 class 之前包含它更有意義,當完成時需要@Dao
注釋類 @Database
注釋摘要 class(單例):-
@Database(
entities = {UserLocations.class,LineLayoutEquipment.class},
exportSchema = false,
version = 1
)
abstract class TheDatabase extends RoomDatabase {
abstract MyDoitAllStuffDao getMyDoitAllStuffDao();
private static TheDatabase INSTANCE;
static TheDatabase getInstance(Context context) {
if (INSTANCE==null) {
return Room.databaseBuilder(context,TheDatabase.class,"the_database.db")
.build();
}
return INSTANCE;
}
}
最后在活動代碼中使用上面的內容,例如:-
public class MainActivity extends AppCompatActivity {
TheDatabase db;
MyDoitAllStuffDao dao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = TheDatabase.getInstance(this);
dao = db.getMyDoitAllStuffDao();
dao.doLotsOfThingsInASingleTransaction();
}
}
所以你需要做的就是確保你已經用 scope 為監聽器實例化了 db 和 dao 並使用最后一行(如果遵循約定,則在主線程之外)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.