vctlzac
vctlzac

Reputation: 847

Hibernate + Spring transaction rollback not working

When service thown an exception that is configured to rollback (rollbackfor), this rollback not working.

Service class:

@Service("bookService")
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { BusinessException.class }, readOnly = true)
public class BookServiceImpl implements BookService {

    @Autowired
    private BookRepository bookDAO;

     @Override
     @Transactional(readOnly = false)
     public void transactionTest(Book book) throws BusinessException {
          try {
               bookDAO.test(book);
          } catch (DAOException e) {
               throw new BusinessException("test rollback - service");
          }
     }
}

Repository class:

@Repository("bookRepository")
public class BookRepositoryImpl implements BookRepository {

    @Autowired
    private SessionFactory sessionFactory;

@Transactional(readOnly = false)
@Override
public Book saveOrUpdate(Book book) {
    if (book.getId() != null) {
        getSession().merge(book);
    } else {
        getSession().save(book);
    }
    return book;
}

@Transactional(readOnly = false)
@Override
public void test(Book book) throws DAOException {

    saveOrUpdate(book);
    System.out.println(book.getTitle() + " inserted!");
    throw new DAOException("Test rollback");
}

}

There are one situation that rollback works. To this, I need change BookServiceImpl removing readOnly = true and removing "@Transactional(readOnly = false)" of the "transactionTest" method. But for security reasons I wish use readOnly = true for all class and specify what is method use readOnly = false

Upvotes: 1

Views: 4725

Answers (1)

Jigar Parekh
Jigar Parekh

Reputation: 6273

currently for whole BookServiceImpl transaction configuration is @Transactional(propagation = Propagation.REQUIRED, rollbackFor = { BusinessException.class }, readOnly = true)

and for transactionTest overridden annotation is @Transactional(readOnly = false), when you override annotation with class to method whole annotation updated instead of just specified attribute.

instead of this you should have below as code for BookServiceImpl

@Service("bookService")
@Transactional(readOnly = true)
public class BookServiceImpl implements BookService {

    @Autowired
    private BookRepository bookDAO;

     @Override
     @Transactional(propagation = Propagation.REQUIRED, rollbackFor = { BusinessException.class },readOnly = false)
     public void transactionTest(Book book) throws BusinessException {
          try {
               bookDAO.test(book);
          } catch (DAOException e) {
               throw new BusinessException("test rollback - service");
          }
     }
}

and further if you want same kind of transaction on DAO (Repository) level then specify it or just let service to take care about transaction (assuming repository are not going to be directly interfaced with client).

Upvotes: 2

Related Questions