【问题标题】:JPA and EJB - When do I need to use transaction?JPA 和 EJB - 我什么时候需要使用事务?
【发布时间】:2016-04-16 13:47:01
【问题描述】:

我正在按照一些教程学习 Java 中的持久性。

我正在使用 Java EE 7 和 Payara 服务器。

我注意到每个人都使用不同的持久性方法。

例子:

  • 简单

    @Stateless
    public class BookServiceBean implements BookService {
        @PersistenceContext
        private EntityManager em;
    
        public void createOrUpdate(Book book) {
            em.persist(book);
        }
        public void remove(Book book) {
            em.remove(book);
        }
    }
    
  • 使用flush(),当persistene.xml 中未将验证策略设置为“AUTO”时使用,对吗?

    @Stateless
    public class BookServiceBean implements BookService {
        @PersistenceContext
        private EntityManager em;
    
        public void createOrUpdate(Book book) {
            em.persist(book);
            em.flush();
        }
        public void remove(Book book) {
            em.remove(book);
            em.flush();
        }
    }
    
  • 有交易

    @Stateless
    public class BookServiceBean implements BookService {
        @PersistenceContext
        private EntityManager em;
    
        public void createOrUpdate(Book book) {
            utx.begin();
            em.persist(book);
            utx.commit();
        }
        public void remove(Book book) {
            utx.begin();
            em.remove(book);
            utx.commit();
        }
    }
    

什么时候以及为什么我必须使用最后一个?

每个方法的末尾都需要em.close()吗?

有哪些好的做法?

【问题讨论】:

  • 可以使用javax.ejb.TransactionAttribute注解检查stackoverflow.com/a/6863264/916225
  • 无状态 EJB 默认是事务性的。在代码中显式启动和提交事务正是无状态 bean 允许避免的。所以没有理由在代码中启动和提交事务。让容器为你做这件事。

标签: jpa jakarta-ee transactions ejb jta


【解决方案1】:

第一种方法是一种 EJB 方法,无需手动刷新和事务模糊,是规范方法。默认情况下,单个 EJB 方法调用已计为单个完整事务。 EJB 容器将在调用方法之前透明地开始事务,并在方法返回时提交事务(或在方法抛出应用程序异常时回滚)。

第二个示例中的手动刷新是不必要的。通常,您只想在修改实体时使用em.flush()(即使其“变脏”),并希望之后(间接)在同一事务中对其执行SELECT。这种情况很少见,但在现实世界中也有它的用例,通常是当您想SELECT 其脏实体是其子级的父级时。

第三个例子中的手动事务管理是完全没有必要的。在阅读了第一段之后,您应该已经意识到这一点。仅当您不使用JTA,而是使用RESOURCE_LOCAL(通常在Java SE 而非Java EE 中)时,才需要手动事务管理。

另见:

【讨论】:

  • 请注意,即使持久性上下文是脏的,JPA 引擎也应该在执行查询之前刷新,其结果可能取决于脏实体。我在 Hibernate 的一个非常特殊的情况下看到了该机制的错误,但总的来说,它不是必需的。
  • 确实,我记得 Hibernate 相关的错误只能通过显式刷新来解决。
猜你喜欢
  • 1970-01-01
  • 2013-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-04
  • 2015-05-26
  • 1970-01-01
相关资源
最近更新 更多