- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我们有一个在 JBoss 5.1 上运行的 Java 应用程序,在某些情况下,我们需要防止事务关闭,以防某些底层方法抛出 JDBCException
。
我们有一个如下所示的 EJB 方法
@PersistenceContext(unitName = "bar")
public EntityManager em;
public Object foo() {
try {
insert(stuff);
return stuff;
} (catch PersistenceException p) {
Object t = load(id);
if (t != null) {
find(t);
return t;
}
}
}
如果 insert
由于 PersistenceException
(包装了由约束违反引起的 JDBCException
)而失败,我们希望继续执行 load
在同一个事务中。
我们现在无法执行此操作,因为事务已被容器关闭。这是我们在日志中看到的内容:
org.hibernate.exception.GenericJDBCException: Cannot open connection
javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: Cannot open connection
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:614)
...
Caused by: javax.resource.ResourceException: Transaction is not active: tx=TransactionImple < ac, BasicAction: 7f000101:85fe:4f04679d:182 status: ActionStatus.ABORT_ONLY >
EJB 类标有以下注解
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
是否有任何适当的方法来防止事务在这种特定情况下回滚?
最佳答案
你真的不应该尝试那样做。正如在另一个答案中提到的,并引用了 Hibernate Docs,Hibernate 抛出的任何异常都不应被视为可恢复的。这可能会导致您遇到一些难以发现/调试的问题,特别是 hibernate 自动脏检查。
解决此问题的一种简洁方法是在插入对象之前检查这些约束。使用查询检查是否违反了数据库约束。
public Object foo() {
if (!objectExists()) {
insertStuff();
return stuff();
}
// Code for loading object...
}
我知道这看起来有点痛苦,但这是您确定违反了哪个约束的唯一方法(您无法从 Hibernate 异常中获取该信息)。我相信这是最干净的解决方案(至少是最安全的)。
如果您仍想从异常中恢复,则必须对代码进行一些修改。
如前所述,您可以手动管理交易,但我不建议这样做。 JTA API 实在是太麻烦了。此外,如果您使用 Bean Managed Transaction (BMT),则必须为 EJB 中的每个方法手动创建事务,要么全有要么全无。
另一方面,您可以重构您的方法,以便容器为您的查询使用不同的事务。像这样:
@Stateless
public class Foo {
...
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public Object foo() {
try {
entityManager.insert(stuff);
return stuff;
} catch (PersistenceException e) {
if (e.getCause() instanceof ConstraintViolationException) {
// At this point the transaction has been rolled-backed.
// Return null or use some other way to indicate a constrain
// violation
return null;
}
throw e;
}
}
// Method extracted from foo() for loading the object.
public Object load() {
...
}
}
// On another EJB
@EJB
private Foo fooBean;
public Object doSomething() {
Object foo = fooBean.insert();
if (foo == null) {
return fooBean.load();
}
return foo;
}
当您调用 foo() 时,当前事务 (T1) 将被挂起,容器将创建一个新事务 (T2)。当错误发生时,T2 将被回滚,T1 将被恢复。当调用 load() 时,它将使用 T1(它仍然处于 Activity 状态)。
希望对您有所帮助!
关于java - 在 JBoss + Hibernate 中防止事务回滚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8730617/
我是 JBoss 的新手,发现了很多不同的术语 - JBoss EAP、JBoss Server、Wildfly、Jboss Web,以及很多不是最新的或针对旧版本的文档。 我从哪里开始了解 JBos
JBoss ESB 服务器之间有什么区别(可在此处获得:http://jbossesb.jboss.org/downloads/) 和 JBoss fuse ( http://www.jboss.or
我在我的 PC 上安装了 JBoss 4 到目录 C:\JBoss4 并将环境变量 JBOSS_HOME 设置为此目录: JBOSS_HOME=C:\JBoss4 我需要在同一台 PC 上安装 JB
我有一个 JBoss 服务器正在运行并且想要部署一个服务。 该服务连接到在以下 xml 文件中配置的数据库 jdbc:postgresql://localhost:543
jboss 中的超时是如何工作的?网络应用程序如何知道何时重定向到登录页面? 只是为了澄清! -我知道如何在 jboss 上配置超时。我的问题是,Jboss 如何知道 session 已超时以及何时超
使用JBoss Forge启动新项目时,默认情况下该项目是使用Maven构建系统创建的。我如何利用Forge 2. *的Gradle插件使用Gradle而不是Maven创建项目? % forge Us
当前配置: 正在运行的16个Pod,基于JBoss TCP的集群以及google ping发现。容器作为状态集部署在Kubernetes集群上。 没有负载的初始群集按预期运行,没有任何单个问题,但是当
我以为这将是一个 JBoss 常见问题解答,但我找不到它。 我想同时运行 JBoss 4 和 JBoss 5。我通过将端口的前导数字更改为 9 手动更改了 JBoss 5 服务器/默认实例上的所有端口
我们在 JBoss AS 6 上实现了一些服务作为我们希望迁移到 JBoss AS 7 的单例服务。 这些服务在 jboss-service.xml 文件中声明,该文件位于 EJB 包中,类似于以下代
例如,如何确定我的简单 JBoss 4.2.3 服务器正在监听端口 8080? 这是我最接近的一次,但这不起作用: MBeanServerConnection server = (MBeanServe
我正在尝试找到从语法上确定我的程序是在 Jboss 5 还是 Jboss 7 (eap-6.1) 上运行的最佳方法。到目前为止,我找到的方法是特定于 jboss 5 或 jboss 7 的,这不起作用
我在域模式下使用 JBoss 6.4.8 版本。我想通过 CLI 添加这 4 个系统属性: 1- /host=myserver/server-config=node/system-property=j
在 JBoss 4 中,您可以在文件中设置对象的部署顺序( .jar 、 .war 、 .sar 等...): conf/xmdesc/org.jboss.deployment.MainDeploye
概括地说,JBoss 5 的关闭有什么作用?如果我只是杀死 java 进程而不是优雅地关闭 JBoss,可能会出现什么问题? 对于我的应用程序来说,正常的 JBoss 5 关闭大约需要 6 分钟,这个
我最近在 CentOS 6.7 服务器上安装了 JBoss AS 7。 jboss as 工作正常。为了测试,我部署了一个 .war 文件并对其进行了测试,效果很好!但现在我尝试从我的台式电脑访问相同
我有 jboss 应用程序。并想自动测试部署。并希望将此任务作为项目添加到 Hudson 我的愿景基于以下阶段: 将我的应用程序放到 JBoss(复制耳朵、配置、库等) 运行 JBoss 我有一台 L
我对 JBoss 很陌生。目前我有一个需求,我需要在 JBoss 上部署应用程序(已经在 Tomcat 上运行)。我下载了 JBoss,但是版本 7 中的目录结构不同。 我正在运行 bin\stand
我是 JBoss AS 7 的新手。我尝试在 JBoss AS 7 上部署我的 war 文件,这似乎工作正常。我的问题是在哪里可以看到部署的内容。 我希望它像 Tomcat 一样,它应该有一个探索的
我使用多播方法在两个不同的 JBoss 服务器之间配置了集群。 当我启动两个 JBoss 服务器时,两个服务器都将连接。 一天后,我收到以下消息 server.log 中的群集开始显示错误 05:28
为了打开/关闭我们产品的跟踪-“类别”或“记录器”标签,我们应该在jboss-log4j.xml中使用什么? 默认情况下,JBoss在jboss-log4j.xml中使用“类别”。 但据我所知,不赞成
我是一名优秀的程序员,十分优秀!