不使用Spring事务的管理---原生JDBC实现事务管理
- [1. 表结构DDL](#1. 表结构DDL)
- [2. Maven依赖配置(pom.xml)](#2. Maven依赖配置(pom.xml))
- [3. 完整Java代码](#3. 完整Java代码)
项目框架经历了 SSH(Struts + Spring + Hibernate)、SSM(Spring + Spring MVC + mybatis),再到现在的 分布式架构:Spring Boot + Spring Cloud + Sharding-JDBC + Redis + MQ + ElasticSearch(ES搜索引擎)。Spring用的多了,都忘了在没有 Spring框架 的时候是怎么使用事务的了。
下面就来看看 使用原生JDBC实现事务管理 的Java代码示例。
1. 表结构DDL
sql
-- 1. 客户信息表
CREATE TABLE customer_info
(
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
cus_id VARCHAR(30) NOT NULL COMMENT '客户编号(业务唯一标识)',
nick_name VARCHAR(20) NOT NULL COMMENT '昵称',
phone_num VARCHAR(15) NOT NULL COMMENT '手机号',
UNIQUE KEY uk_ci (cus_id), -- 唯一索引
UNIQUE KEY uk_pn (phone_num) -- 唯一索引
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='客户信息表';
-- 2. 账户信息表
CREATE TABLE account_info
(
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
acc_id VARCHAR(30) NOT NULL COMMENT '账户编号(业务唯一标识)',
cus_id VARCHAR(30) NOT NULL COMMENT '客户编号(关联customer_info.cus_id)',
acc_level VARCHAR(2) NOT NULL DEFAULT 'NORMAL' COMMENT '账户等级,0-普通,1-VIP,2-SVIP',
UNIQUE KEY uk_ai (acc_id), -- 唯一索引
UNIQUE KEY uk_ci (cus_id), -- 唯一索引:一个客户只能有一个账户
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='账户信息表';
2. Maven依赖配置(pom.xml)
xml
<dependencies>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>
3. 完整Java代码
java
/**
* 原生JDBC方式实现事务
*/
import cn.hutool.core.date.DateUtil;
import java.sql.*;
import java.util.Date;
public class TransactionDemo {
public static void main(String[] args) {
// 数据库连接配置
String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
String user = "test";
String password = "test";
// 1. 获取数据库连接
try (Connection connection = DriverManager.getConnection(url, user, password);
PreparedStatement customerStmt = connection.prepareStatement(
"INSERT INTO customer_info (cus_id, nick_name, phone_num) VALUES (?, ?, ?)"
);
PreparedStatement accountStmt = connection.prepareStatement(
"INSERT INTO account_info (acc_id, cus_id, acc_level) VALUES (?, ?, ?)"
);) {
// 2. 关闭自动提交,开启事务(关键!)
// Spring事务管理器 DataSourceTransactionManager 也是这么开启事务的。
connection.setAutoCommit(false);
System.out.println("开始事务...");
// 3. 设置 customer_info 参数
String format = "yyyyMMddHHmmssSSS";
String cusId = "CUS" + DateUtil.format(new Date(), format);
customerStmt.setString(1, cusId);
customerStmt.setString(2, "哈哈哈");
customerStmt.setString(3, "86-17589789876");
// 4. 设置 account_info 参数
accountStmt.setString(1, "ACC" + DateUtil.format(new Date(), format));
accountStmt.setString(2, cusId); // 使用相同的cus_id建立关联
accountStmt.setString(3, "2");
// 5. 执行插入操作
int customerRows = customerStmt.executeUpdate();
int accountRows = accountStmt.executeUpdate();
// 检查是否成功插入
if (customerRows > 0 && accountRows > 0) {
// 6.1 提交事务
connection.commit();
System.out.println("事务提交成功!");
} else {
// 6.2 回滚事务
/**
* 在try块中,如果发生异常,try-with-resources 会自动关闭资源,
* 而Connection在关闭资源的时候会去调用 rollback()隐式回滚事务。
*
* 所以,【显示rollback() 和 throw 二选其一即可】。
*/
connection.rollback();
throw new SQLException("插入失败");
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
扩展建议:
java
// 如果需要更复杂的事务控制,可以考虑以下改进:
// 1. 设置事务隔离级别
connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
// 2. 设置事务超时时间(需要驱动支持)
// connection.setNetworkTimeout(executor, milliseconds);