【问题标题】:Problem with JDBC transaction. Can't make it atomicityJDBC 事务的问题。不能让它成为原子性
【发布时间】:2019-11-19 08:14:50
【问题描述】:

我有代码:

 @Override
    public void update(Duck entity) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
       try {
            connection = DriverManager.getConnection(daoProperties.getUrl(), daoProperties.getUser(), daoProperties.getPassword());
            connection.setAutoCommit(false);
            connection.commit()
            preparedStatement = connection.prepareStatement(INSERT_FROG);

            preparedStatement.setInt(ID, entity.getFrogId());
            preparedStatement.setString(NAME, entity.getMyFrogFriend().name());
            preparedStatement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
            try {
                connection.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }

        try {
            PreparedStatement duckPreparedStatement = connection.prepareStatement(INSERT_DUCK);

            duckPreparedStatement.setInt(ID, entity.id());
            //..
            duckPreparedStatement.executeUpdate();
   //         throw new SQLException();
    //        connection.commit();
        } catch (SQLException e) {
            log.warning("error with statements or connection");
            try {
                connection.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }
    }

我希望,如果第二次插入失败,那么我们不进行第一次插入。但是这段代码不起作用,如果我们要删除第一个评论,第一次插入就会完成。我做错了什么?

【问题讨论】:

  • connection.commit()到底应该是NO吗?
  • 为什么你在做任何事情之前都要做connection.commit()
  • @YCF_L 是的,我已经评论过了。如果我抛出异常,提交的行将不起作用
  • @petrov.aleksandr 使您的代码更通用,这样您就不必为相同的用例复制相同的代码,其次您应该进行事务管理,以便回滚可以帮助 SQL 操作失败
  • @ScaryWombat 因为我不知道,如果第二次插入发生了事情,我怎么能回到开头

标签: java jdbc transactions


【解决方案1】:

try-catchrollback 应该覆盖整个工作单元。现在你在第一次失败后回滚,然后继续,好像什么都没发生一样。结果,第二个插入将在它自己的事务中(因此与第一个不同的事务),并单独成功。

相反,您需要在两个语句(整个事务)之后回滚,而不是每个语句。

try {
    // first insert
    // second insert
} catch (SQLException e) {
    connection.rollback();
}

顺便说一句,在您的工作单元之前拥有commit() 是没有意义的,并且似乎表明整个事务管理中断。您在工作单元之后注释掉 commit() 的事实也是不可取的。如果连接关闭,您的事务将被回滚(或某些数据库:已提交),如果您的连接被重用,则工作将被提交或回滚,具体取决于后续代码重用连接将做什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-17
    • 1970-01-01
    • 2018-12-09
    • 2019-08-05
    相关资源
    最近更新 更多