JPA和CMT –为什么捕获持久性异常不够?

使用CMT( 容器管理的事务 )进入EJB和JPA的世界非常舒适。 只需定义一些注释来划分事务边界即可(或使用默认值),仅此而已–无需摆弄手动开始,提交或回滚操作。 回滚事务的一种方法是从EJB的业务方法中引发非应用程序异常(或具有rollback = true的应用程序异常)。 看起来很简单:如果在某些操作过程中可能会引发异常,并且您不想回滚tx,那么您应该捕获该异常就可以了。 现在,您可以在同一仍处于活动状态的事务中再次重试该易失性操作。

现在,对于从用户组件抛出的应用程序异常,这一切都是正确 。 问题是– 除了其他组件引发的异常之外,还有什么? 就像JPA的EntityManager抛出PersistenceException ? 这就是故事的开始。

我们想要实现的目标

设想以下情形:您有一个名为E的实体。它包含:

  • id –这是主键,
  • 名称 -这是一些易于理解的实体名称,
  • 内容 -包含字符串的任意字段-它模拟“高级属性”,例如,在持久性/合并期间进行计算会导致错误。
  • 代码 –包含OK或ERROR字符串–定义高级属性是否成功持久保存,

您要持久化E。您假定E的基本属性将始终被成功持久化。 但是,高级属性需要一些额外的计算或操作,这可能会导致例如从数据库引发约束冲突。 如果发生这种情况,您仍然希望E保留在数据库中(但仅填充基本属性,并且将代码属性设置为“ ERROR”)。

换句话说,这就是您可能想到的:

  1. 坚持E的基本属性,
  2. 尝试使用脆弱的高级属性进行更新,
  3. 如果从步骤2抛出了PersistenceException捕获它,将'code'属性设置为“ ERROR”并清除所有高级属性(它们导致异常),
  4. 更新E。

天真的解决方案

转到EJB的代码,这就是您可以尝试执行的方式(假设使用默认的TransactionAttributes):

public void mergeEntity() {MyEntity entity = new MyEntity('entityName', 'OK', 'DEFAULT');em.persist(entity);// This will raise DB constraint violationentity.setContent('tooLongContentValue');// We don't need em.merge(entity) - our entity is in managed mode.try {em.flush();  // Force the flushing to occur now, not during method commit.} catch (PersistenceException e) {  // Clear the properties to be able to persist the entity.entity.setContent('');entity.setCode('ERROR');// We don't need em.merge(entity) - our entity is in managed mode.}
}

这个例子有什么问题?

捕获由EntityManager抛出的PersistenceException 不会阻止事务回滚 。 并不是在EJB中不缓存异常会使tx标记为回滚。 这是EntityManager 抛出的非应用程序异常 ,将tx标记为回滚。 更不用说资源可能会在其内部将tx标记为回滚。 这实际上意味着您的应用程序实际上无法控制此类tx行为。 此外,由于事务回滚,我们的实体已移至分离状态。 因此,此方法末尾需要一些em.merge(entity)

工作方案

那么如何处理这种自动事务回滚? 因为我们使用的是CMT,所以唯一的方法是定义另一种业务方法,该方法将启动新的事务并在那里执行所有易碎的操作 。 这样,即使将抛出(并捕获) PersistenceException ,它也将仅标记要回滚的新事务。 我们的主要TX将保持不变。 在下面,您可以从此处看到一些代码示例(为简洁起见,删除了日志记录语句):

public void mergeEntity() {MyEntity entity = new MyEntity('entityName', 'OK', 'DEFAULT');em.persist(entity);try {self.tryMergingEntity(entity);} catch (UpdateException ex) {entity.setContent('');entity.setCode('ERROR');}
}@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void tryMergingEntity(final MyEntity entity) throws UpdateException {entity.setContent('tooLongContentValue');em.merge(entity);try {em.flush();} catch (PersistenceException e) {throw new UpdateException();}
}

注意:

  • UpdateException@ApplicationException ,它扩展了Exception(因此默认情况下为rollback=false )。 用于通知更新操作失败。 或者,您可以更改tryMergingEntity(-)方法签名以返回布尔值而不是void。 该布尔值可以描述更新是否成功。
  • self是对我们自己的EJB的自我引用。 这是使用EJB容器代理的必需步骤,该代理使被调用方法的@TransactionAttribute起作用。 或者,您可以使用SessionContext#getBusinessObject(clazz).tryMergingEntity(entity)
  • em.merge(entity)是至关重要的。 我们正在tryMergingEntity(-)中开始新事务,因此该实体不在持久性上下文中。
  • 此方法不需要任何其他合并或刷新。 tx尚未回滚,因此批准了CMT的常规功能,这意味着在tx提交期间将自动刷新对实体的所有更改。

