个人建站程序/优化大师官方
数据库事务
什么叫数据库事务
- 事务:一组逻辑操作单元,使数据从一种状态到另外一种状态,一组逻辑操作单元,一个或者多个DML操作
事务处理的原则:
- 保证所有事务都为一个工作单元执行 即使出现了故障,都不能改变这种方式当一个事务中执行了多个操作时,要么所有的事务都被提交(commit) , 那么这些修改就永久保存下来: 要么数据库管理系统将放弃所作的所有修改,整个事务回滚(roolBack) 到最初始状态
JDBC事务处理
- 数据一旦提交 就不会发生回滚
那些操作会导致数据的自动提交?
DDL数据定义语言,用于定义和管理 SQL 数据库中的所有对象的语言
- DDL操作一旦执行,就会自动提交 set autocommit = false 对DDL操作失效
DML数据操作语言,SQL中处理数据等操作统称为数据操纵语言
- DML默认情况下,一旦执行,就会自动提交
我们通过set autocommit= false 的方式 取消DML操作的自动提交
- 默认在关闭连接时,会自动的提交数据
JDBC程序中为了让多个 SQL 语句作为一个事务执行
- 调用Connection对象的setAutoCommit(flase): 以取消自动提交事务
- 在所有的sql语句都成功执行后,调用commit(); 方法提交事务
- 出现异常时.调用rollback(); 进行回滚事务
若此时connection没有被关闭,还可能被被重复使用,则需要恢复其自动提交的状态
setAutoCommit(true) 尤其时使用数据库连接池技术时,执行close()方法前,建议恢复自动提交状态
案例
用户AA向用户BB转账100
未考虑数据库事务情况下的转账操作:
@Testpublic void testUpdate() {String sql1 = "update user_table set balance = balance - 100 where user = ?";update(sql1, "AA");//模拟网络异常
// System.out.println(10 / 0);String sql2 = "update user_table set balance = balance + 100 where user = ?";update(sql2, "BB");System.out.println("转账成功");}// 通用的增删改操作---version 1.0public int update(String sql, Object... args) {Connection conn = null;PreparedStatement ps = null;try {//1, 获取数据库连接conn = JDBCUtils.getConnection();//2 预编译sql语句 返回PreparedStatement的实例ps = conn.prepareStatement(sql);//填充占位符for (int i = 0; i < args.length; i++) {ps.setObject(i + 1, args[i]);}//执行return ps.executeUpdate();} catch (Exception e) {e.printStackTrace();} finally {//修改其为自动提交数据//主要针对于使用数据库连接池的使用try {conn.setAutoCommit(true);} catch (SQLException throwables) {throwables.printStackTrace();}//关闭资源JDBCUtils.closeResource(conn, ps);}return 0;}
出现问题:当模拟网络异常时,AA的钱扣除了,但是没有加到B中
解决问题:考虑数据库事务后进行转账操作
*1.什么叫数据库事务* 事务:一组逻辑操作单元,使数据从一种状态到另外一种状态* > 一组逻辑操作单元,一个或者多个DML操作*2. 事务处理的原则:保证所有事务都为一个工作单元执行 即使出现了故障,都不能改变这种方式* 当一个事务中执行了多个操作时,要么所有的事务都被提交(commit) 那么这些修改就永久保存下来* : 要么数据库管理系统将放弃所作的所有修改,整个事务回滚(roolBack) 到最初始状态
考虑数据库事务后的转账操作
注意:
为了数据报错正常产生回滚
update1(Connection conn, String sql, Object... args)
连接数据库由外部测试提供,也即是关闭连接是JDBCUtils.closeResource(null, ps);
- .取消自动提
conn.setAutoCommit(false)
; - 所有的 SQL 语句都成功执行后,调用
commit();
方法提交事务 - 出现异常 调用
rollback();
方法回滚事务
@Testpublic void testUpdateWithTx() {Connection conn = null;try {conn = JDBCUtils.getConnection();//1.取消自动提交conn.setAutoCommit(false);String sql1 = "update user_table set balance = balance - 100 where user = ?";update1(conn, sql1, "AA");//模拟网路异常
// System.out.println(10 / 0);String sql2 = "update user_table set balance = balance + 100 where user = ?";update1(conn, sql2, "BB");System.out.println("转账成功");//2 提交数据conn.commit();} catch (Exception e) {e.printStackTrace();//3 数据回滚try {conn.rollback();} catch (SQLException throwables) {throwables.printStackTrace();}} finally {JDBCUtils.closeResource(conn, null);}}// 通用的增删改操作---version 2.0public int update1(Connection conn, String sql, Object... args) {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]);}//3 执行return ps.executeUpdate();} catch (Exception e) {e.printStackTrace();} finally {//4 关闭资源JDBCUtils.closeResource(null, ps);}return 0;}
连接数据库相关操作
操作数据库的工具类
package com.nie1.transaction.util;import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;/*** @Description 操作数据库的工具类*/
public class JDBCUtils {/*** @return* @throws Exception* @Description 获取数据库的连接*/public static Connection getConnection() throws Exception {// 1.读取配置文件中的4个基本信息InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");Properties pros = new Properties();pros.load(is);//2获取四个配置String user = pros.getProperty("user");String password = pros.getProperty("password");String url = pros.getProperty("url");String driverClass = pros.getProperty("driverClass");// 3.加载驱动Class.forName(driverClass);// 4.获取连接Connection conn = DriverManager.getConnection(url, user, password);return conn;}/*** @Description 关闭连接和Statement的操作*/public static void closeResource(Connection conn, Statement ps) {try {if (ps != null)ps.close();} catch (SQLException e) {e.printStackTrace();}try {if (conn != null)conn.close();} catch (SQLException e) {e.printStackTrace();}}/*** @Description 关闭资源操作*/public static void closeResource(Connection conn, Statement ps, ResultSet rs) {try {if (ps != null)ps.close();} catch (SQLException e) {e.printStackTrace();}try {if (conn != null)conn.close();} catch (SQLException e) {e.printStackTrace();}try {if (rs != null)rs.close();} catch (SQLException e) {e.printStackTrace();}}
}
配置文件jdbc.properties
#获取
user=root
password=123123
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
driverClass=com.mysql.jdbc.Driver