【问题标题】:Android Room transactions across DAOs跨 DAO 的 Android Room 交易
【发布时间】:2018-06-18 05:47:03
【问题描述】:

官方文档指出:

It is recommended to have multiple Dao classes in your codebase depending on the tables they touch.

并且可以像这样使用 Transaction 注释标记方法:

 @Dao
 public abstract class ProductDao {
    @Insert
     public abstract void insert(Product product);
    @Delete
     public abstract void delete(Product product);
    @Transaction
     public void insertAndDeleteInTransaction(Product newProduct, Product oldProduct) {
         // Anything inside this method runs in a single transaction.
         insert(newProduct);
         delete(oldProduct);
     }
 }

但是如果一个事务跨越多个 DAO 怎么办?我应该将所有 DAO 合并为一个以支持交易,还是有更好的方法来做到这一点?

【问题讨论】:

    标签: android sqlite persistence dao android-room


    【解决方案1】:

    事实 1: 在方法上使用@Transaction 会导致该方法在 Dao_Impl 生成的类中被覆盖。这个方法看起来像这样:

      @Override
      public void makeFieldInactive(final long fieldId) {
          __db.beginTransaction();
          try {
              MyDao_Impl.super.makeFieldInactive(fieldId);
              __db.setTransactionSuccessful();
          } finally {
              __db.endTransaction();
          }
      }
    

    事实 2: runInTransaction() 方法如下所示:

    /**
     * Executes the specified {@link Runnable} in a database transaction. The transaction will be
     * marked as successful unless an exception is thrown in the {@link Runnable}.
     * <p>
     * Room will only perform at most one transaction at a time.
     *
     * @param body The piece of code to execute.
     */
    @SuppressWarnings("deprecation")
    public void runInTransaction(@NonNull Runnable body) {
        beginTransaction();
        try {
            body.run();
            setTransactionSuccessful();
        } finally {
            endTransaction();
        }
    }
    

    结论: 他们都做同样的事情。

    更多信息: 我已经进行了一些测试,似乎使用其中任何一个(或同时使用两者,冗余)将成功地使您的 Dao 方法在一个事务中运行。

    答案: 在访问同一数据库的多个 Daos 中进行更改的方法上使用 @Transaction 是一种安全的方法,可以确保该方法中发生的所有数据库操作都发生在一个事务中。

    编辑: 使用标记为 @Transactoin:

    的一种方法访问multipe Dao 的示例
    @Transaction
     public void addItem(ItemEntity item) {
            item.setId(insert(item));
            ItemReportDao itemReportDao = AppDatabase.getIntance().itemReportDao();
            itemReportDao.addItemReport(item.getId());
    }
    

    【讨论】:

    • 您能否提供一个“@Transaction 对访问同一数据库的多个 Daos 进行更改的方法”的示例?您是否使用@Transaction 标记了“@Dao”之外的代码,并且 Room 成功生成了代码?
    • “@Transaction”注释必须在标记为“@Dao”的抽象类之一中。然后,标记为“@Transaction”的方法可以从它所包含的“@Dao”类中使用多个“@Dao”类。(标记为“@Dao”的接口必须转换为抽象类才能包含方法)跨度>
    【解决方案2】:

    您可以使用RoomDatabase.runInTransaction(...)

    类似:

    database.runInTransaction(new Runnable(){
      @Override
      public void run(){
        Access all your daos here
      }
    });
    

    【讨论】:

    • 每个单独的插入、更新或删除语句也在事务中运行会不会有问题。您将获得嵌套事务
    • 不,你不能在这里访问 DAO
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-25
    • 2018-04-19
    • 2018-09-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 2018-02-20
    相关资源
    最近更新 更多