Transaction-JDBC管理
JDBC默认是自动事务:
执行sql语句:executeUpdate() ---- 每执行一次executeUpdate方法 代表 事务自动提交
所以需要通过jdbc的API手动事务:
开启事务:conn.setAutoCommit(false);
提交事务:conn.commit();
回滚事务:conn.rollback();
注意:控制事务的connnection必须是同一个
执行sql的connection与开启事务的connnection必须是同一个才能对事务进行控制。
Transaction示例:
import java.sql.*;
public class Jdbc {
public static final String URL = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
public static final String USER = "root";
public static final String PASSWORD = "123456";
public static void main(String[] args) throws Exception {
//1.加载驱动程序
Class.forName("com.mysql.cj.jdbc.Driver");
//2. 获得数据库连接
Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
//3.操作数据库,实现增删改查
String sql = "insert into class (id, teacher_id) values (?,?)";
PreparedStatement preparedStatement = conn.prepareStatement(sql);
try {
//设置事务自动提交为手动提交
conn.setAutoCommit(false);
for (int i = 20; i < 30; i++) {
preparedStatement.setObject(1, i);
preparedStatement.setObject(2, i);
preparedStatement.addBatch();
}
int [] success = preparedStatement.executeBatch();
System.out.println(success.length);
//手动制造异常
int m = 10 / 0;
for (int i = 30; i < 40; i++) {
preparedStatement.setObject(1, i);
preparedStatement.setObject(2, i);
preparedStatement.addBatch();
}
int [] success2 = preparedStatement.executeBatch();
System.out.println(success2.length);
//提交事务
conn.commit();
} catch (Exception e) {
e.printStackTrace();
try {
conn.rollback();
System.out.println("JDBC Transaction rolled back successfully");
} catch (SQLException e1) {
System.out.println("SQLException in rollback" + e1.getMessage());
e1.printStackTrace();
}
} finally {
//执行完数据库操作后记得关闭数据库连接资源
try {
preparedStatement.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
异常信息:
JDBC Savepoint
有时候一个事务可能是一组复杂的语句,因此可能想要回滚到事务中某个特殊的点。JDBC Savepoint帮我们在事务中创建检查点(checkpoint),这样就可以回滚到指定点。当事务提交或者整个事务回滚后,为事务产生的任何保存点都会自动释放并变为无效。把事务回滚到一个保存点,会使其他所有保存点自动释放并变为无效。
步骤:
1.在事务中创建检查点
2.异常中捕捉检查点并回滚到检查点
Savepoint示例:
import cn.hutool.core.util.StrUtil;
import java.sql.*;
public class Jdbc {
public static final String URL = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
public static final String USER = "root";
public static final String PASSWORD = "123456";
public static void main(String[] args) throws Exception {
//1.加载驱动程序
Class.forName("com.mysql.cj.jdbc.Driver");
//2. 获得数据库连接
Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
//3.操作数据库,实现增删改查
String classSql = "insert into class (id, teacher_id) values (?,?)";
String userSql = "insert into users (name, age) values (?,?)";
Savepoint savepoint = null;
try {
//设置事务自动提交为手动提交
conn.setAutoCommit(false);
PreparedStatement preparedStatement1 = conn.prepareStatement(classSql);
for (int i = 20; i < 30; i++) {
preparedStatement1.setObject(1, i);
preparedStatement1.setObject(2, i);
preparedStatement1.addBatch();
}
int [] success = preparedStatement1.executeBatch();
System.out.println(success.length);
//设置回滚的点 失败只会回滚users信息
savepoint = conn.setSavepoint("检查点");
//手动制造异常
int m = 10 / 0;
PreparedStatement preparedStatement2 = conn.prepareStatement(userSql);
preparedStatement2.setObject(1, "腕豪");
preparedStatement2.setObject(2, "24");
preparedStatement2.executeUpdate();
//提交事务
conn.commit();
} catch (Exception e) {
e.printStackTrace();
if (StrUtil.isEmptyIfStr(savepoint)) {
//回滚所有更新sql
conn.rollback();
System.out.println("JDBC Transaction rolled back successfully");
} else {
//回滚到指定位置
conn.rollback(savepoint);
System.out.println("JDBC Transaction rolled back successfully");
conn.commit();
}
} finally {
//执行完数据库操作后记得关闭数据库连接资源
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}