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

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

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

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

相关文章

linux安装无法添加挂载,linux-无法在已挂载/ etc / passwd和/ etc / shadow的docker容器中添加新用户...

问题示例&#xff1a;docker run -ti -v my_passwd:/etc/passwd -v my_shadow:/etc/shadow --rm centos[root681a5489f3b0 /]# useradd test # does not work !?useradd: failure while writing changes to /etc/passwd[root681a5489f3b0 /]# ll /etc/passwd /etc/shadow # pe…

CDI中的事务异常处理

在Java EE中&#xff0c;在执行事务性业务方法期间引发的异常导致事务回滚。 但是&#xff0c;只有系统异常&#xff08;即运行时异常&#xff09;才是这种情况&#xff0c;该方法异常未在方法签名中声明。 对于应用程序异常&#xff08;即检查的异常&#xff09;或任何带Appl…

openoffice+linux+jodconverter+乱码,OpenOffice安装和转换乱码解决方案

前言&#xff1a;OpenOffice项目中用途&#xff1a;word转换pdfWindows安装、转换&#xff1a;安装包下载后一路OK就可以正常安装&#xff0c;转换没有问题Linux安装、转换&#xff1a;安装有分DEB包和RPM包&#xff0c;下面会说明各自安装方法在en_US.UTF-8 系统环境下会出现乱…

linux常用操作符,Shell常用操作符总结

一、算术操作 - * / %二、关系操作> < ! && ||三、测试操作测试命令 : test [ ] [[ ]] (( ))1、测试文件状态-d 目录-b 块设备-s 文件长度 > 0、非空-f 正规文件-w 可写-L 符号连接-u 文件有 suid 位设置-r 可读…

junit 参数化测试用例_JUnit:在参数化测试中命名单个测试用例

junit 参数化测试用例几年前&#xff0c;我写了有关JUnit参数化测试的文章 。 我不喜欢它们的一件事是JUnit使用数字命名了单个测试用例&#xff0c;因此&#xff0c;如果它们失败&#xff0c;您将不知道是哪个测试参数导致了失败。 以下Eclipse屏幕快照将向您展示我的意思&…

华硕台式机安装linux进不去系统,[已解决]求助,无法进入系统

之前一直用arch系统盘&#xff0c;Windows系统盘是在另一台电脑上的&#xff0c;我另外一台电脑昨天摔了&#xff0c;我还以为是硬盘坏了&#xff0c;把这块windows硬盘换到这台华硕主板的电脑&#xff0c;发现硬盘没坏。我于是把windows硬盘从机箱拿出来&#xff0c;现在碰到了…

处理JAX-RS中的自定义异常类型

JAX-RS支持处理自定义异常&#xff08;以EJB或CID Bean形式抛出&#xff09;以处理自定义HTTP响应。 假设我们有一个“异常” EJB&#xff1a; Stateless public class Hello {public String greeting() {if (new Random().nextBoolean())throw new GreetingException("…

MX250和第三方Linux版区别,MX250和MX350哪个好一点,区别和差距在哪里?求推荐?_科技数码通...

MX350系列显卡使笔记本颜值变得更高&#xff0c;性能更强&#xff0c;更轻便&#xff0c;在轻便笔记本需求变得越来越大&#xff0c;但性能也要求越来越高&#xff0c;特别是在图像处理方面&#xff0c;这个时候MX系列的显卡便应运而生&#xff0c;其拥有者超低的功耗&#xff…

linux r包默认安装位置,R-Language(R语言或称r-project)的安装

1、R语言的简介R语言(r-project)是主要用于统计分析、绘图的语言和操作环境。2、配置yum源2.1、安装说明由于编译安装相对繁琐&#xff0c;故而安装使用repoforge的源解决&#xff0c;免去编译的麻烦。注意&#xff1a;请根据实际的系统OS版本选取合适的YUM源。2.3、rpmforge源…

aws s3 命令行_通过命令行界面使用AWS ElasticMapReduce

