Spring Transaction - 当一个db更新失败时自动回滚以前的db更新

Vaa*_*ndu 5 java spring hibernate transactions

我正在编写一个简单的应用程序(Spring + Hibernate + PostgreSql db).我只是想构建一个示例对象并在db中持久化.

我运行一个简单的java类main方法,我已经加载了applicationContext并且引用了服务类,如下所示

TestService srv = (TestService)factory.getBean("testService");  
Run Code Online (Sandbox Code Playgroud)

应用上下文 - 上下文:

<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactoryVsm" />
</bean>

<bean id="testService" class="com.test.service.TestServiceImpl">
    <property name="testDao" ref="testDao"/>
</bean>

<bean id="testDao" class="com.test.dao.TestDaoImpl>
    <property name="sessionFactory" ref="sessionFactoryVsm"/>
</bean>
Run Code Online (Sandbox Code Playgroud)

在TestService中我注入了TestDao.在测试服务方法中,我构造了雇员对象emp1和emp2并且两次调用dao来更新.

TestDaoImpl代码:

public void saveOrUpdate(BaseDomainModel baseObject) {

    Session session = null;
    try {
        session = getHibernateTemplate().getSessionFactory().openSession();
        session.saveOrUpdate(baseObject);
        session.flush();
    } catch (Exception e) {
        logger.error("Generic DAO:saveOrUpdate::" + e);
        e.printStackTrace();
    } finally {
        if (session != null) {
            session.close();
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

当emp2更新失败时,emp1也应该失败.我怎么做.请指教

提前致谢

更新 :

谢谢南大.我试过Declarative交易.但它没有用.emp1被持久化并且没有回滚eveb第二次dao调用失败.我已经为该方法添加了事务建议.

为了测试是否应用了交易建议我将传播更改为"NOT_SUPPORTED".但是emp1仍然存在.期望是我们应该有Transaction Not Supported类型的异常.请指教 .

更新

@seanizer - 感谢您的更新.我甚至尝试将
@Transactional(propagation = Propagation.NOT_SUPPORTED)public void saveEmp(Employee emp)添加到该服务方法.但它没有用.此外,只有当我需要调用一个dao时,迭代集合才能保持良好状态.如果我必须调用两个不同的dao来持久化obj1和obj2-这可能没有帮助.为了检查交易是否得到应用,我得到@Transactional(propagation = Propagation.NOT_SUPPORTED).但仍然obj1持续存在.我只是怀疑给出的xml配置/注释是否正确.请检查

@Transactional(propagation=Propagation.NOT_SUPPORTED)
public void saveEmp(Employee emp)
Run Code Online (Sandbox Code Playgroud)

我正在使用org.springframework.orm.hibernate3.HibernateTransactionManager作为transactionManager.它是否正确 ?


更新

我创建了从RuntimeException扩展的异常类myRuntimeExp,并将其从Dao方法抛出到service方法.但仍然没有发生回滚.我只是怀疑我是否在applnContext.xml中正确地给出了配置.有人可以帮助我检查是否将交易建议/注释应用于该方法?有没有办法在调试模式下运行它并检查

问题 :

我在用

<bean id="txManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactoryVsm" />
    </bean>

<tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
         <tx:method name="saveEmp" propagation="REQUIRED" rollback-for="Exception"/>
        <tx:method name="*"/>
    </tx:attributes>
 </tx:advice>   
 <aop:config>
    <aop:pointcut id="testServiceOperation" expression="execution(*com.test.service.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="testServiceOperation"/>
  </aop:config> 
Run Code Online (Sandbox Code Playgroud)

但它应该是当前会议,它工作正常.

session = getHibernateTemplate().getSessionFactory().openSession();
Run Code Online (Sandbox Code Playgroud)

Sea*_*oyd 5

如果您使用声明式事务管理,您可能会丢失大部分样板文件:

测试DaoImpl:

private SessionFactory sessionFactory;

public void setSessionFactory(SessionFactory f){
    this.sessionFactory = f;
}

public void saveOrUpdate(BaseDomainModel baseObject) {
    Session session = sessionFactory.getCurrentSession();
    session.saveOrUpdate(baseObject);
}
Run Code Online (Sandbox Code Playgroud)

@Transactional您可以使用(或 xml 配置)从服务层控制事务处理

测试服务实现:

private TestDao testDao;

public void setTestDao(TestDao  d){
    this.testDao = d;
}

@Transactional // one transaction for multiple operations
public void someServiceMethod(Collection<BaseDomainModel> data){
     for(BaseDomainModel baseObject : data)
         testDao.saveOrUpdate(baseObject);
}
Run Code Online (Sandbox Code Playgroud)

参考:


vir*_*m03 5

默认情况下,Spring 只会回滚未经检查的异常。您必须提供rollback-for 属性并指定您要捕获的异常。


从 Spring文档

但是请注意,Spring Framework 的事务基础结构代码默认只会在运行时、未检查异常的情况下将事务标记为回滚;也就是说,当抛出的异常是RuntimeException的实例或子类时。(默认情况下,错误也会导致回滚。)从事务方法抛出的已检查异常不会导致事务被回滚。