AeroEd
AeroEd

Reputation: 41

SpringBoot @Transactional rollback not working

I'm new to springboot and I'm considering it for a new project. While testing its capabilities, I keep failing using the @Transactional annotation.

I made a little MySql database to which I connect setting this application.properties file:

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3311/mb
spring.datasource.username=mb
spring.datasource.password=password
spring.datasource.tomcat.default-auto-commit=false

Hereunder is a little class I use to access the database. In the insertUser(...) method, I intentionnaly repeated the insert statement so that the second insert statement would cause a rollback because of a duplicate entry on the primary key of the table.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

@Repository
@Transactional
public class UserRepository {
    protected final Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    protected JdbcTemplate jdbc;


    public User getUser(long id) {
        return jdbc.queryForObject("SELECT * FROM test_table WHERE id=?", userMapper, id);
    }

    public List<User> getUsers(long[] ids) {
        String inIds = StringUtils.arrayToCommaDelimitedString(ObjectUtils.toObjectArray(ids));
        List<User> u= jdbc.query("SELECT * FROM test_table WHERE id IN (" + inIds + ")", userMapper);
        return u;
    }

    @Transactional
    public int insertUser(User u) {

        int total = jdbc.update("insert into test_table values ('"+u.id+"', '"+u.firstname+"', 'toto', '"+u.email+"', NOW())");
        //second insert that will cause an exception due to a duplicate key on PK (first column)
        total += jdbc.update("insert into test_table values ('"+u.id+"', '"+u.firstname+"', 'toto', '"+u.email+"', NOW())");
        return total;
    }

    private static final RowMapper<User> userMapper = new RowMapper<User>() {
        public User mapRow(ResultSet rs, int rowNum) throws SQLException {
            User user = new User(rs.getLong("id"), rs.getString("firstname"));
            user.email = rs.getString("email");
            System.out.println("recup du user "+user.id + user.firstname);
            return user;
        }
    };

} 

Even with java throwing the exception, looking in the database shows that the rollback never happens and the first insert is persisted.

Why ?

Upvotes: 0

Views: 2201

Answers (1)

AeroEd
AeroEd

Reputation: 41

solution found : the default storage engine (MyISAM) that i ssetted while creating a mysql table cannot deal with multiple statement transactions. Creating tables with InnoDB's engine makes everything work perfectly.

Upvotes: 2

Related Questions