保存点

Ebean 支持使用 Savepoints,这是大多数关系数据库的一个功能,我们可以在事务中创建保存点(嵌套事务),该事务可以作为工作单元提交或回滚。

如果我们有一个执行某些操作的任务,这些操作可能会失败/回滚,但不想丢失整个事务的所有工作,Savepoint 提供了一种执行此操作的机制。您可以在 Oracle 的 JDBC 教程 中查看更多信息

Transaction.setNestedUseSavepoint()

对于事务,我们可以使用 transaction.setNestedUseSavepoint() 启用它以使用 Savepoint 进行嵌套事务。这意味着这些嵌套事务可以回滚,而外部事务可以继续进行并可能提交。

示例
// start 'outer' transaction
try (Transaction outerTxn = database.beginTransaction()) {

  outerTxn.setNestedUseSavepoint();

  // do stuff with the 'outer' transaction
  bean.save();

  try (Transaction nestedTransaction = database.beginTransaction()) {
    // nested transaction is a savepoint ...

    // do some piece of work which we might want to either commit or rollback ...
    otherBean.save();

    if (...) {
      nestedTransaction.rollback();

    } else {
      nestedTransaction.commit();
    }
  }

  // continue using 'outer' transaction ...

  outerTxn.commit();
}

显式保存点

作为使用 transaction.setNestedUseSavepoint() 的替代方法,我们可以通过从事务中获取 JDBC Connection 来显式创建和使用保存点。

例如

var newCustomer = new Customer();
newCustomer.setName("John");
newCustomer.save();

try (Transaction transaction = DB.beginTransaction()) {

  Connection connection = transaction.getConnection();

  // create a Savepoint
  Savepoint savepoint = connection.setSavepoint();

  newCustomer.setName("Doe");
  newCustomer.save();

  // Rollback to a specific save point
  connection.rollback(savepoint);
  transaction.commit();
}

var found = DB.find(Customer.class, newCustomer.getId());
System.out.println(found.getName()); // Prints "John"