实体管理器的类型:应用程序管理的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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/369291.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

的内怎么放_汽车后备箱的“四不放”原则,你知道吗?网友:怎么不早说

汽车已经开始存在在越来越多的家庭当中了&#xff0c;也正是因为这样&#xff0c;很多人会把汽车当做一个自己的家庭成员&#xff01;而在汽车的使用过程当中&#xff0c;汽车的后备箱往往是放的特别满的&#xff0c;以为这样可以备不时之需&#xff0c;但是老司机也告知大家&a…

as3 访问远程计算机,本地swf不能访问网络的解决办法

本地swf不能访问网络的解决办法作者&#xff1a;小龙博客 2011年03月21日  4条评论 分类&#xff1a;AS3 学习 flash 软件本地swf不能访问网络的解决办法&#xff1a;学习过http://www.lxlong.com/blog“)这样的代码&#xff0c;在测试影片时可以通过navigateToURL方法打开…

Compatibility Telemetry(CompatTelRunner.exe) 占用硬盘100%困扰

Compatibility Telemetry(CompatTelRunner.exe) 占用硬盘100%困扰&#xff0c;Compatibility Telemetry翻译过来就是“微软兼容性检测”的意思&#xff0c;找了半天终于找到了干掉这个兼容性检测的办法。 禁用服务 控制面板–管理工具 — 服务 — 手动&#xff08;或者禁止&…

Java基础知识学习04-自定义类、ArrayList集合

类与对象 类是一个模子&#xff0c;确定对象将会拥有的特征&#xff08;属性&#xff09;和行为&#xff08;方法&#xff09;。 类的特征&#xff1a;类是对象的类型 具有相同属性和方法的一组对象的集合 类的组成&#xff1a;属性和方法 定义一个类&#xff1a;public class …

监视和管理GlassFish 3的多种方法

GlassFish 3支持多种监视和管理方法。 在本文中&#xff0c;我将简要介绍GlassFish提供的管理&#xff0c;监视和管理方法。 GlassFish管理控制台 GlassFish基于Web的管理控制台GUI可能是GlassFish管理最著名的界面。 默认情况下&#xff0c;运行GlassFish后&#xff0c;可通过…

幸运抽奖

var oPointerdocument.getElementsByTagName("img")[0];var oTurnabledocument.getElementsByTagName("img")[1];var cat15;//每个区域15度&#xff0c;一共24个区域var num0;var offOntrue;//是否正在抽奖//指针点击事件&#xff0c;开始抽奖oPointer.onc…

linux usleep 线程控制权_linux多线程同步—信号量

linux多线程编程-信号量信号量机制锁机制使用是有限制的&#xff0c;锁只有两种状态&#xff0c;即加锁和解锁&#xff0c;对于互斥的访问一个全局变量&#xff0c;这样的方式还可以对付&#xff0c;但是要是对于其他的临界资源&#xff0c;比如说多台打印机等&#xff0c;这种…

标题 计算机构自由度时主要步骤有哪些,2010年1月全国自考混凝土结构设计试题和答案...

全国2010年1月自学考试商品混凝土结构设计试题课程代码&#xff1a;02440一、单项选择题(本大题共20小题&#xff0c;每小题2分&#xff0c;共40分)在每小题列出的四个备选项中只有一个是符合题目要求的&#xff0c;请将其代码填写在题后的括号内。错选、多选或未选均无分。1.一…

Django字段类型介绍

一&#xff0c;通过makemigrations&#xff0c;migrate来修改数据&#xff0c; 1.Django的ORM支持修改表结构&#xff0c;修改完以后&#xff0c;执行 python manage.py makemigrations python manage.py migrate 这两句&#xff0c;就会看到更新了。超过长度的数据就会丢了。…

input输入框的input事件和change事件

input输入框的onchange事件&#xff0c;要在 input 失去焦点的时候才会触发&#xff1b; 在输入框内容变化的时候不会触发change&#xff0c;当鼠标在其他地方点一下才会触发&#xff1b; onchange 事件也可用于单选框与复选框改变后触发的事件。 demo如下&#xff1a; <sc…

