事务管理器

TransactionManager事务管理器是用于管理批量数据库操作的类。对于恢复在大量数据更新、保存或删除时的数据非常有用。它同样被包装为了本地方法,使你能够非常简单地使用事务。这个类不仅提供了同步执行的方法,也支持异步执行,防止UI线程被大量数据库操作堵塞。

TransactionManager主要使用DBTransactionQueue。这个队列(Queue)基于Volley框架的VolleyRequestQueueVolleyRequestQueue使用的是PriorityBlockingQueue。这种队列采用优先级的方式对数据库的各个事务进行排序,主要有这些优先级:

  1. UI: 保证事务能够被立刻执行以显式到UI中。
  2. HIGH: 保留的任务,将影响用户的互动。比如在未来显示数据。
  3. NORMAL: Transaction的默认优先级,很适合在app不需要立刻得到结果的情况下。
  4. LOW: 低优先级,适合一些不必要的事务。

DBTransactionInfo:用于保存DBTransactionQueue如何处理BaseTransaction的一些信息,包含名称和优先级。名称是为了在Debug的时候能更容易区分各个事务。

优先级在内部是一个整数值,所以你可以自定义事务的优先级、或者是自定义优先级的大小。

在高级的使用中,你可以使用TableTransactionManager或者继承TransactionManager来自定义自己的DBTransactionQueue,这样你就可以使用自定义的事务管理类更灵活地管理事务了。

批量操作

将大量数据保存到数据库而不阻塞主线程,在以前我们是这样做的:

  new Thread() {
    @Override
    public void run(){
        database.beginTransaction();
        try {
            for(ModelClass model: models){
              // save model here
            }
            database.setTransactionSuccessful();
        } finally {
            database.endTransaction();
        }
    }
  }.start();

而现在我们只需要使用更为简单的方式即可完成:

TransactionManager.getInstance().addTransaction(new SaveModelTransaction<>(ProcessModelInfo.withModels(models)));

Model的批量处理

ProcessModelInfo:描述保存了事务相关的信息,比如包括DBTransactionInfo、表、一些Model和TransactionListener事务回调。

NOTE:这个类可以通过TransactionManager中的方法很简单的创建。

对于大量的操作更好的方式是通过DBTransactionQueue来执行,这样能有效优化由多线程同步或主线程操作带来的阻塞。

大量save()操作,首选的方法是DBBatchSaveQueue,它将会运行一个DBTransaction并一次性填满(默认情况下是50个Models,但也可以设置)。而对于少量的保存操作,更好的方式是定期保存。

示例

  ProcessModelInfo<SomeModel> processModelInfo = ProcessModelInfo<SomeModel>.withModels(models)
                                                                            .result(resultReceiver)
                                                                            .info(myInfo);

  TransactionManager.getInstance().saveOnSaveQueue(models);

  // 或者添加到队列
  TransactionManager.getInstance().addTransaction(new SaveModelTransaction<>(processModelInfo));

  // Updating only updates on the ``DBTransactionQueue``
  TransactionManager.getInstance().addTransaction(new UpdateModelListTransaction(processModelInfo));

  TransactionManager.getInstance().addTransaction(new DeleteModelListTransaction(processModelInfo));

TransactionManager中还有各种各样的方法对DBTransactionQueue进行排序和操作。

接收结果

SelectListTransactionSelectSingleModelTransaction将会在DBTransactionQueue中产生一个SELECT操作。当它们的操作完成将会在UI线程回调TransactionListener函数。一个普通的SELECT操作则会在当前线程完成,对于简单的查询操作这样也没问题,但更好的方式是通过DBTransactionQueue事务来完成,以减少对主线程的阻塞。

  // 获取表中的所有数据
  // 你也可以加入条件语句进行更为复杂的查询
  TransactionManager.getInstance().addTransaction(new SelectListTransaction<>(new TransactionListenerAdapter<TestModel.class>() {
     @Override
    public void onResultReceived(List<TestModel> testModels) {
        // 这里会在UI线程被执行
    }
  }, TestModel.class, condition1, condition2,..);

自定义事务类

DBFlow也支持你很简单地创建自定义的事务类,通过以下方法即可将它们添加到TransactionManager中执行:

TransactionManager.getInstance().addTransaction(myTransaction);

这里是一些你可以创建的自定义事务:

  • 继承BaseTransaction类,你可以在onExecute()方法中定义你要完成的事情:

    BaseTransaction<TestModel1> testModel1BaseTransaction = new BaseTransaction<TestModel1>() {
      @Override
      public TestModel1 onExecute() {
          // do something and return an object
          return testModel;
      }
    };
    
  • BaseResultTransaction类则加入了一个简单的TransactionListener回调函数,让你可以监听到事务的更新状态:

    BaseResultTransaction<TestModel1> baseResultTransaction = new BaseResultTransaction<TestModel1>(dbTransactionInfo, transactionListener) {
      @Override
      public TestModel1 onExecute() {
          return testmodel;
      }
    };
    
  • ProcessModelTransaction让你能够定义如何处理DBTransactionQueue中的每一个model:

    
    public class CustomProcessModelTransaction<ModelClass extends Model> extends ProcessModelTransaction<ModelClass> {
    
      public CustomProcessModelTransaction(ProcessModelInfo<ModelClass> modelInfo) {
          super(modelInfo);
      }
    
      @Override
      public void processModel(ModelClass model) {
         // process model class here!
      }
    }
    
  • QueryTransaction让你能够使用Queriable操作检索数据库。

    // any Where, From, Insert, Set, and StringQuery all are valid parameters
    TransactionManager.getInstance().addTransaction(new QueryTransaction(DBTransactionInfo.create(),
    SQLite.delete().from(MyTable.class).where(MyTable_Table.name.is("Deleters"))));