Search code examples
javamysqlsqljdbcrollback

JDBC rollback method not behaving like expected


I'm developing a software in Java processing data in a MySQL database and I'm facing an issue due to a rollback call not doing what I was expecting ... My function is composed of two queries and I need to rollback if the second query is not executed (or with errors) in order to keep consistent data. Here is my code, I've been doing a syntax error on purpose for throwing an error during the second query execution. The rollback method is called but my first statement is executed and committed in my database, can you explain me why ?

    @Override
    public void updateIndicatorRemainingTimeAndExecuted(int id) throws ServiceException {
        PreparedStatement stmt = null;
        Connection con = null;
        String query1 = "UPDATE "+indicatorSchedulerTable+" i " 
        +"JOIN adv_frequency f ON i.id_frequency = f.id_frequency "
        +"SET i.ind_remainingtime = i.ind_remainingtime + f.frq_seconds WHERE id_indicator = ?";
        String query2 = "UPDATE "+indicatorSchedulerTable
                +" SET ind_executing =  WHERE id_indicator = ?";
        try {
            con = mySQLManipulator.getConnection();
            stmt = con.prepareStatement(query1);
            stmt.setInt(1,id);
            /*Updating remaining time*/
            stmt.executeUpdate();
            stmt.close();
            /*Updating executing status*/
            stmt = con.prepareStatement(query2);
            stmt.setInt(1,id);
            stmt.executeUpdate();
            con.commit();
        } catch (SQLException e) {
            try {
                con.rollback();
                System.out.println("ROLLBACK OK");
            } catch (SQLException e1) {
                throw new ServiceException("Problème de rollback lors de la mise à jour dans la fonction \"updateIndicatorRemainingTimeAndExecuted\" : "+e1.getMessage()+e.getMessage());
            }
            throw new ServiceException("Problème lors de la mise à jour dans la fonction \"updateIndicatorRemainingTimeAndExecuted\" : "+e.getMessage());
        } finally {
            handleDatabaseClosure(con, stmt, null);
        }
    }

I'm also using a pool of connection like this maybe the error is because of this :

public class JDBCManipulator {
    private static final BasicDataSource dataSource = new BasicDataSource();
    private DBType type = null;
    private String URI = null;

    public JDBCManipulator(DBType type, String URI, String user, String password) throws Exception {
        if(type == DBType.PHOENIX){
            Class.forName("org.apache.phoenix.jdbc.PhoenixDriver");
        } else if(type == DBType.MYSQL) {
            dataSource.setDriverClassName("com.mysql.jdbc.Driver");
            dataSource.setUrl(URI);
            dataSource.setUsername(user);
            dataSource.setPassword(password);
            dataSource.setMaxActive(20);
            dataSource.setDefaultAutoCommit(false);
        } else {
            throw new Exception("Le type fournit ("+type+") pour l'initialisation de JDBCManipulator n'est pas connu ...");
        }
        this.type = type;
        this.URI = URI;
    }

    public Connection getConnection() throws SQLException {
        Connection conn = null;
        if(type == DBType.MYSQL){
            conn = dataSource.getConnection();
        } else {
            conn = DriverManager.getConnection(URI);    
        }
        return conn;
    }
}

Solution

  • I was able to get everything working by replacing ENGINE=MyISAM with ENGINE=INNODB in my CREATE statement. Thank you all for your help!