单例设计模式–内省和最佳实践

定义&#xff1a; Singleton是“ 四人帮”设计模式的一部分&#xff0c;它属于创新设计模式。 在本文中&#xff0c;我们将更深入地研究Singleton模式的用法。 就建模而言&#xff0c;它是最简单的设计模式之一&#xff0c;但另一方面&#xff0c;就使用的复杂性而言&#xff0…

修改用户名_Word办公技巧:如何更改文档修订者的用户名?

在一份文档需要多人参与修订的时候,每个审阅者将用户名改为自己的名字就可以方便地看出具体哪个参与者做了哪些改动。下面我们来学习一下更改修订者用户名的办法。 应用场景 下图文档中默认修订者用户名为"AutoBVT",接下来我们想将其改为"李小白"。 操作…

响应式布局 max-device-width 与 max-width 的区别

闲来没事&#xff0c;研究了一下多屏适配和响应式布局的 CSS。 第一种写法 1 media screen and (max-device-width: 320px) {2 3 }4 5 media screen and (min-device-width: 321px) and (max-device-width: 640px) {6 7 }8 9 media screen and (min-device-width: 641px) and…

springboot,修改配置文件不起作用

今天碰到一个奇怪的问题&#xff0c;明明配置了端口&#xff0c;但是每次启动还是用的8080端口&#xff0c;查了下估计是配置文件没生效&#xff0c;然后就去路径配置中把资源文件先移除&#xff0c;再添加&#xff0c;就正常了。 回忆下自己干了啥&#xff0c;发现时在pom.xml…

Java伪随机数生成器(PRNG)中的弱点

这将是Kai Michaelis&#xff0c;JrgSchwenk和我撰写的论文的总结&#xff0c;该论文在RSA Conference 2013的密码学家会议上发表 。 你可以得到我的演讲的幻灯片在这里和我们的全文在这里 。 我们对PRNG&#xff08;主要是SecureRandom&#xff09;附带的常见Java库生成的随机…

asp服务器组件安装包,ASP服务器组件

《ASP服务器组件》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《ASP服务器组件(20页珍藏版)》请在人人文库网上搜索。1、7/10/2020,1,网络开发技术,第二部分 ASP开发技术,7/10/2020,2,第四章 ASP服务器组件,4.1 ASP 服务器组件 ASP服务器组件 ASP服务器组件(ActiveX…

On Comparing Side-Channel Preprocessing Techniques for Attacking RFID Devices

对HF和UHF RFID标签进行DEMA和DFA攻击&#xff0c;并将DFA和应用不同预处理技术的DEMA效果进行比较。 实验中&#xff0c;进行两种隐藏进行攻击&#xff1a; 1、幅域&#xff08;读写器的场干扰&#xff09;隐藏 &#xff08;1&#xff09;DEMA攻击时&#xff0c;轨迹预处理&am…

python超市售货统计程序_用Python实现简易超市售货系统

今天来实现一个简单的超市售货系统数据存储形式为json的数据首先是读取数据&#xff0c;这里用到的Python的json库&#xff0c;用于处理json类型的数据pythondef load(): # 数据读取j open(goods.txt, r, encodingutf-8)# 逐行读取文件中的数据readers j.readlines()# 将数据…

vue安装概要以及vue测试工具

一、概述 1、安装node&#xff0c;去node官网 2、新建一个项目&#xff0c;通过npm init命令初始化&#xff0c;即创建一个package.json文件 3、用命令 npm install vue -g 全局安装vue&#xff08;网上已经有详细的资料&#xff0c;在此就不复述了&#xff09; 二、vue测试…

linux安装与远程连接

1、在VMware上创建新的虚拟机&#xff0c;保证有linux版本的iso镜像文件 具体参考http://jingyan.baidu.com/article/eae0782787b4c01fec548535.html 2、进行切换用户 进行root用户的切换&#xff1a;   #su password: 进行普通用户的切换&#xff1a; #su username 3、编辑…