一灰灰blog 一灰灰blog
首页
  • InfluxDB
  • MongoDB
  • MySql
  • 基础系列
  • DB系列
  • 搜索系列
  • MQ系列
  • WEB系列
  • 中间件
  • 运维
  • SpringSecurity
  • SpringCloud
  • QuickAlarm
  • QuickCrawer
  • QuickFix
  • QuickMedia
  • QuickSpi
  • QuickTask
  • 高可用
  • 分类
  • 标签
  • 归档
  • 收藏
  • 关于
GitHub (opens new window)

一灰灰blog

资深搬运工
首页
  • InfluxDB
  • MongoDB
  • MySql
  • 基础系列
  • DB系列
  • 搜索系列
  • MQ系列
  • WEB系列
  • 中间件
  • 运维
  • SpringSecurity
  • SpringCloud
  • QuickAlarm
  • QuickCrawer
  • QuickFix
  • QuickMedia
  • QuickSpi
  • QuickTask
  • 高可用
  • 分类
  • 标签
  • 归档
  • 收藏
  • 关于
GitHub (opens new window)
  • 基础系列

  • DB系列

    • H2Database

    • JPA

    • JdbcTemplate

    • Jooq

      • 【DB系列】Jooq初体验
      • 【DB系列】Jooq代码自动生成
      • 【DB系列】Jooq之新增记录使用姿势
      • 【DB系列】Jooq之记录更新与删除
      • 【DB系列】Jooq批量写入采坑记录
      • 【DB系列】Jooq之记录查询基础篇
      • 【DB系列】Jooq之聚合查询
      • 【DB系列】Jooq之常用函数使用姿势
      • 【DB系列】Jooq之多表联合查询
      • 【DB系列】Jooq之事务
        • I. 项目搭建
          • 1. 项目依赖
          • 2. 数据准备
        • II. 使用姿势
          • 0. 前期准备
          • 1. @Transactional 注解用法
          • 2. jooq声明式事务
          • 3. 测试
        • II. 其他
          • 0. 项目
          • 1. 一灰灰Blog
    • Mybatis

    • 事务

    • MongoDB

    • Redis

    • 实例

  • 搜索系列

  • MQ系列

  • WEB系列

  • 中间件

  • 运维

  • SpringSecurity

  • SpringCloud

  • Spring系列
  • DB系列
  • Jooq
一灰灰
2020-12-13

【DB系列】Jooq之事务

在SpringBoot中使用事务比较简单,大部分场景下,直接借助@Transactional注解即可,本文将介绍一下Jooq中使用事务的两种方式

# I. 项目搭建

本项目借助SpringBoot 2.2.1.RELEASE + maven 3.5.3 + IDEA进行开发

# 1. 项目依赖

关于如何创建一个SpringBoot的项目工程,不再本文的描述范围内,如有兴趣可以到文末的个人站点获取

在这个示例工程中,我们的选用h2dabase作为数据库(方便有兴趣的小伙伴直接获取工程源码之后,直接测试体验),因此对应的pom核心依赖如下

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jooq</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
    </dependency>
</dependencies>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 2. 数据准备

本文对应的项目工程,和前面介绍增加删除的一致,所以这里直接使用之前新增的数据

# II. 使用姿势

# 0. 前期准备

@Repository
public class PoetryTransactionRepository {
    private static final PoetTB poetTable = PoetTB.POET;
    private static final PoetryTB poetryTable = PoetryTB.POETRY;

    @Autowired
    private DSLContext dsl;
}
1
2
3
4
5
6
7
8

# 1. @Transactional 注解用法

直接借助Spring的@Transactional注解来实现事务相关业务逻辑,在实际的时候需要注意一下,使用姿势不当,可能导致事务不生效,对此有疑问的小伙伴,可以查看博文【SpringBoot DB系列】事务不生效的几种case (opens new window)

