【SpringBoot DB 系列】Jooq 初體驗
java 環境中,說到資料庫的操作,我們通常會想到的是 mybatis 或者 hibernate,今天給大家介紹一個國內可能用得不太多的操作方式 JOOQ,一款基於 Java 訪問關係型資料庫的工具包,輕量,簡單,並且足夠靈活的 ORM 框架
本文將各位小夥伴演示一下 jooq 整合 springboot 的姿勢
<!-- more -->
I. 專案搭建
我們這裡藉助 h2dabase 來搭建演示專案,因此有興趣的小夥伴在文末可以直接獲取專案地址啟動即可體驗,不需要額外的安裝和配置 mysql 了
本文采用SpringBoot 2.2.1.RELEASE
+ maven 3.5.3
+ IDEA
進行開發
1. pom 依賴
下面給出核心的依賴配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jooq</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
2. 配置
接下來設定一下資料庫相關的配置資訊,在資源目錄resources
下,新建配置檔案application.properties
#Database Configuration
spring.datasource.url=jdbc:h2:~/h2-jooq-db
spring.datasource.username=test
spring.datasource.password=
spring.datasource.driverClassName=org.h2.Driver
3. 資料庫初始化
jooq 有一個特點,是需要我們自己來生成表結構物件,所以我們先初始化一下 h2dabase 的資料結構,詳情可以參考博文 [【DB 系列 h2databse 整合示例 demo】]()
表結構定義檔案schema-h2.sql
, 請注意表結構與 mysql 的表建立姿勢不太一樣哦
DROP TABLE IF EXISTS poet;
CREATE TABLE poet (
`id` int NOT NULL,
`name` varchar(20) NOT NULL default '',
CONSTRAINT pk_t_poet PRIMARY KEY (ID)
);
資料初始化data-h2.sql
INSERT INTO `poet` (`id`, `name`)
VALUES
(1, '李白'),
(2, '艾可翁'),
(3, '敖陶孫'),
(4, '安稹'),
(5, '艾性夫'),
(6, '奧敦周卿'),
(7, '安鏖'),
(8, '阿魯威'),
(9, '安鴻漸'),
(10, '安邑坊女');
我們接下來藉助 maven 外掛來初始化資料, pom.xml
檔案中,新增如下配置
<!-- The H2 test schema is loaded here -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sql-maven-plugin</artifactId>
<executions>
<execution>
<id>create-database-h2</id>
<phase>generate-sources</phase>
<goals>
<goal>execute</goal>
</goals>
</execution>
</executions>
<configuration>
<driver>org.h2.Driver</driver>
<url>jdbc:h2:~/h2-jooq-db</url>
<username>test</username>
<password></password>
<autocommit>true</autocommit>
<srcFiles>
<srcFile>src/main/resources/schema-h2.sql</srcFile>
<srcFile>src/main/resources/data-h2.sql</srcFile>
</srcFiles>
</configuration>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</dependency>
</dependencies>
</plugin>
如下圖的 case,完成資料的初始化
II. 體驗 case
在實際開始 jooq 的 curd 之前,需要先生成對應的表結構物件,這裡也是藉助 maven 外掛來完成
1. 程式碼自動生成
同樣在pom.xml
中新增如下配置
<plugin>
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen-maven</artifactId>
<executions>
<execution>
<id>generate-h2</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<jdbc>
<!-- 資料庫相關配置 -->
<driver>org.h2.Driver</driver>
<url>jdbc:h2:~/h2-jooq-db</url>
<username>test</username>
<password></password>
</jdbc>
<generator>
<database>
<!-- 資料庫的基本資訊 -->
<name>org.jooq.meta.h2.H2Database</name>
<includes>.*</includes>
<excludes></excludes>
<inputSchema>PUBLIC</inputSchema>
</database>
<generate>
<deprecated>false</deprecated>
<instanceFields>true</instanceFields>
<pojos>true</pojos>
</generate>
<target>
<!-- 自動生成的類的包名,以及路徑 -->
<packageName>com.git.hui.boot.jooq.h2</packageName>
<directory>src/main/java</directory>
</target>
</generator>
</configuration>
</plugin>
如上圖的方式執行完畢之後,會得到生成的程式碼
2. CURD
接下來我們給出 CURD 的基本使用姿勢
import static com.git.hui.boot.jooq.h2.tables.Poet.POET;
@Service
public class PoetService {
@Autowired
DSLContext dsl;
public int create(int id, String author) {
return dsl.insertInto(POET).set(POET.ID, id).set(POET.NAME, author).execute();
}
public PoetRecord get(int id) {
return dsl.selectFrom(POET).where(POET.ID.eq(id)).fetchOne();
}
public int update(int id, String author) {
return dsl.update(POET).set(POET.NAME, author).where(POET.ID.eq(id)).execute();
}
public int delete(int id) {
return dsl.delete(POET).where(POET.ID.eq(id)).execute();
}
public List<PoetRecord> getAll() {
return dsl.selectFrom(POET).fetch();
}
}
注意上面的使用,很好理解了,基本上能愉快的寫 sql,就可以愉快的使用 jooq,上面的這種鏈式寫法,對於 sql 的閱讀是非常友好的;這裡的重點是DSLContext
,它是JooqAutoConfiguration
自動載入的,這裡直接拿來使用了(關於更多的配置與多資料來源的問題,後面介紹)
3. 測試 case
在 pom 中引入web
依賴,設計一些基本的測試 case
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
增刪改查 case
@RestController
public class PoetRest {
@Autowired
private PoetService poetService;
@RequestMapping(path = "add")
public int add(Integer id, String name) {
return poetService.create(id, name);
}
@GetMapping(path = "get")
public String get(Integer id) {
PoetRecord record = poetService.get(id);
return r2str(record);
}
@GetMapping(path = "list")
public List<String> list() {
List<PoetRecord> list = poetService.getAll();
return list.stream().map(this::r2str).collect(Collectors.toList());
}
@GetMapping(path = "update")
public int update(int id, String author) {
return poetService.update(id, author);
}
@GetMapping(path = "del")
public int delete(int id) {
return poetService.delete(id);
}
private String r2str(PoetRecord record) {
return record.getId() + " # " + record.getName();
}
}
實測結果如下
4. 小結
到此,SpringBoot 整合 jooq 的 demo 已經完成,並提供了基礎的 CURD,整體來看,整合比較簡單,需要注意的是程式碼自動生成,我們這裡是藉助 maven 外掛來實現程式碼自動生成的, 此外也可以透過官方提供的jooq-xx.jar
+ xml
配置檔案來自動生成;後面單獨撈一篇博文給與介紹
從 jooq 的使用姿勢來看,最大的感官就是類 sql 的鏈式寫法,比較的直觀,閱讀友好;此外需要注意的是自動生成的實體PoetRecord
,不要暴露出去哦,一般推薦使用 jooq 包下面的Poet
來代替PoetRecord
來作為 BO 物件使用,可以透過RecordMapper
來實現轉換,如下
public Poet getById(int id) {
PoetRecord record = dsl.selectFrom(POET).where(POET.ID.eq(id)).fetchOne();
RecordMapper<PoetRecord, Poet> mapper =
dsl.configuration().recordMapperProvider().provide(POET.recordType(), POET.getClass());
return mapper.map(record);
}
II. 其他
0. 專案
- 工程:https://github.com/liuyueyi/spring-boot-demo
- 專案原始碼: https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-boot/107-jooq-aop
1. 一灰灰 Blog
盡信書則不如,以上內容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現 bug 或者有更好的建議,歡迎批評指正,不吝感激
下面一灰灰的個人部落格,記錄所有學習和工作中的博文,歡迎大家前去逛逛
- 一灰灰 Blog 個人部落格 https://blog.hhui.top
- 一灰灰 Blog-Spring 專題部落格 http://spring.hhui.top