带有PersistenceUnit的JTA

时间:2013-01-20 22:36:16

标签: java hibernate jpa

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

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

  

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

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

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

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

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

2 个答案:

答案 0 :(得分:0)

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

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

所以简单的答案是否定的,如果你依赖容器管理的实体经理。

例如,请参阅http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html

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

答案 1 :(得分:0)

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

enter image description here

实体管理器已在实体管理器工厂的帮助下实例化。与数据库的连接由实体管理器管理,即它提供用于对数据库执行操作的功能。因此,我们可以说一个应用程序是否需要多个数据库连接,将为特定数据库构建一个EntityManagerFactory,它提供了一种构建多个EntityManager实例的有效方法(如果需要,甚至单个实体管理器实例也可以根据您的要求进行工作)为每个HTTP请求所需的数据库选择多个实例。我们将借助一个例子来理解这一点。假设我们有一个 数据库:A,有关系表B和C. 因此,对于A,将实例化实体管理器工厂的实例。现在我们想要对表B&amp;表示任何更新。假设表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);

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

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)扩展与交易 - Scoped: 默认情况下,使用事务持久性上下文,这意味着在当前事务提交时刷新所有更改并且所有管理实体都将被删除。 扩展范围仅适用于有状态EJB和扩展。它甚至是完美的意义,因为有状态的豆可以拯救国家因此可以说结束 一种商业方法并不意味着交易的结束。 对于无状态bean,它有不同的方面 - 我们有业务方法,必须在业务方法完成时结束。   ===&GT;一种方法=一次交易; 对于无状态Bean,只允许使用Transactional-Scoped实体管理器 您可以在EntityManager注入期间控制EntityManager是扩展的还是事务性的: -

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

默认情况下,它是javax.persistence.PersistenceContextType.TRANSACTION 仅在容器管理的EntityManagers的情况下,才允许扩展和事务范围的PersistenceContext。 是时候加强了:容器管理与应用程序管理 2)容器管理与应用程序管理:

@PersistenceContext
EntityManager emng;

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

@PersistenceUnit
EntityManagerFactory emf;

现在要获取EntityManager,你需要调用

emf.createEntityManager();

这就是 - 您正在使用应用程序管理的持久性上下文。现在,您负责创建和删除EntityManagers。 在你阅读下一篇文章之前要集中精力,因为这是纠结的背景,我试图解决 - 如果要控制创建的EM,可以使用createEntityManager - 例如如果您需要将创建的EntityManager移动到trasaction中涉及的多个bean中 - 容器不会为您执行此操作,并且每次调用createEntityManager()时,您都要创建一个连接到new的EntityManager PersistenceContext。您可以使用CDI进行EntityManager的共享。 请继续关注实体交易 - JPA和Resource-local,将对其进行详细讨论。 希望它能简要介绍一下背景。 &安培;随意发布查询。

阅读here

中的第二部分