@Transactional(rollbackFor = Exception.class)
public void transaction() {
    PoetryPO poetryPO = dsl.newRecord(poetryTable);
    poetryPO.setId(10);
    poetryPO.setPoetId(1);
    poetryPO.setTitle("事务插入的标题");
    poetryPO.setContent("事务插入的内容");
    poetryPO.setCreateAt(new Timestamp(System.currentTimeMillis()));
    boolean ans = poetryPO.insert() > 0;
    System.out.println(ans);

    // 这个会插入失败,长度超限
    PoetPO record = dsl.newRecord(poetTable);
    record.setId(20);
    record.setName("123456789100918237645412738123");
    boolean ans2 = record.insert() > 0;
    System.out.println(ans2);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 2. jooq声明式事务

一般使用Spring的@Transactional注解时,需要注意不能是同类的内部方法调用,因为这样不会走代理,导致事务不生效;

如果确实存在事务的业务需求,但是又不想拆分到另外一个对象类,那么可以考虑一下声明式事务的用法,如下

public void trans2() {
    boolean ans = dsl.transactionResult(new TransactionalCallable<Boolean>() {
        @Override
        public Boolean run(Configuration configuration) throws Throwable {
            final DSLContext inner = DSL.using(configuration);

            PoetryPO poetryPO = inner.newRecord(poetryTable);
            poetryPO.setId(11);
            poetryPO.setPoetId(1);
            poetryPO.setTitle("事务插入的标题2");
            poetryPO.setContent("事务插入的内容2");
            poetryPO.setCreateAt(new Timestamp(System.currentTimeMillis()));
            boolean ans = poetryPO.insert() > 0;
            System.out.println(ans);

            // 这个会插入失败,长度超限
            PoetPO record = inner.newRecord(poetTable);
            record.setId(20);
            record.setName("123456789100918237645412738123");
            boolean ans2 = record.insert() > 0;
            System.out.println(ans2);

            return null;
        }
    });
    System.out.println(ans);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 3. 测试

@RestController
public class TestRest {
    @Autowired
    private PoetryTransactionRepository poetryTransactionRepository;

    @GetMapping(path = "trans")
    public String transaction() {
        try {
            poetryTransactionRepository.transaction();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    
        try {
            poetryTransactionRepository.trans2();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    
        return "over";
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

实际输出如下

true
jOOQ; SQL [insert into "PUBLIC"."POET" ("ID", "NAME") values (cast(? as int), cast(? as varchar))]; Value too long for column "NAME VARCHAR(20)": "'123456789100918237645412738123' (30)"; SQL statement:
insert into "PUBLIC"."POET" ("ID", "NAME") values (cast(? as int), cast(? as varchar)) [22001-200]; nested exception is org.h2.jdbc.JdbcSQLDataException: Value too long for column "NAME VARCHAR(20)": "'123456789100918237645412738123' (30)"; SQL statement:
insert into "PUBLIC"."POET" ("ID", "NAME") values (cast(? as int), cast(? as varchar)) [22001-200]
true
jOOQ; SQL [insert into "PUBLIC"."POET" ("ID", "NAME") values (cast(? as int), cast(? as varchar))]; Value too long for column "NAME VARCHAR(20)": "'123456789100918237645412738123' (30)"; SQL statement:
insert into "PUBLIC"."POET" ("ID", "NAME") values (cast(? as int), cast(? as varchar)) [22001-200]; nested exception is org.h2.jdbc.JdbcSQLDataException: Value too long for column "NAME VARCHAR(20)": "'123456789100918237645412738123' (30)"; SQL statement:
insert into "PUBLIC"."POET" ("ID", "NAME") values (cast(? as int), cast(? as varchar)) [22001-200]
1
2
3
4
5
6
7
8

# II. 其他

# 0. 项目

系列博文

  • 【SpringBoot DB系列】Jooq之多表联合查询 (opens new window)
  • 【SpringBoot DB系列】Jooq之常用函数使用姿势 (opens new window)
  • 【SpringBoot DB系列】Jooq之聚合查询 (opens new window)
  • 【SpringBoot DB系列】Jooq之记录查询基础篇 (opens new window)
  • 【SpringBoot DB系列】Jooq批量写入采坑记录 (opens new window)
  • 【SpringBoot DB系列】Jooq之记录更新与删除 (opens new window)
  • 【SpringBoot DB系列】Jooq之新增记录使用姿势 (opens new window)
  • 【SpringBoot DB系列】Jooq代码自动生成 (opens new window)
  • 【SpringBoot DB系列】Jooq初体验 (opens new window)

项目源码

  • 工程:https://github.com/liuyueyi/spring-boot-demo (opens new window)
  • 项目源码: https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-boot/108-jooq-curd (opens new window)

# 1. 一灰灰Blog

尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

下面一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

  • 一灰灰Blog个人博客 https://blog.hhui.top (opens new window)
  • 一灰灰Blog-Spring专题博客 http://spring.hhui.top (opens new window)

一灰灰blog

编辑 (opens new window)
#Jooq
上次更新: 2021/10/15, 19:56:22
【DB系列】Jooq之多表联合查询
【DB系列】Mybatis+xml整合篇

← 【DB系列】Jooq之多表联合查询 【DB系列】Mybatis+xml整合篇→

最近更新
01
【基础系列】基于maven多环境配置
04-25
02
【WEB系列】内嵌Tomcat配置Accesslog日志文件生成位置源码探索
04-24
03
【搜索系列】ES查询常用实例演示
04-18
更多文章>
Theme by Vdoing | Copyright © 2017-2022 一灰灰Blog
MIT License | 鄂ICP备18017282号 |
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×