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

jpa 异常捕获

使用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

jpa 异常捕获

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

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

相关文章

linux 线程等待时间,线程超时等待方法 linux中select()函数使用

线程超时等待方法 linux中select()函数使用select系统调用时用来让我们的程序监视多个文件句柄的状态变化的。程序会停在select这里等待,直到被监视的文件句柄有一个或多个发生了状态改变。关于文件句柄,其实就是一个整数,通过socket函数的声…

使用Spring @Transactional进行数据源路由

卡尔帕帕(Carl Papa)在Spring框架中使用方面来确定要使用的DataSource (读写或只读)启发了我。 所以,我正在写这篇文章。 我必须承认,我对Spring的AbstractRoutingDataSource早已熟悉。 但是我不知道在哪里…

linux应用程序是什么,linux下c开发了一个应用程序,它的扩展名是什么?

这个貌2113似涉及到linux文件系统。linux文件系统与windows的不相同5261,windows系统应该是通4102过文件后缀来进行文件类型是别的,而1653linux虽然也会借鉴后缀信息,但好像不完全依赖于文件后缀。比如,在windows下,讲…

linux服务器带宽设置,linux 系统查看服务器带宽使用

使用linux服务器中,可能刚接触的同学不会查看系统的带宽使用,这里收集了一个脚本,可以实时显示服务器的带宽使用喔~vi cs.sh然后粘贴以下内容:#!/bin/bashif [ -z "$1" ]; thenechoecho usage: $0 network-interfaceech…

moxy json介绍_MOXy的对象图– XML和JSON的输入/输出局部模型

moxy json介绍假设您有一个要公开为RESTful服务的域模型。 问题是您只想输入/输出部分数据。 以前,您将创建一个代表子集的单独模型,然后使用代码在模型之间移动数据。 在EclipseLink 2.5.0中,我们有一个称为“对象图”的新功能,使…

linux设置新硬盘权限,Linux 下挂载新硬盘以及更改为普通权限

1、启动终端,以root用户登录2、查看硬盘信息:#fdisk -l3、进入磁盘,对磁盘进行分区:#fdisk /dev/sda(注意看你要挂载哪一个磁盘,我的是sda,有的是sdb)4、格式化分区:#mkfs.ext3 /dev/sda1 //注&…

使用Payara Micro的Easy Java EE Microservices

想知道如何开始使用Java EE Microservices? 使用Java EE API只需很少的步骤即可部署微服务。 许多人认为Java EE无法与微服务一起使用,但事实并非如此……特别是如果您仅使用服务所需的Java EE规范。 在这篇简短的文章中,我将演示如何使用Jav…

linux终端lex程序运行,lex的简单使用

Lex & Flex 简介Lex是lexical compiler的缩写,是Unix环境下非常著名的工具, Lex (最早是埃里克施密特和 Mike Lesk 制作)是许多 UNIX 系统的标准词法分析器(lexical analyzer)产生程式,而且这个工具所作的行为被详列为 POSIX 标准的一部分…

Linux内存page,Linux虚拟内存管理 - Page Table的作用

虚拟内存的作用:1.扩展实际有限的物理内存,当然这种扩展是虚拟的,比如物理内存512M,对于一个需要1G空间的进程来说,照样可以运行。这增加了操作系统是应用范围。2.使得进程中的数据空间增大,增大到多少与硬…

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

entitymanagerJPA规范定义了几种类型的EntityManagers / Persistence Context。 我们可以有: 扩展和事务范围的EntityManager, 容器管理或应用程序管理的EntityManager。 JTA或本地资源EntityManager, 除了上述区别之外,我们还…

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

问题示例: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中,在执行事务性业务方法期间引发的异常导致事务回滚。 但是,只有系统异常(即运行时异常)才是这种情况,该方法异常未在方法签名中声明。 对于应用程序异常(即检查的异常)或任何带Appl…

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

前言:OpenOffice项目中用途:word转换pdfWindows安装、转换:安装包下载后一路OK就可以正常安装,转换没有问题Linux安装、转换:安装有分DEB包和RPM包,下面会说明各自安装方法在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存储桶中获取结果 在开始这三个高级步骤之前&…