我试着尽快描述我的环境。技术:EJB 3.1,JSF,JBoss 7.1.1
有Servise-classes(@SessionScoped @Stateful)。 Servise-classes调用Dao类(@Stateless)
我想:
我有: Pesistense.xml
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:jboss/datasources/MydataSource</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.dialect"value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
<property name="hibernate.connection.autocommit" value="true"/>
<property name="hibernate.connection.characterEncoding" value="utf8"/>
<property name="hibernate.c3p0.min_size" value="5"/>
<property name="hibernate.c3p0.max_size" value="20"/>
<property name="hibernate.c3p0.timeout" value="1800"/>
<property name="hibernate.c3p0.max_statements" value="50"/>
</properties>
</persistence-unit>
道
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class UserDaoBean implements UserDAO, Serializable {
@PersistenceContext(name = "MyEntityManager")
private EntityManager em;
@Override
@Transactional
public void update(User user) throws Exception {
User tmpUser = getUser(user.getUser());
//some code, should be rollback, if it is an exception
em.persist(tmpUser);
}
交易拦截器
@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。或者断开连接将每个项目立即保存到数据库(使用缓存)。 我尝试了不同的方法,但没有成功。
提前感谢!
答案 0 :(得分:0)
这看起来特别有问题:
<property name="hibernate.connection.autocommit" value="true"/>
您不应该在persistence.xml
文件中进行任何连接管理。 <jta-data-source>
元素以及在<properties>
中放置连接信息的概念是互斥的。
JPA提供程序创建和管理连接(使用属性),或者从容器获取连接(使用jta-data-source)。将两者放在那里会给你带来不可预测的结果。如果JPA提供程序选择遵守连接属性,则可以非常轻松地关闭事务管理,连接池等。
您想要的是在容器中配置所有这些内容,而不是在持久性单元声明中执行任何操作。
TransactionManagementType.BEAN
(BMT)和UserTransaction
的组合应该没问题。请注意,您需要抓住Throwable
而不是Exception
。同样,rollback()
调用也可以抛出应该处理的异常。但总的来说,这应该产生你想要的结果。
请注意,尽管这看起来几乎与您从TransactionManagementType.CONTAINER
(CMT)获得的内容完全相同,并且没有拦截器,但它们在一个关键方面确实存在差异:
这是因为在使用BMT调用任何bean之前,容器需要挂起可能正在进行的任何事务。在这方面,术语 Bean-Managed Transaction 实际上有点用词不当,因为容器总是在调用BMT bean之前对正在进行的任何事务采取行动。
因此BMT和CMT不是平等的,实际上不可能使用BMT实现一些基本的CMT功能,例如SUPPORTS
或REQUIRED
。