3.4.5.1. 编程式事务管理

编程式事务管理使用 com.haulmont.cuba.core.Transaction 接口完成。可以通过Persistence基础接口的 createTransaction()getTransaction() 方法获得对它的引用。

createTransaction() 方法创建一个新事务并返回 Transaction 接口。后续调用此接口的 commit()commitRetaining()end() 方法控制创建的事务。如果在创建时有另一个活动的事务,它将先暂停并在新创建的事务完成后恢复。

getTransaction() 方法要么创建新事务,要么附加到已有事务并返回一个嵌套事务。如果在调用时有一个活动的当前事务,那么该方法会成功完成,但后续调用嵌套事务的 commit()commitRetaining()end() 方法对当前事务没有影响。但是,在没有调用嵌套事务的 commit() 方法的情况下调用 end() 方法,会将当前事务标记为 RollbackOnly。简单来说,就是只有嵌套事务成功提交了,外层事务才能提交。

编程式事务管理的示例:

@Inject
private Metadata metadata;
@Inject
private Persistence persistence;
...
// try-with-resources style
try (Transaction tx = persistence.createTransaction()) {
    Customer customer = metadata.create(Customer.class);
    customer.setName("John Smith");
    persistence.getEntityManager().persist(customer);
    tx.commit();
}
// plain style
Transaction tx = persistence.createTransaction();
try {
    Customer customer = metadata.create(Customer.class);
    customer.setName("John Smith");
    persistence.getEntityManager().persist(customer);
    tx.commit();
} finally {
    tx.end();
}

Transaction 接口还有 execute() 方法接受 action 类或 lambda 表达式。action 类或 lambda 表达式表示的操作将在事务中执行。这样可以以函数式编程风格组织事务管理,例如:

UUID customerId = persistence.createTransaction().execute((EntityManager em) -> {
    Customer customer = metadata.create(Customer.class);
    customer.setName("ABC");
    em.persist(customer);
    return customer.getId();
});

Customer customer = persistence.createTransaction().execute(em ->
        em.find(Customer.class, customerId, "_local"));

需要注意,给定 Transaction 实例的 execute() 方法只能调用一次,因为事务在执行完操作代码后结束。