让我们再次强调最重要的一点: 如果您捕获到异常,这并不意味着您的当前事务没有被标记为回滚。 PersistenceException不是ApplicationException,即使您是否捕获它,也将使您的tx回滚。

JTA BMT解决方案

我们一直在谈论CMT。 JTA BMT呢? 好吧,作为奖励,请找到以下代码,该代码显示了如何使用BMT处理此问题(也可在此处访问):

public void mergeEntity() throws Exception {utx.begin();MyEntity entity = new MyEntity('entityName', 'OK', 'DEFAULT');em.persist(entity);utx.commit();utx.begin();entity.setContent('tooLongContentValue');em.merge(entity);try {em.flush();} catch (PersistenceException e) {utx.rollback();utx.begin();entity.setContent('');entity.setCode('ERROR');em.merge(entity);utx.commit();}
}

使用JTA BMT,我们可以用一种方法完成所有这一切。 这是因为我们控制着tx何时开始以及提交/回滚 (看看那些utx.begin()/ commit()/ rollback()。尽管如此,结果还是一样的–抛出PersistenceException我们的tx被标记为回滚然后可以使用UserTransaction#getStatus()进行检查,并将其与诸如Status.STATUS_MARKED_ROLLBACK之类的常量进行比较,并可以在我的GitHub帐户上检查整个代码。

参考: JPA和CMT –为什么捕获持久性异常不足? 从我们的JCG合作伙伴 Piotr Nowicki在Piotr Nowicki的首页博客中获得。

翻译自: https://www.javacodegeeks.com/2013/03/jpa-and-cmt-why-catching-persistence-exception-is-not-enough.html

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

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

相关文章

2016 linux发行版排行_选择困难症必看!云服务器如何选择操作系统,Windows和Linux哪个更好?...

在购买云服务器时,会有一个必选的配置,就是操作系统的选择,如何选择操作系统?操作系统选择错了怎么办?这是不少用户会遇到的问题,今天我们就来教大家如何选择操作系统,以及操作系统选择错了&…

spring取得通过配置文件和注解注入的bean、取得当前数据库连接、取得ApplicationContext的方法...

spring取得通过配置文件和注解注入的bean、取得当前数据库连接、取得ApplicationContext的方法 1、思路: 应用程序启动时使用ApplicationContextAware让Spring容器传递自己生成的ApplicationContext给我们, 然后我们把这个ApplicationContext设置成一个类…

怎样不通过高考进入清华计算机系,山东高考状元孟令昊澄清,没有参加政审,已经填报清华计算机系!...

原标题:山东高考状元孟令昊澄清,没有参加政审,已经填报清华计算机系!说到高考状元,其实每年在高考分数公布以后和志愿填报的时候,他们都是大家最为关注的群体,特别是对于这些状元的去向成为了很…

DOM BOM document window 区别

DOM 是为了操作文档出现的 API,document 是其的一个对象; BOM 是为了操作浏览器出现的 API,window 是其的一个对象。 使用下图讲解: 归DOM管的: E区:即document 归BOM管的: A区:浏览…

提取Java集合的元素-Java 8方法

我们所有人都广泛使用了Collection类&#xff0c;例如List&#xff0c;Map及其派生版本。 每次使用它们时&#xff0c;我们都必须遍历它们以找到某个元素或更新这些元素&#xff0c;或者找到匹配某个条件的不同元素。 考虑如下所示的人员列表&#xff1a; List<Person> …

D2

依托 Weex 的能力&#xff0c;轻舟平台使得前端开发人员可以基于 Vue 或者 Rax&#xff08;类 React&#xff09;开发媲美原生的 App。 不需要学习各类 Native 开发语言&#xff1b;不需要搭建复杂的编译打包环境&#xff0c;轻舟提供的一站式集成开发解决方案全部帮你搞定。吴…

hibernate5--主键生成策略

1、hibernate自己维护主键的值。首先获取该表中最大主键值&#xff0c;然后加一插入。主键字段对应的属性类型可以是int、short、long以及其封装类型。在高并发或者集群的情况下不能使用。 2、identity&#xff1a;使用数据库自身自增长来维护。 <id name"id" col…

vue watch 第一次不执行_Vue 实现前进刷新,后退不刷新的效果

https://github.com/woai3c/Front-end-articles​github.com需求一&#xff1a;在一个列表页中&#xff0c;第一次进入的时候&#xff0c;请求获取数据。点击某个列表项&#xff0c;跳到详情页&#xff0c;再从详情页后退回到列表页时&#xff0c;不刷新。也就是说从其他页面进…

win8计算机安全模式,安全模式,详细教您Win8怎么进入安全模式

电脑的用途在我们的日常生活之中体现的是最为突出了&#xff0c;比方说网上购物、看电视、玩游戏、做文件什么的都用得着电脑。但是有用户遇到了Win8系统按F8无法进入安全模式怎么办&#xff1f;非也&#xff0c;非也&#xff0c;下面&#xff0c;小编给大家带来了Win8进入安全…

元素加了position:absolute则该元素的text-align:center居中失效的解决办法

position:absolute;top:50%;left:50%;-webkit-transform: translate(-50%,-50%);-moz-transform: translate(-50%,-50%);transform:translate(-50%,-50%); 当元素变为position:absolute时&#xff0c;该元素不占据文档流&#xff0c;text-align&#xff1a;center失效&#xff…

elasticsearch-6.0.1安装

elasticsearch-6.0.1安装 0. 介绍&#xff1a;ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎&#xff1b;是目前全文搜索引擎的首选。Elastic 的底层是开源库 Lucene。但是&#xff0c;没法直接用 Lucene&#xff0c;必须自己写代码…

使用GlassFish 4.0测试驱动Java API以处理JSON

编写规范并为其做出贡献是一回事。 如果您想提供宝贵的反馈意见&#xff0c;请使用它并研究真实的示例。 最新推广的GlassFish构建包含重命名为4.0&#xff0c;我认为现在是对Java处理JSON&#xff08;JSON-P&#xff09;API进行测试的好时机。 获取启用了Java EE 7的GlassFis…

查询已有链表的hashmap_原创 | 面试不再慌,看完这篇保证让你写HashMap跟玩一样...

点击上方蓝色小字&#xff0c;关注“码农小黑屋”重磅干货&#xff0c;第一时间送达今天这篇文章给大家讲讲hashmap&#xff0c;这个号称是所有Java工程师都会的数据结构。为什么说是所有Java工程师都会呢&#xff0c;因为很简单&#xff0c;他们不会这个找不到工作。几乎所有面…

华为p40手机自带计算机,华为p40pro支持PC模式吗_华为p40pro能连接至电脑模式吗

华为p40pro支持PC模式吗&#xff1f;华为p40pro能连接至电脑模式吗&#xff1f;从前几年开始&#xff0c;就有部分华为手机可以支持PC模式了。这个模式在出差的时候还是很实用的&#xff0c;可以直接将手机上的内容投屏到投影仪等大屏设备上&#xff0c;不需要带笔记本电脑&…

工欲善其事

持续补充更新中....... 工具箱汇总 娄老师的超强百宝箱 &#xff08;必看&#xff01;&#xff01;&#xff09;张老师 的总结 在博客中插入代码作业高分博客指南冲刺博客指南环境搭建 Git和Github教程Git简明指南猴子都能懂的GIT入门Coding使用方法如何使用Git和码云转载于:ht…

在Bootstrap框架中,form-control的效果

在Bootstrap框架中&#xff0c;通过定制了一个类名form-control&#xff0c;也就是说&#xff0c;如果这几个元素使用了类名“form-control”&#xff0c;将会实现一些设计上的定制效果。 1、宽度变成了100% 2、设置了一个浅灰色&#xff08;#ccc&#xff09;的边框 3、具有…

ubuntu 使用apt-get install 安装php5.6--php7

使用ppa增加源:$ sudo apt-get install python-software-properties $ sudo add-apt-repository ppa:ondrej/php $ sudo apt-get update $ sudo apt-get install -y php7.0 php7.0-mysql php7.0-curl php7.0-json php7.0-cgi然后可以查看php版本:php -v关于php5.4--php5.6版本 …

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

JPA规范定义了几种类型的EntityManagers / Persistence Context。 我们可以有&#xff1a; 扩展的和事务范围的EntityManager&#xff0c; 容器管理或应用程序管理的EntityManager。 JTA或本地资源EntityManager&#xff0c; 除了上述区别外&#xff0c;我们还可以在其中存…

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

汽车已经开始存在在越来越多的家庭当中了&#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方法打开…