如何在Room数据库中执行事务操作以删除某些表 android

How to perform transaction operation in Room database to delete some tables android

提问人:kartheeki j 提问时间:1/31/2023 更新时间:2/1/2023 访问量:311

问:

我不熟悉房间数据库。我想在单击按钮时清除某些表中的数据。我在IOS中有类似的代码,但我不确定在哪里编写此方法并调用此删除函数以及如何访问表。任何人都可以在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")
        }
    }
}
sql android-room sqltransaction

评论


答:

1赞 MikeT 2/1/2023 #1

如果使用Room,您将拥有

  1. @Entity带注释的类(表),

  2. 每个数据库一个带注释的类(很可能只是 1):-@Database

    1.描述数据库(通过参数列出实体列表(即表,又名带注释的类)@Entityentities

    1. 提供用于获取注解(接口或抽象类)的抽象方法@Dao
  3. 一个或多个带注释的接口和/或抽象类,其中@Dao

    1. 详细说明了便捷方法(、、)和方法。@Insert@Delete@Update@Query

由于您似乎希望在单个事务中执行许多操作,因此您需要一个调用这些操作的方法。

接口不能有带函数的方法,因此需要一个带注释的类。@Dao

实际上,做很多事情的方法有点技巧。

你首先有一个注释。由于 room 似乎不考虑此注释,除非您正在使用其中一个注释(并且唯一可以定制的注释是 ),因此您告诉 Room 运行一个不执行任何操作的查询,即使用 .@Transaction@Query@Query("")

使用主体定义方法,该主体可以调用带注释的抽象类中的其他方法。@Dao

所以你的代码可以是这样的:-

@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
   }
}

然后,在代码的某个地方,你得到一个实例抽象类,其中构建了 RoomDatabase,然后通过带注释的抽象类中的抽象方法获取相应的带注释的接口/类实例后,检索并调用相应的方法 ()。@DatabasedoLotsOfThinsInASingleTransaction@Dao@Database

下面是一个示例(未运行,但已成功编译)

一些带注释的类(非常基本,因为它与表格的复杂性/设计无关):-@Entity

@Entity
class UserLocations {
    @PrimaryKey Long id=null;
    String user_name;
}

@Entity
class LineLayoutEquipment {
    @PrimaryKey Long id=null;
    String lle_name;
}
  • 显然,您的课程很可能会有所不同,这无关紧要

带注释的抽象类(而不是更典型的接口(抽象类由于带有主体的方法而更灵活)):-@Dao

@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@Database@Dao

带注释的抽象类(单例):-@Database

@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();

    }
}

因此,您需要做的就是确保已将 db 和 dao 实例化为侦听器,并使用最后一行(如果遵循约定,则关闭主线程)。

评论

0赞 kartheeki j 2/1/2023
T 感谢您的详细解释。如果发生任何故障,我可以知道如何进行回滚操作吗(如上面的ios代码)
0赞 MikeT 2/1/2023
@kartheekij 根据 developer.android.com/reference/androidx/room/Transaction:- 除非在方法主体中抛出异常,否则事务将被标记为成功。