petrov.aleksandr
petrov.aleksandr

Reputation: 642

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?

Upvotes: 0

Views: 128

Answers (1)

Mark Rotteveel
Mark Rotteveel

Reputation: 109015

The try-catch with rollback should be over the entire unit-of-work. 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. The fact you commented out the commit() after your unit-of-work is also not advisable. 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.

Upvotes: 1

Related Questions