java - JDBC 事务的问题。不能让它成为原子性
问题描述
我有代码:
@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();
}
}
}
我想要,如果第二次插入失败,那么我们不进行第一次插入。但是这段代码不起作用,如果我们删除第一个评论,第一次插入就会完成。我究竟做错了什么?
解决方案
try-catch
withrollback
应该覆盖整个工作单元。现在你在第一次失败后回滚,然后继续,好像什么都没发生一样。结果,第二个插入将在它自己的事务中(因此与第一个不同的事务),并单独成功。
相反,您需要在两个语句(整个事务)之后回滚,而不是每个语句。
try {
// first insert
// second insert
} catch (SQLException e) {
connection.rollback();
}
顺便说一句,在您的工作单元commit()
之前有一个没有意义,并且似乎表明整个事务管理中断。您在工作单元之后注释掉的事实commit()
也是不可取的。如果连接关闭,您的事务将被回滚(或某些数据库:已提交),如果您的连接被重用,则工作将被提交或回滚,具体取决于后续代码重用连接将执行的操作。
推荐阅读
- php - 奇怪的浮点数增量结果,使用 PHP Laravel API
- python - 如果内容处置或 url 本身中不存在文件名,如何检索文件名?
- scala - 将患者分配到斯卡拉斯帕克最近的设施
- api - 如何开始将实用程序帐户集成到应用程序中?
- c - STM32F103C8 项目 - 我无法让 HAL 在我自己的函数中工作
- python - 从终端运行后保存 Python 变量
- mysql - 尝试在 Laravel 中进行多输入搜索
- python - 我的迭代在第一次运行后不起作用
- mysql - 阅读时无法在codeigniter中显示项目。它显示致命错误
- ios - 按下按钮时如何返回下一个数组?