当前位置: 首页 > 知识库问答 >
问题:

如何在引发异常时回滚Spring事务

徐涵亮
2023-03-14

我使用的是Spring3.0.5和Hibernate3.6。在我的项目中,有一个场景,我必须回滚在抛出的任何异常或错误发生的事务。这是示例代码,除了当我抛出异常时事务不会回滚之外,一切都很好,但是如果抛出任何异常,比如mysql.IntegrityConstraintException,那么事务会回滚,为什么在我的情况下没有发生这种情况?

    <bean id="propertyConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:database.properties"/>
    </bean>
      <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
            <property name="driverClassName" value="${jdbc.driverClassName}" />
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />

        </bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
 <property name="dataSource" ref="myDataSource" />
    <property name="packagesToScan" value="com.alw.imps"/>
    <property name="configLocation">    
        <value>
            classpath:hibernate.cfg.xml
        </value>
     </property>
    </bean>

    <bean id="stateDao" class="com.alw.imps.dao.StateDaoImpl">
     <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>


        <bean id="stateService" class="com.alw.imps.services.StateService">
       <property name="stateDao" ref="stateDao"></property>
       <property name="cityDao" ref="cityDao"></property>
       <property name="customerDao" ref="customerDao"></property>
       </bean>  

        <bean id="customerDao" class="com.alw.imps.dao.CustomerDaoImpl">
        <property name="sessionFactory" ref="sessionFactory"></property>
       </bean> 

            <bean id="cityDao" class="com.alw.imps.dao.CityDaoImpl">
              <property name="sessionFactory" ref="sessionFactory"></property>
            </bean>  





<tx:annotation-driven transaction-manager="transactionManager"  />

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

<tx:advice id = "txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
@Transactional(rollbackFor={Exception.class})
public class StateService {

  private StateDaoImpl stateDao;
  private CityDao cityDao;
  private CustomerDao customerDao;

  public void setCustomerDao(CustomerDao customerDao) {
    this.customerDao = customerDao;
  }

  public void setStateDao(StateDaoImpl stateDao) {
    this.stateDao = stateDao;
  }

  public CityDao getCityDao() {
    return cityDao;
  }

  public void setCityDao(CityDao cityDao) {
    this.cityDao = cityDao;
  }

  public void addState() {
    try {
      State state=new State();
      state.setStateName("Delhi");
      stateDao.create(state);
      addCity();
      addCustomer();
    } catch(Exception e) {
      e.printStackTrace();
    }
  }

  public void addCity() throws Exception {
    City city=new City();
    city.setCiytName("Delhi");
    city.setStateId(1);
    cityDao.create(city);
  }

  public void addCustomer() throws Exception {
    throw new java.lang.Exception();
  }
public class StateDaoImpl extends GenericDaoImpl<State, Integer> implements StateDao {
}
public class GenericDaoImpl<T,PK extends Serializable> implements GenericDao<T,PK> {
  public SessionFactory sessionFactory;
  public void setSessionFactory(SessionFactory sessionFactory) {
    this.sessionFactory = sessionFactory;
  }

  public Session getSession() {
    return sessionFactory.getCurrentSession();
  }

  public PK create(T o) {
    Session ss= getSession();
    ss.save(o);
    return null;
  }

hibernate.cfg

<hibernate-configuration>
  <session-factory>
    <property name="connection.pool_size">1</property>
    <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
    <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
    <property name="show_sql">true</property>
    <property name="hbm2ddl.auto">update</property>
    <property name="defaultAutoCommit">false</property>
    <mapping class="com.alw.imps.pojo.State"/>
    <mapping class="com.alw.imps.pojo.City"/> 
  </session-factory>
</hibernate-configuration>

因此,正如我所说,我的问题是,当我从方法addCustomer()抛出exception类型的异常时,transaction没有得到回滚

共有1个答案

蓝泰平
2023-03-14

您的事务不会回滚,因为没有引发异常:您调用的addstate()方法捕获异常:

public void addState() {
    try {
        State state=new State();
        state.setStateName("Delhi");
        stateDao.create(state);
        addCity();
        addCustomer();
    }
    catch(Exception e) {
        e.printStackTrace();
    }
}

因此,事务性Spring代理不会看到任何抛出的异常,也不会回滚事务。

它适用于从DAO抛出的异常,因为DAO本身是事务性的,所以它自己的事务性代理检测DAO抛出的异常,并将事务标记为回滚。然后异常被传播到服务并被代码捕获,但此时事务已经被标记为回滚。

 类似资料:
  • 我有办法: 和每个内部事务的另一个bean: 当我第一次尝试保存时,我有20行DB。每次下一次保存,我得到+10行。名称具有约束。当我得到错误时,事务是提交而不是继续。每次保存后我都会等待98行。

  • 问题内容: 如果在mysql命令列表中发生任何错误,是否可以自动回滚? 例如类似以下内容的东西: 现在,在执行我希望整个交易失败,因此我应该 不 看到值1在myTable的。但是不幸的是,即使事务有错误,该表也仍使用values1进行伪造。 任何想法,我如何使其回滚?(再次出现任何错误)? 编辑-从DDL更改为标准SQL 问题答案: 您可以使用13.6.7.2。DECLARE … HANDLER语

  • 这很好,但并不总是在代码中抛出运行时异常。因此,我挖掘并发现如下所示的rollbackFor; 现在,我必须更改所有代码,以使用RollBackfor更改@Transactional。但是还有其他方法可以将所有@transaction advice属性更改为rollbackFor=exception.class吗?

  • 问题内容: 我在下面使用HIbernate和Spring和JPA。当引发PersistenceException时,我想捕获它并返回错误消息,以便它不会传播到调用者。 但是我得到一个异常,说我需要在异常之后回滚事务,但是当我捕获到异常并且不想重新抛出该异常时,如何回滚它呢? 问题答案: 似乎没有办法回退由Spring ORM管理的失败事务。问题中显示的代码是服务类。将其持久性例程提取到单独的DAO

  • 我正在使用Spring JpaRepository在我的一个应用程序屏幕中实现CRUD。作为其中的一部分,我正在开发一个功能,用户可以保存所有汽车实体或没有(应该回滚)到数据库。我不确定如何使用Spring Boot、Spring Rest和Spring JPA实现此功能。 下面是我的源代码。 除此之外,我还得到了一个类似 请帮帮我。谢谢你。