entitymanager

JPA规范定义了几种类型的EntityManagers / Persistence Context。 我们可以有:

  • 扩展和事务范围的EntityManager,
  • 容器管理或应用程序管理的EntityManager。
  • JTA或本地资源EntityManager,

除了上述区别之外,我们还可以在其中存在EntityManager / Persistence Context的两个主要上下文– Java EEJava SE 。 并非每个选项都适用于Java EE,并且并非每个选项都适用于Java SE。 在本文的其余部分中, 我将介绍Java EE环境

好的,因此在继续本文之前的主题之前(这是使用EntityManagerFactory手动创建的Java EE中EntityManager的行为),我们仅简要介绍一下上述EM类型。

扩展与事务范围

此功能告诉我们EntityManager的操作是否可能跨越多个事务。 默认情况下,使用事务性持久性上下文,这意味着当提交当前事务时,将清除所有更改,并分离所有受管实体。 扩展范围仅适用于有状态EJB。 这非常有意义,因为SFSB可以保存状态,因此不必终止一种业务方法就意味着结束事务。 使用SLSB的情况就不同了–我们有业务方法必须在业务方法完成时结束,因为在下一次调用中,我们不知道我们将以哪个EJB实例结束。 SLSB仅允许使用事务范围的EntityManager。 您可以控制在EntityManager注入期间EntityManager是扩展的还是事务的:

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

默认情况下为javax.persistence.PersistenceContextType.TRANSACTION 。 附带说明–使用扩展的EntityManager可能使您可以创建一些有趣的解决方案; 看看具有事务性保存方法技巧的 Adam Bien的无事务bean 。 他使用这种方法使事务开始和结束时自动清除所有更改(并且他实际上通过调用特殊的人工方法来做到这一点。)仅在容器管理的EntityManagers的情况下才允许扩展和事务范围的PersistenceContext。

容器管理与应用程序管理

在大多数Java EE应用程序中,您只是使用@PersistenceContext注入EntityManager,如下所示:

@PersistenceContext
EntityManager em;

实际上,这意味着您要让容器为您的EntityManager注入 (容器是在后台从EntityManagerFactory创建的。)这意味着EntityManager是由容器管理的。 另外,您可以从EntityManagerFactory自己创建EntityManager。 您可以通过注入获得它:

@PersistenceUnit
EntityManagerFactory emf;

然后,要获取EntityManager,您需要调用emf.createEntityManager() 。 这就是–您现在正在使用应用程序管理的EntityManager应用程序(您)负责创建和删除EntityManager。 每个应用程序管理的持久性上下文都有扩展的范围。

如果要控制已创建的EM,则可以使用-例如,如果要为基础JPA实现程序设置一些属性,或者只是在业务方法将其投入使用之前插入自己。 但是,您将需要跨事务涉及的多个bean移动创建的EntityManager –容器不会为您这样做,并且每次调用emf.createEntityManager()您都在创建一个与新PersistenceContext连接的EntityManager。 。 您可以使用CDI进行EntityManager的共享,但这是最后一节之一的主题。

JTA与本地资源

此属性定义您是要JTA管理EntityManager的事务,还是要使用其直接API开始和提交。 如果您使用的是容器管理的EntityManager,则自动意味着您必须使用JTA EntityManager 。 如果您使用的是应用程序管理的EntityManager,则可以使用JTA或本地资源。 在现实生活中,这意味着,如果您使用的是JTA EntityManager,则您只需照顾更高级别的事务管理:

  • 声明性地 使用注释或XML JTA交易属性,或
  • 以编程方式 使用javax.transaction.UserTransaction

如果您使用的是本地资源EntityManager,则需要更深入一点,并使用EntityManager.getTransaction()返回javax.persistence.EntityTransaction并调用commit(-)begin(-)rollback()等。使用transaction-type属性在persistence.xml定义此功能:

<?xml version='1.0' encoding='UTF-8'?>
<persistence ...><persistence-unit transaction-type='RESOURCE_LOCAL' ... >
</persistence>

另一个可能的值(当未定义transaction-type时为默认值)是JTA

