Hibernate – Spring transaction doesn’t rollback with exception

exceptionhibernaterollbackspring-mvcspring-transactions

Config.xml

<bean id="emfactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="persistenceUnitName" ref="default"/>
    <property name="jpaVendorAdaptor">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdaptor"/>
    </property>
    <property name="jpaProperties">
        <prop key="hibernate.show_sql">true</prop>
        <prop key="hibernate.dialect">com.xxx.xxx.xxx.xxx.SQLServer2012CustomDialect</prop>
    </property>
</bean>

<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="emfactory"/>
</bean>

Service.java

@Transactional
public void save(Dto dto) throws Exception{
    dao.save(entity);
    throw new Exception();
}

My problem is this exception does not rollback transaction. I have searched a lot and found that spring rollback transaction for runtime/unchecked exceptions by default. I have tried as following;

@Transactional
public void save(Dto dto) throws Exception{
    dao.save(entity);
    throw new RunTimeException();
}

This is working fine but it is not always in code those throws runtime exception everywhere. So, I do dig up and found rollbackFor as following;

@Transactional(rollbackFor = Exception.class)
public void save(Dto dto) throws Exception{
    dao.save(entity);
    throw new Exception();
}

Now I have to change all of my codes to change @Transactional with rollbackFor. But any other way to change all @Transaction advice property to rollbackFor = Exception.class ?

Best Answer

Take a look also at the red rectangle in the image:

enter image description here

With @Transactional The default is to rollback only unchecked exceptions, checked exception won't rollback by default.

This might solve your problem: (Look at the red rectangle)

enter image description here

You suppose to pass an array of classes to this attribute, then you should write it like this:

@Transactional(rollbackFor = new Class[]{Exception.class})

and not like you wrote it:

@Transactional(rollbackFor = Exception.class)

Now, if you want to rollback checked exceptions without specifying the rollbackFor property, you'll have to add XML configuration, to your configuration file. Like this:

<tx:advice id="txAdvice">
    <tx:attributes>
        <tx:method name="*" rollback-for="Throwable"/>
    </tx:attributes>
</tx:advice>

Add this to your configuration XML file. The above will rollback checked exceptions.