数据库事务及代码实现
package com.shan.transaction;
import com.mysql.fabric.ShardTable;
import com.shan.util.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.SQLOutput;
/**
* 1.什么叫数据库事物
* 事物:一组逻辑操作单元,使数据从一种状态转换到另一种状态。
* -->一组逻辑操作单元:一个或多个DML操作
* 2.事物处理
* 事务处理是将多个操作或者命令一起执行,所有命令全部成功执行才意味着该事务的成功,任何一个命令失败都意味着该事务的失败。
* 3.以银行转账为例(100块都不给),
* A要给B 转账100元,
* A转账的指令已经成功发出,而B 由于未知的原因接收失败,
* 如果两个命令单独执行,那么A账户少了100块,但是B又没收到100块,显而易见是不合理的;
* 如果将A向B 转账100元当成一个事务处理,那么由于B 接收的失败,整个转账事务都将失败,A不会少100,B更不会增加100,这个时候“100块都不给”才是合理的情况。
* 4.数据一旦提交,就不可回滚
* a. DDL操作一旦执行,都会自动提交
* b. AML默认情况下,一旦执行,就会自动提交
* -->可以设置set automint = false 取消DML操作的自动提交
* c. 默认在关闭连接时,会自动提交数据
* @author shan
* @date 2021/5/17
*/
public class transactionTest {
/**
* 针对与数据表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'
*
*/
public static void main(String[] args) {
模拟转账异常
//
// 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("转账成功");
Connection conn = null;
try {
conn = JDBCUtils.getConnection();
System.out.println("默认:" + conn.getAutoCommit());
//取消数据的自动提交功能
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("转账成功");
//提交数据
conn.commit();
} catch (Exception e) {
e.printStackTrace();
//回滚数据
try {
conn.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}finally {
JDBCUtils.closeResource(conn,null);
}
}
//************************考虑数据库事物处理后的转账操作************************
//考虑事物处理后的操作
public static int update1(Connection conn, String sql, Object... args) {//sql中占位符的个数应该与可变形参的长度一致
PreparedStatement ps = null;
try {
//1.预编译sql语句,返回PrepareStatement的实例
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 {
//5.资源的关闭
JDBCUtils.closeResource(null, ps);
}
return 0;
}
//通用的增删改操作 未考虑事物处理的操作
public static int update(String sql, Object... args) {//sql中占位符的个数应该与可变形参的长度一致
Connection conn = null;
PreparedStatement ps = null;
try {
//1.获取数据库的连接
conn = JDBCUtils.getConnection();
//2.预编译sql语句,返回PrepareStatement的实例
ps = conn.prepareStatement(sql);
//3.填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
//4.执行
return ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
//修改
try {
conn.setAutoCommit(true);
}catch (SQLException e) {
e.printStackTrace();
}
//5.资源的关闭
JDBCUtils.closeResource(conn, ps);
}
return 0;
}
}