【问题标题】:JDBC rollback method not behaving like expectedJDBC 回滚方法的行为不像预期的那样
【发布时间】:2014-07-17 13:29:42
【问题描述】:

我正在开发一个用 Java 处理 MySQL 数据库中数据的软件,但由于回滚调用没有达到我的预期,我遇到了一个问题......我的函数由两个查询组成,我需要回滚如果第二个查询没有执行(或有错误)以保持一致的数据。这是我的代码,我一直在故意犯语法错误,以便在第二次查询执行期间抛出错误。回滚方法被调用,但我的第一条语句在我的数据库中执行并提交,你能解释一下为什么吗?

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

我也在使用这样的连接池,可能错误是因为这个:

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

【问题讨论】:

  • 您的桌子是 MyISAM 吗?在这种情况下,MySQL 中没有事务。

标签: java mysql sql jdbc rollback


【解决方案1】:

您必须将连接的 autoCommit 设置为 false。

con.setAutoCommit(false);

否则,每个执行的更新都会立即提交。

此外,使用支持事务的存储引擎,如 InnoDB。 MyISAM 不支持事务。

【讨论】:

  • 之前已经完成了,否则我会有一个特定的消息向我解释这个^^
  • 对于 MySQL,您还需要确保表使用的存储引擎实际上确实支持事务。
  • 看来是他干的:dataSource.setDefaultAutoCommit(false);
  • 我正在使用 MyISAM 是否支持交易?
  • @Ko2r 不,MyISAM 不支持事务
【解决方案2】:

通过在我的 CREATE 语句中将 ENGINE=MyISAM 替换为 ENGINE=INNODB,我能够让一切正常工作。谢谢大家的帮助!

【讨论】:

  • 这不是“谢谢”评论。是 OP 回答他们自己的问题并在他们的回答末尾添加“谢谢”。
  • 您还应该接受您的回答(这很好),以便将此问题标记为已回答。
猜你喜欢
  • 2017-04-11
  • 1970-01-01
  • 2021-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-11
  • 2016-01-28
  • 2018-12-15
相关资源
最近更新 更多