@Transactional

使用 @Transactional 注释方法,所有数据库查询和更改都将在单个事务中发生。

事务将使用 默认数据库,放入“线程本地作用域”,并在方法成功完成时提交。

@Transactional
public void process(OffsetDateTime startOffset) {
  ...
  customer.save();
  contact.save();
}

Transaction.current()

使用 Transaction.current()默认数据库 的“线程本地作用域”返回当前事务。

@Transactional
public void process(OffsetDateTime startOffset) {
  ...
  Transaction txn = Transaction.current();
  ...
}

使用 database.currentTransaction() 返回给定数据库的当前事务,该数据库通常不是默认数据库。

Database otherDb = DB.byName("other");

Transaction txn = otherDb.currentTransaction();

beginTransaction()

作为 @Transactional 的替代方法,我们可以使用 beginTransaction() 来启动一个显式事务。事务被放入“线程本地作用域”,并被任何后续查询、保存、删除等使用。

我们应该使用 try with resources 块来确保在块中发生任何错误时关闭事务。

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

  // do stuff...
  Customer customer = ...
  customer.save();

  Order order = ...
  order.save();

  transaction.commit();
}

Kotlin transaction.use { }

Kotlin use 的用法类似于 try with resources,以确保事务关闭。

DB.beginTransaction().use { transaction ->

  // do stuff...
  val customer = ...
  customer.save();

  val order = ...
  order.save();

  transaction.commit()
}

commit()、rollback()、end()

通常,对于 try with resources 块,我们不需要显式调用 transaction.rollback()transaction.end(),如上面 beginTransaction() 的示例所示。

rollback() 将回滚事务,我们通常在 catch 块中使用它。

end() 将回滚事务(如果尚未提交)。我们主要在 finally 块中使用 end()

Transaction transaction = DB.beginTransaction()
try {
  // do stuff...
  Customer customer = ...
  customer.save();

  Order order = ...
  order.save();

  transaction.commit();

} catch (SomeException e) {
  transaction.rollback();

} finally {
  transaction.end();  // rollback if not committed
}

commitAndContinue()

有时在较大的事务中,我们到达一个点,希望提交到此点的更改,但随后继续处理后续更改,这些更改可能失败。我们为此使用 transaction.commitAndContinue()

setRollbackOnly()

我们使用 transaction.setRollbackOnly(),以便事务不会提交,只会回滚。

当某些处理具有某种“预览”模式时,我们可以使用它,在这种模式下,我们处理更改,但随后不提交。这在某些测试场景中也很有用。

createTransaction()

database.createTransaction() 将创建一个事务,但它 不会 被放入“线程本地作用域”。我们通常在需要在各个线程之间传递事务时使用它。

例如:启动事务,获取行锁,如果成功,则通过后台线程将事务传递给任务执行。

当我们使用 createTransaction() 时,我们必须在查询和保存等操作中显式使用事务。我们通过查询 bean 显式指定事务,方法是 ... 和 model.save(transaction) 等。

try (Transaction transaction = DB.getDefault().createTransaction()) {

  ...
  var customer = new QCustomer(transaction) // explicit transaction
    .name.eq("Rob")
    .findOne();
  ...
  customer.update(transaction);  // explicit transaction

}

隐式事务

当没有显式指定事务时,Ebean 将创建一个事务来执行操作。

查询 - 只读事务

对于查询,Ebean 将尝试使用只读事务。如果已配置 只读数据源,Ebean 将尝试默认使用该数据源。

插入、更新、删除

对于所有持久化请求,如保存、插入、更新、删除,Ebean 将创建一个事务并在操作结束时执行 COMMIT