aws s3 命令行在本文中&#xff0c;我将通过使用EMR的CLI使用AWS MapReduce服务&#xff08;称为ElasticMapReduce &#xff09;。 使用EMR的过程可以大致分为三个步骤&#xff1a; 设置并填充S3存储桶 创建并运行EMR作业 从S3存储桶中获取结果 在开始这三个高级步骤之前&…

在5分钟内将Spring Boot作为Windows服务启动

最近&#xff0c;我不得不将Spring Boot应用程序部署为Windows服务&#xff0c;并且对使用winsw如此容易感到惊讶。 我之前曾写过关于使用procrun – Java程序作为Windows服务的文章 &#xff0c;但是winsw更加容易 入门 Spring Boot文档的第59节是有关安装Spring Boot应用程序…

linux下用c语言打印hellword,用C语言写一个Helloworld_实现第一步编译运行

asp&period;net在线预览txt文件&lpar;简单实现&rpar;最近在做文件的在线预览,发现txt文件没有一个较好的方法去实现,想了想可能是比较简单就直接在后台输出了 txt文件Windows 环境下基于 Redis 的 Celery 任务调度模块的实现搭建环境: Windows-x64 10 Celery 3.1.2…

c语言自动计算时间,C语言 · 计算时间

【工业串口和网络软件通讯平台&lpar;SuperIO&rpar;教程】四&period;开发设备驱动SuperIO相关资料下载:http://pan.baidu.com/s/1pJ7lZWf 1.1 开发准备 把“开发包”内的所有文件复制到项目的“bin”目录下,或项目下的专用生成目录.开发包 ...java compiler leve…

matchers依赖_Hamcrest Matchers,Guava谓词和Builder设计模式

matchers依赖通常&#xff0c;在编码时&#xff0c;我们必须处理其中包含数十个字段的一些POJO对象。 很多时候&#xff0c;我们通过一个带有数十个参数的构造函数来初始化这些类&#xff0c;这以任何可能的想象的方式都是可怕的。 除此之外&#xff0c;使用这些构造函数的函数…

8255编程c语言程序,51单片机8255驱动C程序

/*----------------------------------------------------------------------------------------------------------------库文件名称&#xff1a;driver8155.h功能描述&#xff1a;驱动8155&#xff0c;不需要了解8255的工作原理&#xff0c;透明操作8255的三个输入输出口PA、…

如何编写更少,更好的代码,或Project Lombok

我长期以来一直打算撰写有关Lombok项目的文章 &#xff0c;以至于每当一个自重的Java开发人员都已经听说过它时&#xff0c;我可能会写它。 尽管如此&#xff0c;值得一提的是&#xff0c;如果只是提醒自己&#xff0c;不要犹豫&#xff0c;尝试性能增强工具并查看它们是否合适…

c语言ue,小话C语言中的cotinue和break

#includeint fun(){ printf("fun\n");return 1;}int main(int argc,char *argv[]){int c0;printf("please input your num ,case 3 to break\n");do{scanf("%d",&c);switch(c){case 0:break; /*这里的break只会跳出swtich*/case 1:continue;…

c语言 at指令,学渣求指教,如何识别字符串中的AT命令并逐个输出,求程序!!!...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼Topic – to implement a parser to retrieve AT command line and print out (1) the tokensone by one and (2) the elapse time of each command line (processing).Please submit the solution in 48 hours.- The solution cou…

defender 删除_Java 8中的默认方法(Defender方法)简介

defender 删除我们都知道Java中的接口仅包含方法声明&#xff0c;而没有实现&#xff0c;并且任何实现该接口的非抽象类都必须提供实现。 让我们看一个例子&#xff1a; public interface SimpleInterface {public void doSomeWork(); }class SimpleInterfaceImpl implements …

江西财经研究生834c语言试卷,江西财经大学2006年考研C语言程序设计试题(B卷)

1、给定一个数X&#xff0c;判断它至少能被3&#xff0c;5&#xff0c;7中的两个数整除的表达式。(5分)某学生今年学习5门课程&#xff0c;其考试成绩为&#xff1a;X1、X2、X3、X4、X5.请写出该同学符合三好学生学习成绩的表达式。(5分)3、a&#xff0c;b&#xff0c;c为三条边…