查看“JDBC数据库事务”的源代码
←
JDBC数据库事务
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
用户
您可以查看和复制此页面的源代码。
https://www.bilibili.com/video/BV1eJ411c7rf/?p=34 11:57之前是数据库连接及 PreparedStatement 使用小结 ===数据库事务介绍=== *事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态 *事务处理(事务操作):保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种这行方式。当在一个事务中执行多个操作时,要么所有的事务都'''<big>被提交(commit)</big>''',那么这些修改就永久地保存下来;要么数据库管理系统将放弃所作的所有修改,整个事务'''<big>回滚(rollback)</big>'''到最初状态。 *为确保数据库中数据的'''<big>一致性</big>''',数据的操纵应当是离散的成组的逻辑单元:当它全部完成时,数据的一致性可以保持,而当这个单元中的一部分操作失败,整个事务应全部视为错误,所有从起始点以后的操作应全部回退到开始状态。 ===JDBC事务处理=== *数据一旦提交,就不可回滚。 *数据什么时候意味着提交? **'''<big>当一个连接对象被创建时,默认情况下是自动提交</big>''':每次执行一个 SQL 语句时,如果执行成功,就会向数据库自动提交,而不能回滚。 **'''<big>关闭数据库连接,数据就会自动的提交</big>'''。如果多个操作,每个操作使用的是自己单独的连接,则无法保证事务。即同一个事务的多个操作必须在同一个连接下。 *'''<big>JDBC 程序中为了让多个 SQL 语句作为一个事务执行</big>''': **调用 Connection 对象的 '''<big>setAutoCommit(false)</big>'''; 以取消自动提交事务 **在所有的 SQL 语句都成功执行后,调用 '''<big>commit()</big>'''; 方法提交事务 **在出现异常时,调用 '''<big>rollback();</big>''' 方法回滚事务 **若此时 Connection 没有被关闭,还可能被重复使用,则需要恢复其自动提交状态 setAutoCommit(true)。尤其是在使用数据库连接池技术时,执行 close() 方法前,建议恢复自动提交状态。 https://www.bilibili.com/video/BV1eJ411c7rf/?p=35 === 数据库事务的问题的引入 === ==== 数据库准备 ==== <syntaxhighlight lang="sql"> CREATE TABLE `user_table` ( `user` varchar(20) NOT NULL, `password` varchar(45) DEFAULT NULL, `balance` int(11) DEFAULT NULL, PRIMARY KEY (`user`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; INSERT INTO `user_table` VALUES ('AA','123456',1000),('BB','654321',1000); </syntaxhighlight> ==== 模拟经典的转账业务场景 ==== <syntaxhighlight lang="java"> /** * 针对于数据表 user_table 来说: * AA用户给BB用户转账100 * * update user_table set balance = balance - 100 where user = 'AA'; * update user_table set balance = balance + 100 where user = 'BB'; */ @Test public void testUpdate() { String sql1 = "update user_table set balance = balance - 100 where user = ?"; update(sql1, "AA"); //模拟网络异常 System.out.println(1 / 0); String sql2 = "update user_table set balance = balance + 100 where user = ?"; update(sql2, "BB"); System.out.println("转账成功"); } </syntaxhighlight>扣钱的操作执行成功,加钱的操作未执行。 https://www.bilibili.com/video/BV1eJ411c7rf?p=36 === 事务及数据库事务的处理原则 === <syntaxhighlight lang="java"> /** * 1.什么叫数据库事务? * 事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态。 * > 一组逻辑操作单元:一个或多个 DML 操作。 * * 2.事务处理的原则:保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。 * 当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存下来; * 要么数据库管理系统将放弃所作的修改,整个事务回滚(rollback)到最初状态。 * * 3.数据一旦提交,就不可回滚 * * 4.哪些操作会导致数据的自动提交? * > DDL 操作一旦执行,都会自动提交。 * > set autocommit = false 的方式对 DDL 操作无效。 * > DML 操作在默认情况下,一旦执行,也会自动提交。 * > 可以通过 set autocommit = false 的方式取消 DML 操作默认的自动提交。 * > 默认在关闭连接时,会自动地提交事务。 */ </syntaxhighlight> https://www.bilibili.com/video/BV1eJ411c7rf?p=37 === 考虑事务之后的代码实现 === <syntaxhighlight lang="java"> //*********************考虑数据库事务后的转账操作********************* @Test public void testUpdateWithTx() { Connection con = null; try { con = JDBCUtils.getConnection(); System.out.println(con.getAutoCommit()); //取消数据的自动提交 con.setAutoCommit(false); String sql1 = "update user_table set balance = balance - 100 where user = ?"; update(con, sql1, "AA"); //模拟网络异常 System.out.println(1 / 0); String sql2 = "update user_table set balance = balance + 100 where user = ?"; update(con, sql2, "BB"); //提交数据 con.commit(); System.out.println("转账成功"); } catch (Exception e) { e.printStackTrace(); //回滚数据 try { con.rollback(); } catch (SQLException ex) { e.printStackTrace(); } } finally { /* * 修改其为自动提交数据 * 主要针对使用数据库连接池的使用 */ try { con.setAutoCommit(true); } catch (SQLException e) { e.printStackTrace(); } JDBCUtils.closeResource(con, null); } } //通用的增删改查操作---version 2.0(考虑上事务) public int update(Connection conn, String sql, Object ...args) {//sql 中占位符的个数与可变形参的长度相同 PreparedStatement ps = null; try { //1.预编译sql语句,返回PreparedStatement的实例 ps = conn.prepareStatement(sql); //2.填充占位符 for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } //4.执行 return ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.closeResource(null, ps); } return 0; } </syntaxhighlight> https://github.com/jihch/jdbc_2/blob/main/src/main/java/io/github/jihch/transaction/TransactionTest.java https://www.bilibili.com/video/BV1eJ411c7rf?p=38 若此时 Connection 没有被关闭,还可能被重复使用,则需要恢复其自动提交状态 setAutoCommit(true)。尤其是在使用数据库连接池技术时,执行 close() 方法前,建议恢复自动提交状态。<syntaxhighlight lang="java"> } finally { /* * 修改其为自动提交数据 * 主要针对使用数据库连接池的使用 */ try { con.setAutoCommit(true); } catch (SQLException e) { e.printStackTrace(); } JDBCUtils.closeResource(con, null); } </syntaxhighlight>
返回至
JDBC数据库事务
。
导航菜单
个人工具
登录
名字空间
页面
讨论
变种
视图
阅读
查看源代码
查看历史
更多
搜索
导航
首页
Spring Boot 2 零基础入门
Spring Cloud
Spring Boot
设计模式之禅
VUE
Vuex
Maven
算法
技能树
Wireshark
IntelliJ IDEA
ElasticSearch
VirtualBox
软考
正则表达式
程序员精讲
软件设计师精讲
初级程序员 历年真题
C
SQL
Java
FFmpeg
Redis
Kafka
MySQL
Spring
Docker
JMeter
Apache
Linux
Windows
Git
ZooKeeper
设计模式
Python
MyBatis
软件
数学
PHP
IntelliJ IDEA
CS基础知识
网络
项目
未分类
MediaWiki
镜像
问题
健身
国债
英语
烹饪
常见术语
MediaWiki帮助
工具
链入页面
相关更改
特殊页面
页面信息