简体   繁体   English

JDBC回滚方法不符合预期

[英]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. 我正在用Java开发一个软件来处理MySQL数据库中的数据,由于回滚调用未按预期运行,因此我遇到了一个问题。我的函数由两个查询组成,如果第二个查询则需要回滚不执行查询(或带有错误)以保持数据一致。 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 ? 调用了rollback方法,但是我的第一条语句已在数据库中执行并提交,您能解释一下为什么吗?

    @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;
    }
}

You have to set autoCommit of the connection to false. 您必须将连接的autoCommit设置为false。

con.setAutoCommit(false);

Otherwise, each executed update would be commited immediatelly. 否则,将立即提交每个已执行的更新。

In addition, use a storage engine that supports transactions like InnoDB. 此外,使用支持InnoDB等事务的存储引擎。 MyISAM does not support transactions. MyISAM不支持交易。

I was able to get everything working by replacing ENGINE=MyISAM with ENGINE=INNODB in my CREATE statement. 通过在CREATE语句中将ENGINE=MyISAM替换为ENGINE=INNODB ,我可以使所有工作正常进行。 Thank you all for your help! 谢谢大家的帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM