一. jOOQ简介
1. jOOQ概述
jOOQ(Java Object Oriented Querying): 翻译成中文是 Java面向对象查询 的意思。
jOOQ是Data Geekery提供的基于Java的轻量级数据库访问库,通过特定的语法将类以及数据库模型翻译成对应的SQL语句实现实体与关系的映射,在数据库与类之间建立起一一对应关系,也可以让我们通过它的流式API构建出类型安全的SQL查询。
jOOQ是一个基于Java编写SQL的工具包,具有简单、轻量、函数式编程写SQL等独特优势,非常适合敏捷快速迭代开发。
jOOQ不管是商业版,还是开源版本都能跟Spring Boot一块使用。
2. jOOQ的特点:
- 继承了ORM框架的优点,简单操作,类型安全等。jOOQ将SQL建模为内部DSL,使用Java编译器编译SQL语法,元数据和数据类型。
- jOOQ会根据数据库的元数据来生成对应的实体类,省略了原有开发中不断修改对应数据库的类名,属性名。
- jOOQ允许运行时配置数据库模式,且支持行级别的安全。
- 支持联合查询,多表查询,存储过程等数据库高级操作。
二. Spring Boot中整合jOOQ
1.创建Web项目
我们按照之前的经验,创建一个web程序,并将之改造成Spring Boot项目,具体过程略。
2. 添加依赖和插件
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- 阿里巴巴fastjson,解析json视图 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.46</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-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.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> </plugin> <plugin> <groupId>org.jooq</groupId> <artifactId>jooq-codegen-maven</artifactId> <executions> <execution> <goals> <goal>generate</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> </dependencies> <configuration> <configurationFile>src/main/resources/JooqConfig.xml</configurationFile> </configuration> </plugin> </plugins> </build> |
3. 创建JooqConfig配置文件
在resource目录下,创建一个JooqConfig.xml配置文件,用来进行关联数据库,根据数据库进行逆向生成对应的Java代码。
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <configuration> <jdbc> <driver>com.mysql.jdbc.Driver</driver> <url>jdbc:mysql://localhost:3306/db4?serverTimezone=GMT</url> <user>root</user> <password>syc</password> </jdbc> <generator> <!-- 代码生成器 --> <!--<name>org.jooq.util.JavaGenerator</name>--> <name>org.jooq.codegen.JavaGenerator</name> <database> <!--下面这两行是为view也生成代码的关键--> <!--force generating id'sfor everything in public schema, that has an 'id' field--> <syntheticPrimaryKeys>public\..*\.id</syntheticPrimaryKeys> <!--name for fake primary key--> <overridePrimaryKeys>override_primmary_key</overridePrimaryKeys> <!--<name>org.jooq.util.mysql.MySQLDatabase</name>--> <name>org.jooq.meta.mysql.MySQLDatabase</name> <!--include和exclude用于控制为数据库中哪些表生成代码--> <includes>.*</includes> <!--<excludes></excludes>--> <!--数据库名称--> <inputSchema>db4</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>com.yyg.boot.generator</packageName> <directory>src/main/java</directory> </target> </generator> </configuration> |
4. mvn执行逆向工程
在lifecycle中执行compile命令,就可以自动执行逆向工程的命令了。
只要JooqConfig.xml配置文件没问题,并且依赖包都完整下载,就可以逆向工程执行成功。
?逆向工程执行完毕后,我们就可以看到如下效果,发现自动生成了很多的Java代码,这些Java代码就是根据我们数据库中的表,生成的对应的Java代码。
对应的数据库表:
5. 配置application.yml文件
主要是配置关联我们的数据库。
1 2 3 4 5 6 7 8 9 10 11 | spring: datasource: url: jdbc:mysql://localhost:3306/db4?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true type: com.alibaba.druid.pool.DruidDataSource username: root password: syc driver-class-name: com.mysql.jdbc.Driver #驱动 jpa: hibernate: ddl-auto: update #自动更新 show-sql: true #日志中显示sql语句 |
6. 创建DataSource配置类
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 28 29 30 31 32 33 34 35 36 | package com.yyg.boot.config; import com.alibaba.druid.pool.DruidDataSource; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; /** * @Author 一一哥Sun * @Date Created in 2020/3/30 * @Description 第二种配置数据源的方式 */ @Data @ComponentScan @Configuration @ConfigurationProperties(prefix="spring.datasource") public class DbConfig { private String url; private String username; private String password; @Bean public DataSource getDataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); return dataSource; } } |
7.创建Service层代码
创建UserService接口
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 28 29 30 31 32 33 34 35 36 37 38 39 40 | package com.yyg.boot.service; import com.yyg.boot.generator.tables.pojos.User; import java.util.Iterator; import java.util.List; /** * @Author 一一哥Sun * @Date Created in 2020/4/2 * @Description Description */ public interface UserService { /** * 删除 */ void delete(int id); /** * 增加 */ void insert(User user); /** * 更新 */ int update(User user); /** * 查询单个 */ User selectById(int id); /** * 查询全部列表 */ List<User> selectAll(int pageNum, int pageSize); } |
创建UserServiceImpl类
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | package com.yyg.boot.service.impl; import com.yyg.boot.generator.tables.User; import com.yyg.boot.generator.tables.records.UserRecord; import com.yyg.boot.service.UserService; import org.jooq.DSLContext; import org.jooq.Record; import org.jooq.Result; import org.jooq.UpdateSetMoreStep; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Iterator; import java.util.List; /** * @Author 一一哥Sun * @Date Created in 2020/4/2 * @Description Description */ @Service public class UserServiceImpl implements UserService { @Autowired DSLContext dsl; /** * 给User表 重命名 u 。(类似sql语句中的 user as u). * 注意一点,这个User类是逆向生成的tables包下的,不是pojos包下的User实体类。 * (逆向工程它会生成两个User类。一个在pojos下,一个再tables下) */ com.yyg.boot.generator.tables.User u = User.USER.as("u"); /** * 删除 */ @Override public void delete(int id) { dsl.delete(u).where(u.ID.eq(id)); } /** * 增加 */ @Override public void insert(com.yyg.boot.generator.tables.pojos.User user) { dsl.insertInto(u). columns(u.ADDRESS, u.BIRTHDAY, u.SEX, u.USERNAME). values(user.getAddress(), user.getBirthday(), user.getSex(), user.getUsername()) .execute(); } /** * 更新 * * @param user */ @Override public int update(com.yyg.boot.generator.tables.pojos.User user) { dsl.update(u).set((Record) user); return 0; } /** * 查询单个 */ @Override public com.yyg.boot.generator.tables.pojos.User selectById(int id) { List<com.yyg.boot.generator.tables.pojos.User> result = dsl.select(u.ADDRESS,u.BIRTHDAY,u.ID,u.SEX,u.USERNAME) .from(u) .where(u.ID.eq(id)) .fetch() .into(com.yyg.boot.generator.tables.pojos.User.class); return result.get(0); } /** * 查询全部列表 */ @Override public List<com.yyg.boot.generator.tables.pojos.User> selectAll(int pageNum, int pageSize) { return dsl.select() .from(u) //id倒序 .orderBy(u.ID.desc()) //分页 .limit(0) //分页 .offset(10) .fetch() //数据类型格式转化 .into(com.yyg.boot.generator.tables.pojos.User.class); } } |
8. 创建Controller测试接口
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 28 | package com.yyg.boot.web; import com.yyg.boot.generator.tables.pojos.User; import com.yyg.boot.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @Author 一一哥Sun * @Date Created in 2020/4/2 * @Description Description */ @RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @GetMapping("/{id}") public User findUserById(@PathVariable("id") Integer id) { return userService.selectById(id); } } |
9. 创建入口类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package com.yyg.boot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * @Author 一一哥Sun * @Date Created in 2020/4/2 * @Description Description */ @SpringBootApplication public class JooqApplication { public static void main(String[] args){ SpringApplication.run(JooqApplication.class,args); } } |
10.总的项目结构
11.测试接口
我们在浏览器中进行测试。
可以看到我们的接口功能已经实现了,其他方法没有一一测试,感兴趣的朋友可以自己试验一下。