Java EE中由应用程序管理的JTA EntityManager

尽管此字幕听起来很复杂,但了解EntityManager和PersistenceContexts的所有先前类型后,您应该确切了解if指的是什么。

  • “应用程序托管”意味着我们将注入@PersistenceUnit EntityManagerFactory而不是EntityManager,
  • 之所以称为 “ Java EE”,是因为这些示例(在github上发布)仅在Java EE Application Server中使用
  • “ JTA”,因为我们将使用JTA事务级别,因此不会使用javax.persistence.EntityTransaction

现在,您需要了解的第一件事是如何使用JTA事务。 JTA事务管理有两种类型-容器(CMT)和Bean管理(BMT)。 容器管理的JTA事务CMT )意味着您使用javax.ejb.TransactionAttribute定义tx是否应处于活动状态以及事务边界在何处。 这是默认的JTA管理类型。 或者,您可以选择自己划定JTA事务的边界。 这称为Bean管理的JTA事务BMT )。应用程序(您)负责启动,回滚或提交事务。 您如何控制JTA交易? 您可以使用javax.transaction.UserTransaction做到这一点。

您如何获得一个? 好吧,至少有3种方法可以做到这一点:

  • 它绑定到组件私有名称空间( java:comp/UserTransaction )中的JNDI,因此您可以使用InitialContextSessionContext对其进行查找,
  • 您可以使用SessionContext进行访问– SessionContext#getUserTransaction()
  • 因为它绑定在众所周知的JNDI名称中,所以可以让容器使用以下方式注入它: @Resource UserTransaction utx;

如果您有UserTransaction ,则可以开始划分事务中要执行的内容。 请注意,您仍在控制JTA事务 –您甚至都没有接触EntityManager的资源本地事务。

EntityManager何时在JTA事务中?

