前言
之前朋友推荐了一款ORM框架jooq,有空的时候搜了一下资料,感觉有点意思,就自己写了个简单demo。官方简介说:jOOQ 高效的合并了复杂 SQL、类型安全、源码生成、Active Records、存储过程以及高级数据类型的 Java 类库。这款框架相对mybatis,对于java开发来说,复杂查询这一块相对更轻松一些,它可以很方便地进行复杂SQL的查询。
springboot+jooq项目搭建
pom引入相关依赖
这里利用jooq插件反向生成实体类及dao层代码,直接把整个pom文件粘出来,根据需要修改。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.kite</groupId>
<artifactId>jooq-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jooq-demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jooq</artifactId>
</dependency>
<dependency>
<groupId>org.jooq</groupId>
<artifactId>jooq</artifactId>
</dependency>
<dependency>
<groupId>org.jooq</groupId>
<artifactId>jooq-meta</artifactId>
</dependency>
<dependency>
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen-maven</artifactId>
<version>3.13.4</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<!--对应的数据库依赖-->
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
</dependencies>
<configuration>
<!--配置文件的存放路径-->
<configurationFile>src/main/resources/JooqConfig.xml</configurationFile>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.yml配置
就配置一个MySQL数据库连接和连接池参数自定义就好了。
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
password: 123456
url: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&noAccessToProcedureBodies=true&tinyInt1isBit=false&useSSL=false
username: root
hikari:
auto-commit: true
connection-test-query: SELECT 1
connection-timeout: 60000
idle-timeout: 600000
max-lifetime: 7200
maximum-pool-size: 50
minimum-idle: 50
pool-name: JooqDemoHikariCP
server:
port: 8088
logging:
level:
cn.kite: debug
JooqConfig.xml
在pom文件配置里有代码生成的配置文件JooqConfig.xml,文件内容如下,文件放到sources下面跟application.yml同级就好了。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<configuration>
<jdbc>
<!-- 配置需要的数据库的驱动 -->
<driver>com.mysql.cj.jdbc.Driver</driver>
<!-- 配置数据库地址 -->
<url>jdbc:mysql://127.0.0.1:3306/demo</url>
<!-- 配置数据库用户名-->
<user>root</user>
<!-- 配置数据库密码-->
<password>123456</password>
</jdbc>
<generator>
<!-- 代码生成器 -->
<name>org.jooq.codegen.JavaGenerator</name>
<database>
<!--是否重写主键-->
<overridePrimaryKeys>true</overridePrimaryKeys>
<name>org.jooq.meta.mysql.MySQLDatabase</name>
<!--include和exclude用于控制为数据库中哪些表生成代码-->
<includes>.*</includes>
<excludes></excludes>
<!--数据库名称-->
<inputSchema>demo</inputSchema>
</database>
<generate>
<!--是否生成dao和pojo-->
<daos>true</daos>
<pojos>true</pojos>
<!--是否把数据库时间类型映射到java 8时间类型-->
<javaTimeTypes>true</javaTimeTypes>
<!--<interfaces>true</interfaces>-->
<!--是否在生成的代码中添加spring注释,比如@Repository-->
<springAnnotations>false</springAnnotations>
</generate>
<target>
<!--生成代码文件的包名及放置目录-->
<packageName>cn.kite.jooq</packageName>
<directory>src/main/java</directory>
</target>
</generator>
</configuration>
编译反向生成实体类代码
搭建一个springboot下面,通过上面三步配置,就可以进行maven编译了,编译正常,success之后,就可以在项目包下面看到插件自动生成的代码了。jooq包下面生成了很多类,如下图所示。
编写测试代码
controller层代码
package cn.kite.controller;
import cn.kite.jooq.tables.pojos.User;
import cn.kite.req.ReqPageVO;
import cn.kite.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @author kite
* @description
* @date 2020/11/2
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private IUserService userService;
@DeleteMapping
public Object delete(@RequestParam int id){
userService.delete(id);
return "success";
}
@PostMapping
public Object insert(@RequestBody User user){
userService.insert(user);
return "success";
}
@PutMapping
public Object update(@RequestBody User user){
userService.update(user);
return "success";
}
@GetMapping("/{id}")
public Object selectById(@PathVariable("id") int id){
return userService.selectById(id);
}
@GetMapping
public Object selectConditionPage(@RequestBody ReqPageVO<User> reqPageVO){
return userService.selectConditionPage(reqPageVO);
}
}
service
package cn.kite.service;
import cn.kite.jooq.tables.pojos.User;
import cn.kite.req.ReqPageVO;
import cn.kite.res.ResPageVO;
/**
* @author kite
* @description
* @date 2020/11/2
*/
public interface IUserService {
/**
* 删除
*/
public void delete(int id);
/**
* 增加
*/
public void insert(User user);
/**
* 更新
*/
public int update(User user);
/**
* 查询单个
*/
public User selectById(int id);
/**
* 条件分页查询
*/
public ResPageVO<User> selectConditionPage(ReqPageVO<User> pageVO);
}
实现接口
package cn.kite.service.impl;
import cn.kite.jooq.tables.daos.UserDao;
import cn.kite.jooq.tables.pojos.User;
import cn.kite.req.ReqPageVO;
import cn.kite.res.ResPageVO;
import cn.kite.service.IUserService;
import org.jooq.Condition;
import org.jooq.DSLContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
/**
* @author kite
* @description
* @date 2020/11/2
*/
@Service
public class UserServiceImpl implements IUserService {
cn.kite.jooq.tables.User dbUser = cn.kite.jooq.tables.User.USER;
@Autowired
DSLContext dslContext;
private UserDao userDao;
//表示在UserServiceImpl构造完成之后执行,直接注入dao没有配置,启动时bean加载会报错
@PostConstruct
private void createDao() {
userDao = new UserDao(dslContext.configuration());
}
@Override
public void delete(int id) {
userDao.deleteById(id);
}
@Override
public void insert(User user) {
userDao.insert(user);
}
@Override
public int update(User user) {
userDao.update(user);
return 0;
}
@Override
public User selectById(int id) {
return userDao.findById(id);
}
@Override
public ResPageVO<User> selectConditionPage(ReqPageVO<User> pageVO) {
List<Condition> conditions = new ArrayList<>();
if (pageVO.getCondition().getId() != null) {
conditions.add(dbUser.ID.ge(pageVO.getCondition().getId()));
}
if (!StringUtils.isEmpty(pageVO.getCondition().getName())) {
conditions.add(dbUser.NAME.like(pageVO.getCondition().getName()));
}
long totalCount = userDao.ctx().selectFrom(dbUser).where(conditions).stream().count();
ResPageVO<User> resPageVO = new ResPageVO<>().build(pageVO, (int) totalCount);
//没有数据直接返回
if (totalCount == 0) {
return resPageVO;
}
//条件+分页查询
List<User> list = userDao.ctx().selectFrom(dbUser).where(conditions)
.limit((pageVO.getPage() - 1) * pageVO.getPageSize(), pageVO.getPageSize()).fetchInto(User.class);
resPageVO.setList(list);
return resPageVO;
}
}
用到的其他pojo
package cn.kite.req;
import lombok.Data;
/**
* @author kite
* @description
* @date 2020/11/2
*/
@Data
public class ReqPageVO<T> {
/**
* 当前页
*/
private int page;
/**
* 分页条数
*/
private int pageSize;
/**
* 查询条件
*/
private T condition;
}
package cn.kite.res;
import cn.kite.req.ReqPageVO;
import lombok.Data;
import java.util.List;
/**
* @author kite
* @description
* @date 2020/11/2
*/
@Data
public class ResPageVO<T> {
/**
* 当前页
*/
private Integer page;
/**
* 分页条数
*/
private Integer pageSize;
/**
* 总页数
*/
private Integer totalPage;
/**
* 总条数
*/
private Integer totalCount;
/**
* 返回集合
*/
private List<T> list;
public ResPageVO build(ReqPageVO reqPageVO, Integer totalCount) {
if(totalCount == null){
totalCount = 0;
}
this.page = reqPageVO.getPage();
this.pageSize = reqPageVO.getPageSize();
this.totalCount = totalCount;
this.totalPage = totalCount % reqPageVO.getPageSize() == 0 ? totalCount / reqPageVO.getPageSize() : totalCount / reqPageVO.getPageSize() + 1;
return this;
}
}
最后测试,启动springboot项目,通过接口调用,就可以对数据库进行简单的增删改查操作了。
注意
- 插件生成的UserDao不能直接通过bean对象注入的方式在service引入。如果直接注入,项目启动的时候就会报错。这个bean生成需要传入一个配置类DSLContext,然后就可以了。通过代码提示,可以看到dao有很多接口方法可以很方便的直接使用。
- 生成的类有两个user,一个是数据库要用的类,tables下面那个,它是继承自TableImpl的,可以通过它指定数据表属性、字段属性等。pojos下面的是pojo实体类。