JDBC_05事务相关
JDBC_05事务相关
1.演示jdbc事务自动提交机制
1.1建表并插入数据
drop table if exists t_vip;
create table t_vip(
id int primary key auto_increment,
name varchar(255)
);
insert into t_vip(name) values('zhangsan');
insert into t_vip(name) values('lisi');
commit;
查看数据:
1.2编写程序同时修改两条记录
在两条sql语句之间加一个空指针异常,使程序执行第一条sql语句后,终止运行。
package com.tsccg.jdbc.transaction;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* @Author: TSCCG
* @Date: 2021/07/28 19:19
* 演示jdbc的事务自动提交机制
*/
public class TransactionDemo01 {
//程序执行入口
public static void main(String[] args) {
boolean result = change();
System.out.println(result ? "操作成功" : "操作失败");
}
/**
* 修改t_vip表的数据
* @return 返回执行结果
*/
private static boolean change() {
boolean isSuccess = false;
Connection conn = null;
PreparedStatement ps = null;
try {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://localhost:3306/tsccg";
String user = "root";
String password = "123456";
conn = DriverManager.getConnection(url,user,password);
//3.获取预编译数据库操作对象
String sql = "update t_vip set name = ? where id = ?";
ps = conn.prepareStatement(sql);
//第一次给占位符赋值
ps.setString(1,"张三");
ps.setInt(2,1);
//4.1执行sql语句
int count = ps.executeUpdate();
//设置一个空指针异常
String str = null;
str.toString();
//第二次给占位符赋值
ps.setString(1,"李四");
ps.setInt(2,2);
//4.2执行sql语句
count += ps.executeUpdate();
//如果两次执行sql语句都成功了,那么count的值就会是2
if (count == 2) {
isSuccess = true;
}
} catch (SQLException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
//6.释放资源
if (ps != null) {
try {
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
return isSuccess;
}
}
1.3查看运行结果
Exception in thread "main" java.lang.NullPointerException
at com.tsccg.jdbc.transaction.TransactionDemo01.change(TransactionDemo01.java:53)
at com.tsccg.jdbc.transaction.TransactionDemo01.main(TransactionDemo01.java:23)
由图知,在执行过第一条sql语句后,就立即将其提交了。
从该案例中,可见jdbc会自动提交事务。
在开发中,会有很多操作要求同时成功或同时失败,这样的自动提交机制是不可行的。
比如说银行转账操作。A账户中有20000元,B账户中有0元。
A向B转账10000元,这就设计到两个修改操作:
- A账户减去10000元,
- B账户增加10000元。
如果使用自动提交机制,在A账户中减去金额后就会自动提交一次事务,无论之后的程序如何运行。
假设在转账过程中遇到了如上面程序中的异常,就会导致在A账户减去金额后,B账户没有增加金额。
所以为了数据安全,要把两步修改操作放进一个事务中,要成功一起成功,要失败一起失败。
2.设置事务手动提交和关闭
重点有三条代码:
//conn数据库连接对象
conn.setAutoCommit(false);//关闭自动提交
conn.commit();//手动提交
conn.rollback();//回滚。
2.1修改上面的程序
现用这三条代码修改上面的程序
package com.tsccg.jdbc.transaction;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* @Author: TSCCG
* @Date: 2021/07/28 22:24
*/
public class TransactionDemo02 {
public static void main(String[] args) {
boolean result = change();
System.out.println(result ? "操作成功" : "操作失败");
}
/**
* 修改t_vip表的数据
* @return 返回执行结果
*/
private static boolean change() {
boolean isSuccess = false;
Connection conn = null;
PreparedStatement ps = null;
try {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://localhost:3306/tsccg";
String user = "root";
String password = "123456";
conn = DriverManager.getConnection(url,user,password);
//关闭自动提交
conn.setAutoCommit(false);
//3.获取预编译数据库操作对象
String sql = "update t_vip set name = ? where id = ?";
ps = conn.prepareStatement(sql);
//第一次给占位符赋值
ps.setString(1,"张三");
ps.setInt(2,1);
//4.1执行sql语句
int count = ps.executeUpdate();
//设置一个空指针异常
String str = null;
str.toString();
//第二次给占位符赋值
ps.setString(1,"李四");
ps.setInt(2,2);
//4.2执行sql语句
count += ps.executeUpdate();
//如果两次执行sql语句都成功了,那么count的值就会是2
if (count == 2) {
isSuccess = true;
}
//手动提交事务
conn.commit();
} catch (SQLException | ClassNotFoundException e) {
//回滚事务
if(conn != null) {
try {
conn.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
e.printStackTrace();
} finally {
//6.释放资源
if (ps != null) {
try {
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
return isSuccess;
}
}
重新初始化表中数据:
2.2重新运行程序
Exception in thread "main" java.lang.NullPointerException
at com.tsccg.jdbc.transaction.TransactionDemo02.change(TransactionDemo02.java:48)
at com.tsccg.jdbc.transaction.TransactionDemo02.main(TransactionDemo02.java:14)
可见,即使已经执行了第一条sql语句,当程序遇到异常后,也会将执行的语句进行回滚,表中数据并未受影响。
去除空指针异常再次运行:
操作成功
两条语句同时执行成功。