简体   繁体   English

JDBC 事务有问题。 不能让它成为原子性

[英]Problem with JDBC transaction. Can't make it atomicity

I have code:我有代码:

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

I want, that if second insert was failed, then we don't do the first insert.我想要,如果第二次插入失败,那么我们不进行第一次插入。 But this code won't work, first insert will be done if we will delete first comment.但是这段代码不起作用,如果我们删除第一个评论,第一次插入就会完成。 What am I doing wrong?我究竟做错了什么?

The try-catch with rollback should be over the entire unit-of-work.具有rollback功能的try-catch应覆盖整个工作单元。 Right now you are rolling back after the first failure, and then continue as if nothing happened.现在你在第一次失败后回滚,然后继续,好像什么都没发生一样。 As a result, the second insert will be in its own transaction (so a different transaction from the first), and succeed individually.结果,第二个插入将在它自己的事务中(因此与第一个不同的事务),并单独成功。

Instead you need to rollback after both statements (the entire transaction), not per statement.相反,您需要在两个语句(整个事务)之后回滚,而不是每个语句。

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

As an aside, having a commit() before your unit-of-work makes no sense, and seems to be an indication of broken transaction management overall.顺便说一句,在你的工作单元之前有一个commit()是没有意义的,并且似乎表明整个事务管理被破坏了。 The fact you commented out the commit() after your unit-of-work is also not advisable.您在工作单元之后注释掉commit()的事实也是不可取的。 If the connection is closed, your transaction will be rolled back (or with some databases: committed), if your connection is reused, the work will either be committed or rolled back depending on what the subsequent code reusing the connection will do.如果连接关闭,您的事务将被回滚(或某些数据库:已提交),如果您的连接被重用,则工作将被提交或回滚,具体取决于后续代码重用连接将执行的操作。

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

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