【问题标题】:JTA with PersistenceUnit带有 PersistenceUnit 的 JTA
【发布时间】:2013-01-20 22:36:16
【问题描述】:

@PersistenceUnit 可以与 JPA 中的 JTA 一起使用吗?如果有,怎么可能?

http://tomee.apache.org/jpa-concepts.html:

<persistence-unit transaction-type="RESOURCE_LOCAL">[...]

  • 您必须使用 EntityManagerFactory 来获取 EntityManager
  • [...]
  • EntityManagerFactory 只能通过@PersistenceUnit 注解注入(不能通过@PersistenceContext)

<persistence-unit transaction-type="JTA">[...]

  • EntityManager 只能通过@PersistenceContext 注解注入(不能通过@PersistenceUnit)

我有一个类似的代码,它同时使用 JTA 和 @PersistenceUnit。但有时我在访问事务时遇到NullPointerException(定义为@Resource)。

【问题讨论】:

标签: java hibernate jpa


【解决方案1】:

使用 JTA 意味着您将工作委托给容器。您可以使用UserTransaction 覆盖它。您的报价包含您想知道的所有答案。使用PersistenceUnit 获取EntityManager 是行不通的。

如果您使用RESOURCE_LOCAL,您需要对交易本身负责,使用EntityManager.getTransaction()。实体管理器由EntityManagerFactory 创建。要获取该工厂,您可以使用PersistenceUnit

如果您依赖容器管理的实体管理器,那么简单的答案是否定的。

例如见http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html

应用程序托管实体管理器 = RESOURCE_LOCAL 可以使用 UserTransaction(它们是 JTA 的一部分)。

【讨论】:

    【解决方案2】:

    实体管理器是什么意思??? 如果我是一个天真的程序员,我可以简单地解释一些管理实体的东西,实际上它的意思是一样的。

    实体管理器是在实体管理器工厂的帮助下实例化的。与数据库的连接由实体管理器管理,即它提供对数据库执行操作的功能。因此我们可以说,如果应用程序需要多个数据库连接,将为特定数据库构建一个 EntityManagerFactory,它提供了一种构建多个 EntityManager 实例的有效方法(如果需要,即使是单个实体管理器实例也可以根据您可能的要求来工作选择多个实例)用于每个 HTTP 请求所需的数据库。我们将借助一个例子来理解这一点。假设我们有一个 数据库:A,具有关系表 B 和 C。 所以对于 A,实体管理器工厂的一个实例将被实例化。现在,如果我们想要对表 B 执行任何更新并假设对表 C 进行删除操作,则可以实例化两个不同的实体管理器,或者可以对两者使用相同的实体管理器实例。 实体管理器工厂本身的实例化被认为效率较低,但由于它是一次性活动,因此它是可管理的任务,因为实体管理器工厂一旦实例化,它将服务于整个应用程序 实例化的实体管理器与持久化上下文相关联。

    @PersistenceUnit(unitName = "MyDatabase")
    EntityManagerFactory emf;
    EntityManager entityManager = emf.createEntityManager();
    

    @PersistenceContext(unitName = "MyDatabase") 
    private EntityManager entityManager;
    

    PersistenceUnit 注入一个 EntityManagerFactory,而 PersistenceContext 注入一个 EntityManager。除非您确实需要手动管理 EntityManager 生命周期,否则通常最好使用 PersistenceContext。 EntityManagerFactory 定义了另一种实例化 EntityManager 的方法,该方法与工厂一样,将属性映射作为参数。当必须指定 EntityManagerFactory 的默认用户名和密码以外的用户名和密码时,此表单很有用:

    Map properties = new HashMap(); 
    properties.put("javax.persistence.jdbc.user", "kashyap");
    properties.put("javax.persistence.jdbc.password","kashyap"); 
    EntityManager em = emf.createEntityManager(properties);
    

    在持久化上下文中,管理实体实例及其生命周期。实体实例是指一个实体的实例,每个实体指定数据库中的关系表。实体管理器实际上是一个接口,它提供了创建和删除持久实体实例、通过主键查找实体以及查询实体的方法,因此这些功能一起分组在我们执行的操作下。修改数据库内容的操作需要活动事务。事务由从 EntityManager 获得的 Entity Transaction 实例管理。 精确定义:- 实体管理器由持久性单元定义。持久性单元定义了与应用程序相关或分组的所有类的集合,并且必须在它们到单个数据库的映射中并置。 下面我正在编写一个代码 sn-p 以便更好地理解:-

    try {
            em.getTransaction().begin();
            // Operations that modify the database should come here.
            em.getTransaction
            /**
            *getTransaction() EntityManager's method Return the resource-level EntityTransaction object. See JavaDoc Reference Page
            */
            em.getTransaction().commit();
      }
      finally {
            if (em.getTransaction().isActive())
                em.getTransaction().rollback();
      }
    

    让我们按照 JPA 规范进行:- 1)扩展与事务 - 范围: 默认情况下,使用事务持久性上下文,这意味着所有更改都被刷新,并且所有托管实体在当前事务提交时都变得分离。 扩展范围仅适用于有状态 EJB,它甚至非常有意义,因为有状态 bean 可以保存状态,因此可以说结束 一种业务方法并不一定意味着交易的结束。 对于无状态 bean,它有一个不同的方面——我们有业务方法必须在业务方法完成时结束。 ===> 一种方法 = 一种交易; 无状态 Bean 只允许事务范围的实体管理器 您可以在 EntityManager 注入期间控制 EntityManager 是扩展的还是事务性的:-

    @PersistenceContext (type = javax.persistence.PersistenceContextType.EXTENDED)
        EntityManager emng;
    

    默认是 javax.persistence.PersistenceContextType.TRANSACTION Extended 和 Transaction Scoped PersistenceContext 仅在容器管理的 EntityManager 的情况下才允许使用。 是时候加强一点了:容器管理与应用程序管理 2) 容器管理 vs 应用程序管理:

    @PersistenceContext
    EntityManager emng;
    

    上面的语句授权 Container 为你注入实体管理器,因此是 Container-Managed。 或者,您可以使用 EntityManagerFactory 自己创建一个 EntityManager 但这一次注入会有点不同 -

    @PersistenceUnit
    EntityManagerFactory emf;
    

    现在获取您需要调用的 EntityManager

    emf.createEntityManager();
    

    就是这样 - 您正在使用应用程序管理的持久性上下文。现在您负责创建和删除 EntityManager。 在阅读下一段之前先集中注意力,因为这就是纠结的上下文,我正在尝试解决- 如果您想控制创建的 EM,您可以使用 createEntityManager - 例如如果您需要在事务中涉及的多个 bean 之间移动创建的 EntityManager - 容器不会为您执行此操作,并且每次调用 createEntityManager() 时,您都会创建一个连接到新 PersistenceContext 的 EntityManager。您可以将 CDI 用于 EntityManager 的共享。 请继续关注 Entity Transaction - JPA 和 Resource-local,将发布关于它的详细讨论。 希望它对上下文有一个简要的了解。并随时发布查询。

    here阅读第二部分

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-12
      • 1970-01-01
      • 1970-01-01
      • 2018-12-19
      • 1970-01-01
      • 1970-01-01
      • 2014-11-13
      • 1970-01-01
      相关资源
      最近更新 更多