Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Annotation @Transactional. How to rollback?

I used this annotation successfully for a Dao class. And rollback works for tests.

But now I need to rollback real code, not just tests. There are special annotations for use in tests. But which annotations are for non-test code? It is a big question for me. I spent a day for that already. The official documentation did not meet my needs.

class MyClass { // this does not make rollback! And record appears in DB.
        EmployeeDaoInterface employeeDao;

        public MyClass() {
            ApplicationContext context = new ClassPathXmlApplicationContext(
                    new String[] { "HibernateDaoBeans.xml" });
            employeeDao = (IEmployeeDao) context.getBean("employeeDao");
         }

        @Transactional(rollbackFor={Exception.class})
    public void doInsert( Employee newEmp ) throws Exception {
        employeeDao.insertEmployee(newEmp);
        throw new RuntimeException();
    }
}

employeeDao is

@Transactional
public class EmployeeDao implements IEmployeeDao {
    private SessionFactory sessionFactory;

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

    public void insertEmployee(Employee emp) {
        sessionFactory.getCurrentSession().save(emp);
    }
}

And here is a test for which the annotations work well:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/HibernateDaoBeans.xml" })
@TransactionConfiguration(transactionManager = "txManager", defaultRollback = true)
@Transactional
public class EmployeeDaoTest {

    @Autowired
    EmployeeDaoInterface empDao;

    @Test
    public void insert_record() {
       ...
       assertTrue(empDao.insertEmployee(newEmp));
    }

HibernateDaoBeans.xml

   ...
<bean id="employeeDao" class="Hibernate.EmployeeDao">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
    <tx:annotation-driven transaction-manager="txManager"/>

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



**YES, I rolled back the transaction. I just added BEAN for the service... and then annotation @Transactional begin to work :-) **

<bean id="service" class="main.MyClass">
    <property name="employeeDao" ref="employeeDao" />
</bean>

Thanks all, Russia will not forget you!

like image 457
Moscow Boy Avatar asked Oct 24 '11 08:10

Moscow Boy


People also ask

Does @transactional rollback?

The @Transactional annotation makes use of the attributes rollbackFor or rollbackForClassName to rollback the transactions, and the attributes noRollbackFor or noRollbackForClassName to avoid rollback on listed exceptions. The default rollback behavior in the declarative approach will rollback on runtime exceptions.

How do I rollback a transaction Spring?

You can throw an unchecked exception from the method which you wish to roll back. This will be detected by spring and your transaction will be marked as rollback only.

How do I rollback a transaction in JPA?

To rollback a transaction you can use @Transaction annotation. You can either implement it on method level or class level. Class level @Transactional(rollbackFor = Exception.


2 Answers

Just throw any RuntimeException from a method marked as @Transactional.

By default all RuntimeExceptions rollback transaction whereas checked exceptions don't. This is an EJB legacy. You can configure this by using rollbackFor() and noRollbackFor() annotation parameters:

@Transactional(rollbackFor=Exception.class)

This will rollback transaction after throwing any exception.

like image 111
Tomasz Nurkiewicz Avatar answered Oct 10 '22 03:10

Tomasz Nurkiewicz


or programatically

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
like image 43
Stefan K. Avatar answered Oct 10 '22 03:10

Stefan K.