不使用Spring事务的管理—原生JDBC实现事务管理

不使用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);
相关推荐
岁岁种桃花儿1 小时前
MySQL从入门到精通系列:InnoDB记录存储结构
数据库·mysql
毕设源码-朱学姐1 小时前
【开题答辩全过程】以 基于JavaWeb的网上家具商城设计与实现为例,包含答辩的问题和答案
java
jiunian_cn2 小时前
【Redis】hash数据类型相关指令
数据库·redis·哈希算法
冉冰学姐2 小时前
SSM在线影评网站平台82ap4(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·ssm框架·在线影评平台·影片分类
C雨后彩虹2 小时前
CAS与其他并发方案的对比及面试常见问题
java·面试·cas·同步·异步·
sww_10263 小时前
RAG检索增强 ETL最佳实战
人工智能·python·spring
知识分享小能手3 小时前
SQL Server 2019入门学习教程,从入门到精通,SQL Server 2019数据库的操作(2)
数据库·学习·sqlserver
java1234_小锋4 小时前
Java高频面试题:SpringBoot为什么要禁止循环依赖?
java·开发语言·面试
2501_944525544 小时前
Flutter for OpenHarmony 个人理财管理App实战 - 账户详情页面
android·java·开发语言·前端·javascript·flutter
计算机学姐4 小时前
基于SpringBoot的电影点评交流平台【协同过滤推荐算法+数据可视化统计】
java·vue.js·spring boot·spring·信息可视化·echarts·推荐算法