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