Jpa JTA UserTransaction回滚不起作用
我试着简单地描述一下我的环境。技术:EJB3.1、JSF、JBoss7.1.1 存在服务类(@SessionScoped@Stateful)。服务类调用Dao类(@Stateless) 我想:Jpa JTA UserTransaction回滚不起作用,jpa,ejb,translation,jta,Jpa,Ejb,Translation,Jta,我试着简单地描述一下我的环境。技术:EJB3.1、JSF、JBoss7.1.1 存在服务类(@SessionScoped@Stateful)。服务类调用Dao类(@Stateless) 我想: 仅在@StateLess bean(Dao)中使用EntityManager 大多数情况下都有短事务(如持久、合并) 对于某些多步骤方法有一个长事务(方法也在Dao中) 具有实际(最新,无一级缓存)数据 我有: Pesistense.xml 事务拦截器 @Transactional @Interce
- 仅在@StateLess bean(Dao)中使用EntityManager
- 大多数情况下都有短事务(如持久、合并)
- 对于某些多步骤方法有一个长事务(方法也在Dao中)
- 具有实际(最新,无一级缓存)数据
@Transactional
@Interceptor
public class TransactionInterceptor implements Serializable {
@Resource
private UserTransaction userTransaction;
@AroundInvoke
public Object verifyAccess(InvocationContext context) throws
Exception {
Object result = null;
try {
userTransaction.begin();
result = context.proceed();
userTransaction.commit();
} catch (Exception e) {
userTransaction.rollback();
throw new CustomRuntimeException(e.getMessage());
}
return result;
}
}
问题:
若向Dao方法抛出异常,则部分数据将保存在DB中,而不是全部回滚
我认为,需要将事务连接到EM。或者断开连接,将每个项目立即保存到DB(使用缓存)。
我尝试过不同的方法,但没有成功
提前谢谢 这看起来特别有问题:
<property name="hibernate.connection.autocommit" value="true"/>
您不应该在persistence.xml
文件中进行任何连接管理。
元素和将连接信息放入
的概念是相互排斥的
JPA提供者可以创建和管理连接(使用属性),也可以从容器中获取连接(使用jta数据源)。把两者都放进去会给你带来不可预知的结果。如果JPA提供商选择遵守连接属性,您可以非常轻松地关闭事务管理、连接池等
您想要的是在容器中配置所有这些内容,而不要在持久性单元声明中进行任何配置
更新
TransactionManagementType.BEAN
(BMT)和UserTransaction
的组合应该可以。请注意,您希望捕获可丢弃的而不是异常
。此外,rollback()
调用还可以抛出应该处理的异常。不过,总的来说,这应该会产生您想要的结果
请仔细注意,虽然这看起来与您从TransactionManagementType.CONTAINER
(CMT)中获得的几乎相同,但没有拦截器,但它们在一个关键方面存在差异:
- 两个CMT bean可以共享同一事务
- 两个BMT bean不能共享同一事务
这是因为在使用BMT调用任何bean之前,容器需要挂起任何可能正在进行的事务。在这方面,术语Bean管理的事务实际上有点用词不当,因为容器在调用bmtbean之前总是对任何正在进行的事务采取行动
因此,BMT和CMT不是平等的,实际上不可能使用BMT实现一些基本的CMT功能,例如支持或必需的。感谢您的重播!我已经从persistence.xml中删除了所有属性(除了),感谢您的重播!我认为,这是一个很好的观察。但这并没有解决我的问题。可能问题与TransactionManagementType有关(它应该使用TransactionManagementType.CONTAINER,但在本例中我得到了异常:“java.lang.IllegalStateException:线程上的tx错误:预期TransactionImple”)
@Transactional
@Interceptor
public class TransactionInterceptor implements Serializable {
@Resource
private UserTransaction userTransaction;
@AroundInvoke
public Object verifyAccess(InvocationContext context) throws
Exception {
Object result = null;
try {
userTransaction.begin();
result = context.proceed();
userTransaction.commit();
} catch (Exception e) {
userTransaction.rollback();
throw new CustomRuntimeException(e.getMessage());
}
return result;
}
}
<property name="hibernate.connection.autocommit" value="true"/>