0

我试图简短地描述我的环境。技术:EJB 3.1、JSF、JBoss 7.1.1

有服务类(@SessionScoped @Stateful)。服务类调用 Dao 类 (@Stateless)

我想 :

  • 仅在 @StateLess bean 中使用 EntityManager (Dao)
  • 在大多数情况下有短事务(如持久化、合并)
  • 对一些多步骤方法有一个长事务(方法也在 Dao 中)
  • 有实际的(最新的,没有一级缓存的)数据

我有: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。或断开连接将每个项目立即保存到数据库(使用缓存)。我尝试了不同的方法,但没有成功。

提前感谢您!

4

1 回答 1

0

这看起来特别有问题:

<property name="hibernate.connection.autocommit" value="true"/>

您根本不应该在persistence.xml文件中进行任何连接管理。<jta-data-source>放入连接信息的元素和概念<properties>是相互排斥的。

JPA 提供者要么创建和管理连接(使用属性),要么从容器获取连接(使用 jta-data-source)。将两者都放在那里会给您带来不可预测的结果。如果 JPA 提供者选择尊重连接属性,您可以很容易地关闭事务管理、连接池等。

你想要的是在容器中配置所有这些东西,而不是在持久性单元声明中做任何事情。

更新

TransactionManagementType.BEAN(BMT)和的组合UserTransaction应该没问题。请注意,您需要 catchThrowable而不是Exception. 调用也rollback()可以抛出应该处理的异常。不过,总的来说,这应该会产生您想要的结果。

请注意,虽然这看起来与您从TransactionManagementType.CONTAINER(CMT) 获得的内容几乎相同并且没有拦截器,但它们确实在一个关键方面有所不同:

  • 两个 CMT bean 可以共享同一个事务
  • 两个 BMT bean不能共享同一个事务。

这是因为容器需要在使用 BMT 调用任何 bean 之前暂停任何可能正在进行的事务。在这方面,术语Bean-Managed Transaction实际上有点用词不当,因为容器总是在调用 BMT bean 之前对正在进行的任何事务采取行动。

因此,BMT 和 CMT 并不是平等的,实际上不可能实现一些基本的 CMT 功能,例如SUPPORTSREQUIRED使用 BMT。

于 2012-06-18T19:30:44.817 回答