使用配置类方式整合 jOOQ
在本教程中,我们将演示如何在 tio-boot 项目中,以纯 Java 配置类的方式整合 jOOQ,实现:
- 不使用 XML
- 不使用代码生成插件(可选)
- 使用
DSLContext进行类型安全 SQL - 通过 AOP 自动注入 jOOQ 核心对象
- 与 tio-boot 生命周期完美整合
通过本文,不仅能学会 怎么做,还能理解 为什么这样做更合理。
一、为什么选择 jOOQ
在进入实战之前,先明确一点: jOOQ 并不是 ORM,而是“类型安全的 SQL 构建器”。
jOOQ 的核心优势
SQL 即一等公民
- 不隐藏 SQL
- 不强行抽象关系模型
类型安全
- 编译期校验字段、表名
- 避免字符串 SQL 带来的运行期错误
极强的可控性
- 复杂 SQL、子查询、窗口函数非常友好
- 非常适合中大型系统
非常适合与 tio-boot 这种轻量框架结合
- 无侵入
- 全代码配置
- 启动速度快
二、添加依赖
在 pom.xml 中加入以下依赖:
<properties>
<!-- 项目属性 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>21</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<!-- 版本属性 -->
<lombok-version>1.18.30</lombok-version>
<fastjson2.version>2.0.52</fastjson2.version>
<hotswap-classloader.version>1.2.6</hotswap-classloader.version>
<tio-boot.version>2.0.6</tio-boot.version>
<jfinal-aop.version>1.3.8</jfinal-aop.version>
<!-- 应用程序属性 -->
<final.name>web-hello</final.name>
<main.class>com.litongjava.test.HelloApp</main.class>
</properties>
<dependencies>
<!-- 日志框架 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.3.3</version>
</dependency>
<!-- Tio Boot 框架 -->
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>tio-boot</artifactId>
<version>${tio-boot.version}</version>
</dependency>
<!-- 热加载类加载器 -->
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>hotswap-classloader</artifactId>
<version>${hotswap-classloader.version}</version>
</dependency>
<!-- JFinal AOP -->
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>jfinal-aop</artifactId>
<version>${jfinal-aop.version}</version>
</dependency>
<!-- FastJSON2 用于 JSON 解析 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>${fastjson2.version}</version>
</dependency>
<!-- Lombok 用于简化代码 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok-version}</version>
<optional>true</optional>
<scope>provided</scope>
</dependency>
<!-- JUnit 用于测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- jOOQ -->
<dependency>
<groupId>org.jooq</groupId>
<artifactId>jooq</artifactId>
<version>3.18.6</version>
</dependency>
<!-- PostgreSQL 驱动 -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.24</version>
</dependency>
<!-- Druid 数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
</dependencies>
三、启动类
package demo.jooq;
import com.litongjava.annotation.AComponentScan;
import com.litongjava.tio.boot.TioApplication;
@AComponentScan
public class JooqApp {
public static void main(String[] args) {
TioApplication.run(JooqApp.class, args);
}
}
四、数据库表结构
以 system_admin 表为例:
CREATE TABLE system_admin (
id SERIAL PRIMARY KEY,
login_name VARCHAR(64),
password VARCHAR(64)
);
五、模型类(可选)
jOOQ 不强制要求实体类,但在 Web 返回时通常仍然需要 DTO:
package demo.jooq.model;
import lombok.Data;
@Data
public class SystemAdmin {
private Integer id;
private String loginName;
private String password;
}
六、jOOQ 核心配置类
这是整合的核心部分。
1. 配置目标
- 创建数据源
- 创建
DSLContext - 注册到 AOP 容器
- 应用关闭时自动释放资源
2. JooqConfig 配置类
app.properties
jdbc.url=jdbc:postgresql://192.168.3.151/defaultdb
jdbc.user=postgres
jdbc.pswd=1234566
package demo.jooq.config;
import org.jooq.DSLContext;
import org.jooq.SQLDialect;
import org.jooq.impl.DSL;
import com.alibaba.druid.pool.DruidDataSource;
import com.litongjava.annotation.AConfiguration;
import com.litongjava.annotation.Initialization;
import com.litongjava.constants.ServerConfigKeys;
import com.litongjava.hook.HookCan;
import com.litongjava.jfinal.aop.AopManager;
import com.litongjava.tio.utils.environment.EnvUtils;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@AConfiguration
public class JooqConfig {
@Initialization
public void initJooq() {
String jdbcUrl = EnvUtils.get(ServerConfigKeys.JDBC_URL);
String username = EnvUtils.getStr(ServerConfigKeys.JDBC_USER);
String password = EnvUtils.getStr(ServerConfigKeys.JDBC_PSWD);
// 1. 数据源
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(jdbcUrl);
dataSource.setUsername(username);
dataSource.setPassword(password);
// 2. 创建 DSLContext
DSLContext dslContext = DSL.using(dataSource, SQLDialect.POSTGRES);
// 3. 注册到 AOP 容器
AopManager.me().addSingletonObject(DSLContext.class, dslContext);
log.info("jOOQ DSLContext initialized");
// 4. 应用关闭时释放资源
HookCan.me().addDestroyMethod(() -> {
dataSource.close();
log.info("DruidDataSource closed");
});
}
}
七、DAO / Repository 层(使用 jOOQ)
1. SystemAdminDao
package demo.jooq.dao;
import org.jooq.DSLContext;
import org.jooq.impl.DSL;
import com.litongjava.annotation.Inject;
import demo.jooq.model.SystemAdmin;
public class SystemAdminDao {
@Inject
private DSLContext dsl;
public SystemAdmin findByLoginName(String loginName) {
return dsl.select(DSL.field("id"), DSL.field("login_name"), DSL.field("password"))
//
.from(DSL.table("system_admin"))
//
.where(DSL.field("login_name").eq(loginName))
//
.fetchOneInto(SystemAdmin.class);
}
}
2. 为什么这样写
DSLContext是 jOOQ 的核心- SQL 结构清晰,完全可控
fetchOneInto自动映射到 POJO- 不依赖 XML、不依赖注解、不依赖反射扫描
八、控制器层
package demo.jooq.controller;
import com.jfinal.kit.Kv;
import com.litongjava.annotation.Inject;
import com.litongjava.annotation.RequestPath;
import demo.jooq.dao.SystemAdminDao;
import demo.jooq.model.SystemAdmin;
@RequestPath("/systemAdmin")
public class SystemAdminController {
@Inject
private SystemAdminDao systemAdminDao;
public Kv getByLoginName() {
SystemAdmin admin = systemAdminDao.findByLoginName("litong");
return Kv.by("data", admin);
}
}
九、访问测试
启动应用后访问:
http://localhost/systemAdmin/getByLoginName
返回结果:
{
"data": {
"id": 1,
"loginName": "litong",
"password": "00000000"
}
}
十、AOP 自动注入原理
1. 注入链路
JooqConfig
↓
DSLContext 创建
↓
AopManager.addSingletonObject
↓
@Inject 自动注入
2. 为什么 DSLContext 适合单例
- jOOQ 本身无状态
- 线程安全
- 连接由 DataSource 管理
十一、为什么 jOOQ + tio-boot 非常搭
对比 MyBatis
| 维度 | MyBatis | jOOQ |
|---|---|---|
| SQL | XML / 注解 | 纯 Java |
| 类型安全 | 部分 | 完全 |
| 动态 SQL | XML 标签 | Java 表达式 |
| 重构友好 | 一般 | 极强 |
| 复杂 SQL | 一般 | 非常强 |
十二、什么时候推荐用 jOOQ
- 中大型系统
- SQL 复杂度高
- 对性能和可维护性要求高
- 不想被 ORM 约束
不推荐的场景:
- CRUD 极简单
- 团队 SQL 基础较弱
十三、总结
通过本文,我们完成了:
- 使用 配置类方式整合 jOOQ
- 不使用 XML、不使用生成器
- 与 tio-boot 生命周期深度整合
- 使用 AOP 实现
DSLContext自动注入 - 编写完全类型安全、可维护的 SQL
一句话总结:
jOOQ + tio-boot = 高性能、强控制、低侵入的现代 Java Web 数据访问方案。
