3.4.5.1. 编程式事务管理

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

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

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

编程式事务管理的示例:

  1. @Inject
  2. private Metadata metadata;
  3. @Inject
  4. private Persistence persistence;
  5. ...
  6. // try-with-resources style
  7. try (Transaction tx = persistence.createTransaction()) {
  8. Customer customer = metadata.create(Customer.class);
  9. customer.setName("John Smith");
  10. persistence.getEntityManager().persist(customer);
  11. tx.commit();
  12. }
  13. // plain style
  14. Transaction tx = persistence.createTransaction();
  15. try {
  16. Customer customer = metadata.create(Customer.class);
  17. customer.setName("John Smith");
  18. persistence.getEntityManager().persist(customer);
  19. tx.commit();
  20. } finally {
  21. tx.end();
  22. }

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

  1. UUID customerId = persistence.createTransaction().execute((EntityManager em) -> {
  2. Customer customer = metadata.create(Customer.class);
  3. customer.setName("ABC");
  4. em.persist(customer);
  5. return customer.getId();
  6. });
  7. Customer customer = persistence.createTransaction().execute(em ->
  8. em.find(Customer.class, customerId, "_local"));

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