JDBC原生事务管理,类比超市购物来讲解(不常用,但作为基础还是要了解一下)
目录
1. JDBC事务管理基础
1.1 关闭自动提交模式
1.2 执行SQL语句
1.3 提交事务
1.4 处理异常
1.5 回滚事务
1.6 清理资源
1.7 恢复自动提交模式
2. 拓展知识:事务的隔离级别
3. 拓展知识:分布式事务管理
4. 结论
在软件开发中,数据库事务管理是确保数据完整性和一致性的关键环节。Java数据库连接(JDBC)为我们提供了一种原生的方式来控制数据库事务。
场景:超市购物
你正在超市购物,你的购物车就是你进行事务操作的数据库。购物过程可以看作是一系列的事务操作。
1. JDBC事务管理基础
1.1 关闭自动提交模式
在JDBC中,默认情况下,每个SQL语句执行后会自动提交事务。为了管理事务,我们首先需要关闭自动提交模式:
connection.setAutoCommit(false);
- 这就像是超市规定,在你结账之前,你可以随时更改你的购物车内容,不需要每拿一件商品就去收银台结账。
1.2 执行SQL语句
关闭自动提交后,我们可以执行多个SQL语句,这些语句将作为事务的一部分:
try {
statement.executeUpdate("UPDATE accounts SET balance = balance - 100 WHERE name = 'Alice'");
statement.executeUpdate("UPDATE accounts SET balance = balance + 100 WHERE name = 'Bob'");
// 更多的SQL操作...
} catch (SQLException e) {
// 处理SQL异常
}
- 你从货架上取下商品放入购物车(相当于执行SQL更新操作),比如你拿了一瓶牛奶和一包面包。
1.3 提交事务
如果所有SQL语句都成功执行,我们可以提交事务,使更改永久生效:
try {
connection.commit();
} catch (SQLException e) {
// 处理提交异常
}
- 当你走到收银台,告诉收银员你准备好结账了,这就是提交事务。如果收银员扫描了你所有的商品并告诉你总价,然后你支付了费用,那么这个事务就提交成功了。
1.4 处理异常
如果在执行SQL语句的过程中发生异常,我们需要捕获这些异常,并进行适当的处理,通常这意味着需要回滚事务:
try {
connection.setAutoCommit(false);
statement.executeUpdate("UPDATE accounts SET balance = balance - 100 WHERE name = 'Alice'");
statement.executeUpdate("UPDATE accounts SET balance = balance + 100 WHERE name = 'Bob'");
connection.commit();
} catch (SQLException e) {
try {
connection.rollback();
} catch (SQLException ex) {
// 处理回滚异常
}
} finally {
try {
connection.setAutoCommit(true); // 重置为自动提交模式
statement.close();
connection.close();
} catch (SQLException ex) {
// 处理关闭资源时的异常
}
}
- 如果在结账过程中,收银员发现你拿了一瓶过期的牛奶,那么超市会要求你把牛奶放回,或者换一瓶新的。这就像是回滚事务,撤销了错误的操作。
1.5 回滚事务
如果在执行过程中遇到任何错误,我们应该回滚事务,撤销所有未提交的更改:
try {
connection.rollback();
} catch (SQLException e) {
// 处理回滚异常
}
- 如果你发现总价超出了你的预算,你可以选择放弃购买,把商品放回原处,然后离开收银台。这就像是事务回滚,撤销了所有未完成的操作。
1.6 清理资源
无论事务是否成功,都应该释放数据库资源。这包括关闭Statement
和Connection
对象:
finally {
try {
if (statement != null) statement.close();
if (connection != null) connection.close();
} catch (SQLException ex) {
// 处理关闭资源时的异常
}
}
- 结账完成后,你把商品装进购物袋,然后离开超市。这就像是关闭了数据库连接和清理了资源。
1.7 恢复自动提交模式
事务完成后,通常需要将连接恢复到自动提交模式,以便后续操作不会无意中成为事务的一部分:
connection.setAutoCommit(true);
- 你离开超市后,准备下一次购物,这时你又可以随意地拿商品,不需要每次都去结账。这就像是恢复了自动提交模式。
2. 拓展知识:事务的隔离级别
在JDBC中,我们还可以设置事务的隔离级别,以控制事务间的可见性。隔离级别可以通过setTransactionIsolation
方法设置:
connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
常见的隔离级别包括:
READ_UNCOMMITTED
:最低隔离级别,可能导致脏读、不可重复读和幻读。READ_COMMITTED
:避免脏读,但可能遇到不可重复读和幻读。REPEATABLE_READ
:避免脏读和不可重复读,但可能遇到幻读。SERIALIZABLE
:最高隔离级别,避免脏读、不可重复读和幻读,但可能导致性能下降。
3. 拓展知识:分布式事务管理
在微服务架构中,可能需要跨多个服务进行事务管理,这时可以使用分布式事务管理工具,如Spring Cloud的Spring Cloud Sleuth
和Spring Cloud Zipkin
,或者使用两阶段提交(2PC)等协议。
4. 结论
JDBC原生事务管理为我们提供了一种直接控制数据库事务的方式,但需要开发者手动管理事务的边界和异常处理。虽然这种方式增加了代码的复杂性,但它为理解事务管理提供了基础。在实际开发中,更高级的事务管理机制(如JTA或Spring的声明式事务管理)通常更为受欢迎,因为它们可以减少样板代码并提供更灵活的事务控制。