如果没有前面的介绍,您可能会认为由应用程序管理的EntityManager意味着您将独自承担一切–创建,共享EntityManager,开始tx,提交,关闭。 但是,了解了以上所有差异后,您知道可以在应用程序管理的EntityManager中使用JTA事务 。 但是问题是–如何使它知道活动的JTA事务? 如果我们有一个容器管理的EntityManager,我们知道容器将全部管理它,但是如果我们是一个人,我们该怎么做? 实际上, 这取决于我们在哪里创建EntityManager 。 在下面找到一些示例(完整的代码可以在我的github帐户上找到:

情况1:我们在没有活动交易的情况下调用以下代码(因此,对于CMT,我们具有TransactionAttribute.NEVERTransactionAttribute.NOT_SUPPORTED ;对于BMT,我们不调用UserTransaction.begin()

EntityManager em = emf.createEntityManager();
em.persist(new Customer(firstName, lastName));

结果: EntityManager操作在持久化时不会引发任何异常,但是所有更改都不会提交 。 没有活动的事务,因此不会进行任何更改。

情况2:我们使用BMT调用以下代码:

utx.begin();EntityManager em = emf.createEntityManager();em.persist(new Customer(firstName, lastName));utx.commit();

结果:在JTA提交期间,新数据已正确保留(在最后一行。)

情况3:我们使用BMT调用以下代码:

EntityManager em = emf.createEntityManager();
utx.begin();em.persist(new Customer(firstName, lastName));utx.commit();

结果: EntityManager在事务之外,因为它是在启动JTA事务之前创建的。 尽管已提交JTA事务,但更改不会持久保存。 没有异常被抛出。

在第二个示例的情况下,您可能会问自己-是否可以首先创建EntityManager,然后开始事务,最后以某种方式使EntityManager知道周围的TX? 如果事实是这样,则可以执行此操作,而这正是EntityManager#joinTransaction()方法的用途。 以下两种情况将向您展示如何使用它:

情况4:我们使用BMT调用以下代码:

EntityManager em = emf.createEntityManager();
utx.begin();
em.joinTransaction();em.persist(new Customer(firstName, lastName));utx.commit();

结果:在这里,我们明确地告诉EntityManager加入活动的JTA事务。 结果, EntityManager将在JTA commit期间刷新其所有更改

情况5:我们使用BMT调用以下代码:

EntityManager em = emf.createEntityManager();
utx.begin();em.joinTransaction();em.persist(new Customer(firstName, lastName));utx.commit();utx.begin();em.joinTransaction();em.persist(new Customer(firstName, lastName));utx.commit();

结果: 两种EntityManager操作均正确存在。 在这里,我们证明了应用程序管理的持久性上下文可以跨越多个JTA事务 (请注意,我们没有创建另一个EntityManager,而只是重用了先前事务中使用的那个)。在这里,您可以看到JPA规范(JPA规范) 2.0最终版本)告诉您有关应用程序管理的持久性上下文的信息:

7.7应用程序管理的持久性上下文

使用JTA应用程序管理的实体管理器时,如果在当前JTA事务的范围之外创建实体管理器,则应用程序有责任通过调用EntityManager.joinTransaction将实体管理器与事务关联(如果需要)。 。 如果实体管理器是在JTA事务范围之外创建的,则除非调用EntityManager.joinTransaction,否则它不与事务关联。
使用CDI共享EntityManager

如前所述,如果要在组成一个事务的组件之间共享EntityManager,则应手动传递它(毕竟,它是“应用程序管理的”。)CDI可能是此处的解决方案。 您可以生成请求范围内的EntityManager并将其注入所需的任何组件中。 看起来可能像这样(在现实生活中,您还需要注意处理EM):

public class Resources {@PersistenceUnitEntityManagerFactory emf;@Produces @RequestScopedpublic EntityManager createEntityManager() {return emf.createEntityManager();}
}

现在,在每个bean中我们都可以拥有:

@Stateless
public class MyBean {@InjectEntityManager em;
}

在构成事务的不同组件之间共享应用程序管理的持久性上下文似乎是一种非常干净的方法。 但是,我担心的是:知道由应用程序管理的EntityManager事务性行为取决于创建它的位置 ,因此这种方法有时可能会给您带来讨厌的结果。 以下面的代码为例( 我的Github项目中也提供了该类,该类正是在这里 ):

@Stateless
@TransactionAttribute(TransactionAttributeType.NEVER)
public class BeanABoundary {@Injectprivate EntityManager em;@EJBBeanB beanB;public void invoke() {em.getProperties();beanB.invoke();
}

请注意,BeanA是非事务性资源。 还要注意,我们在EntityManager上注入并调用了一些操作 (这使得注入实际上得以执行。)现在,如果BeanB是事务性的,并且还注入并使用EntityManager –我们将以非事务性EntityManager结束,该操作不会抛出任何异常,并且不会将任何更改保存到数据库

在旧的@PersistenceContext的情况下,我们将处于事务中,因为EntityManager将由容器管理,并且容器将知道当前处于活动状态的事务。 容器负责在事务边界之间共享EntityManager。 在显示CDI生产者方法的情况下,CDI不知道运行事务,而只是共享EntityManager。

当然,可以使用CDI并创建一个@Produces @PersistenceContext EntityManager em ,然后使用@Inject EntityManager 。 这将与@PersistenceContext EntityManager完全一样,但是允许我们在产生EntityManager的单个位置定义(例如)持久性单元的名称。 但是,如果我们要拥有一个应用程序管理的EntityManager,则这不是一个选择。

参考: 实体管理器的类型:由我们的JCG合作伙伴 Piotr Nowicki在Piotr Nowicki主页博客上进行的应用程序管理的EntityManager 。

翻译自: https://www.javacodegeeks.com/2013/03/types-of-entity-managers-application-managed-entitymanager.html

entitymanager

entitymanager_实体管理器的类型:应用程序管理的EntityManager相关推荐

  1. 实体管理器的类型:应用程序管理的EntityManager

    JPA规范定义了几种类型的EntityManagers / Persistence Context. 我们可以有: 扩展的和事务范围的EntityManager, 容器管理或应用程序管理的Entity ...

  2. pyqt 控件焦点_PyQt5(2)——调整布局(布局管理器)第一个程序

    我们拖拽一个UI文件,转为PY文件后生成一个类Ui_MainWindow 此时,我们新建一个文件,用来控制业务逻辑(继承界面中的类),跟界面分开,这样我们就完成了界面和逻辑相分离(这段代码使用率基本1 ...

  3. Android布局管理器-使用TableLayout表格布局管理器实现简单的用户登录页面

    场景 Android布局管理器-使用FrameLayout帧布局管理器显示层叠的正方形以及前景照片: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article ...

  4. java中布局管理器flowlayout_JAVA基础:FlowLayout布局管理器

    在前面的例子中,使用到了FlowLayout布局管理器.FlowLayout型布局管理器对容器中组件进行布局的方式是将组件逐个地安放在容器中的一行上.一行放满后就另起一个新行. FlowLayout有 ...

  5. 引用管理器没有程序集_程序员必背英语单词不会,就别说你是程序员!

    Compile:编绎 Run:运行 Class:类 Object:对象 System:系统 out:输出 print:打印 line:行 variable:变量 type:类型 static:静态的 ...

  6. win10 系统下本地 IIS 管理器 MIME 类型添加

    问题: 我在本地建了一个本地的 web 服务器,如下图所示: 我在里面放了一些文件,点击其他文件都可以下载到本地,可是点击 *.xbin 类型的文件,就会出现如下提示: 原因: *.xbin 格式的文 ...

  7. Linux软件管理器(如何使用软件管理器来管理软件)

    我们的Linux系统大部分都是某个Linux厂商的系统,所以这些厂商可以编译好一些软件来提供用户下载,用户下载完了之后就可以直接安装,从而省去了编译源码及其过程中的各种问题.这时我们就可以使用相应的软 ...

  8. Android布局管理器-使用FrameLayout帧布局管理器显示层叠的正方形以及前景照片

    场景 Android布局管理器-使用LinearLayout实现简单的登录窗口布局: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details ...

  9. 黑莓桌面管理器4.2_虚拟桌面管理器行业现状调研分析及发展趋势预测报告(2020)...

    QYResearch预测:2020-2026全球与中国虚拟桌面管理器市场现状及未来发展趋势 [纸版价格]:RMB 18000 [电子版(PDF)价格]:RMB 18000 [报告篇幅]:101 [报告 ...

最新文章

  1. 专访施巍松:边缘计算早期提出者之一
  2. SAP Spartacus 里的三种table类型
  3. 《SAS编程与数据挖掘商业案例》学习笔记之十四
  4. 建立一颗二叉排序树,并删除该二叉排序树上的某个节点
  5. 【算法分析与设计】二分查找平均查找长度的求解
  6. dos盘启动计算机,最新万能 DOS 启动盘制作全攻略(软盘+光盘+U盘+硬盘+NTFS+应急实用工具)...
  7. tiny core linux ftp,tinycore 的基本搭建,开机时间只需要1-3秒
  8. [恢]hdu 1421
  9. mysql 日期循环_如何在mysql存储过程中循环日期时间
  10. (HDU)1061 --Rightmost Digit( 最右边的数字)
  11. Dapper.net 入门demo 轻量级ORM框架
  12. IntelliJ IDEA创建Java-Web项目
  13. 防热服的设计数学建模_数学建模之高温作业专用服装设计.pdf
  14. smartq ten3 android4,智器TEN3(T15)拆机
  15. 基于Python制作的一个打砖块小游戏
  16. 【Gem5】有关gem5模拟器的资料导航
  17. 第一个C编译器的诞生图
  18. 网络协议-DNS与Hosts
  19. [非线性控制理论]6_滑模控制 (sliding mode control)
  20. CP2K入门教程分享

热门文章

  1. Java中枚举的线程安全性及序列化问题
  2. c语言程序设计--图书管理系统
  3. 今天,我们就来抽个奖!
  4. 就业形势如此的严峻,你为何不努力?
  5. mysql中的isnull
  6. count does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manu
  7. 阿里云服务器 window server tomcat启动 并且关闭window防火墙 配置8080端口开放还是没用
  8. xrkmonitor监控mysql_xrkmonitor字符云监控系统
  9. 转- java单例模式几种实现方式
  10. jvm(8)-虚拟机字节码执行引擎