Andrea
Andrea

Reputation: 16560

Nested @Transactional annotation behaviour on Spring Data JPA

I have an entity User, a Repository/Dao class UserDao (using Spring Data JPA) and a Service class UserService with a method addUser annotated as @Transactional:

@Service
public class UserService {

  @Autowired
  private UserDao userDao;

  @Transactional
  public void addUser() throws Exception {

    User user = new User();
    user.setUsername("aaa");

    // Save the user, but since this method have the @Transactional
    // annotation it should not be committed....
    userDao.save(user);

    // Forcing an error here I expected that the previous operation
    // were rolled back.. Instead the user is saved in the db.
    if ("".equals("")) {
      throw new Exception("something fails");
    }

    // Other operations (never executed in this example)
    user.setUsername("bbb");
    userDao.save(user);

    return;
  } // method addUser

} // class UserService

The UserDao is simply this:

@Transactional
public interface UserDao extends CrudRepository<User, Long> { }

Reading the Spring Data JPA documentation and other questions on the same argument (1, 2) my expectations were that each operations inside a method marked with @Transactional will be rolled back if some error occurs..

What am I doing wrong? Is there a way for rollback the save operation in the previous example if an error occurs?

Upvotes: 2

Views: 3706

Answers (2)

Alan Hay
Alan Hay

Reputation: 23226

Your understanding is correct however automatic rollback only occurs for runtime, unchecked exceptions.

So, assuming your transaction manager is configured correctly, to rollback on a non-runtime, checked exception add the rollbackFor attribute to your transactional annotation:

@Transactional(rollbackFor=Exception.class)
public void addUser() throws Exception {

}

Upvotes: 4

Aviad
Aviad

Reputation: 1549

You need to add things to your Xml configuration file.. you need to add trnasaction manager.

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

<!-- Creating TransactionManager Bean, since JDBC we are creating of type
    DataSourceTransactionManager -->
<bean id="txMgrDataSource"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="DataSource" />
</bean>

Assuming your data source is:

<bean id="DataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="####" />
    <property name="url"
              value="jdbc:sqlConnection" />
    <property name="username" ref="user" />
    <property name="password" ref="pass" />

</bean>

Upvotes: 0

Related Questions