前言
什么是Jooq?
Jooq反向生成数据库实体类
jooq包下每个类的作用
tables包下每个类的作用
daos包下类的作用
pojos包下每个类的作用
record包每个类的作用
前言
本次项目的搭建使用SpringBoot + MySQL + Jooq整合
什么是Jooq?
JOOQ 是基于Java访问关系型数据库的工具包。JOOQ 既吸取了传统ORM操作数据的简单性和安全性,又保留了原生sql的灵活性,它更像是介于 ORM和JDBC的中间层。
DSL(Domain Specific Language )风格,代码够简单和清晰。遇到不会写的sql可以充分利用IDEA代码提示功能轻松完成。
保留了传统ORM 的优点,简单操作性,安全性,类型安全等。不需要复杂的配置,并且可以利用Java 8 Stream API 做更加复杂的数据转换。
支持主流的RDMS和更多的特性,如self-joins,union,存储过程,复杂的子查询等等。
丰富的Fluent API和完善文档。
runtime schema mapping 可以支持多个数据库schema访问。简单来说使用一个连接池可以访问N个DB schema,使用比较多的就是SaaS应用的多租户场景。
Jooq反向生成数据库实体类
1.创建好SpringBoot项目后在pom.xml中导入jooq所需包:
<?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 http://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.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo</groupId>
<artifactId>springjooq-1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springjooq-1</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-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jooq</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.15</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.jooq</groupId>
<artifactId>jooq-meta</artifactId>
</dependency>
<dependency>
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen</artifactId>
</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>${jooq.version}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<!--对应的数据库依赖-->
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>
</dependencies>
<configuration>
<!--配置文件的存放路径-->
<configurationFile>src/main/resources/JooqConfig.xml</configurationFile>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.在application.properties中加入访问数据库路径
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/demo?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
3.在SpringBoot项目结构的src/main/resources下创建一个JooqConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<jdbc>
<driver>com.mysql.jdbc.Driver</driver>
<!-- 配置数据库地址 -->
<url>jdbc:mysql://127.0.0.1:3306/demo?characterEncoding=UTF-8</url>
<!-- 配置数据库用户名-->
<user>root</user>
<!-- 配置数据库密码-->
<password>123456</password>
</jdbc>
<generator>
<!-- 代码生成器 -->
<!-- <name>org.jooq.meta.mysql.MySQLDatabase</name>-->
<database>
<!--强制为scheme1模式下所有的含有id域生成id-->
<!--是否重写主键-->
<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>com.demo.main.jooq</packageName>
<directory>src/main/java</directory>
</target>
</generator>
</configuration>
4.右击项目选择Run->Maven install运行即可,如图 (注:如使用IDEA在编辑器的右边点击Maven找到指定项目点击install即可 )
5.生成好后可以看到项目的结构
jooq包下每个类的作用
先讲解下jooq包下面的每个类的作用
DefaultCatalog.java:里面存放的是Demo.java也就是数据库名
/*
* This file is generated by jOOQ.
*/
package com.demo.main.jooq;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Generated;
import org.jooq.Schema;
import org.jooq.impl.CatalogImpl;
/**
* This class is generated by jOOQ.
*/
@Generated(
value = {
"http://www.jooq.org",
"jOOQ version:3.11.9"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class DefaultCatalog extends CatalogImpl {
private static final long serialVersionUID = 1891688733;
/**
* The reference instance of <code></code>
*/
public static final DefaultCatalog DEFAULT_CATALOG = new DefaultCatalog();
/**
* The schema <code>demo</code>.
*/
public final Demo DEMO = com.demo.main.jooq.Demo.DEMO;
/**
* No further instances allowed
*/
private DefaultCatalog() {
super("");
}
@Override
public final List<Schema> getSchemas() {
List result = new ArrayList();
result.addAll(getSchemas0());
return result;
}
private final List<Schema> getSchemas0() {
return Arrays.<Schema>asList(
Demo.DEMO);
}
}
Demo.java里面存放的是数据库的表
/*
* This file is generated by jOOQ.
*/
package com.demo.main.jooq;
import com.demo.main.jooq.tables.SClass;
import com.demo.main.jooq.tables.Student;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Generated;
import org.jooq.Catalog;
import org.jooq.Table;
import org.jooq.impl.SchemaImpl;
/**
* This class is generated by jOOQ.
*/
@Generated(
value = {
"http://www.jooq.org",
"jOOQ version:3.11.9"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class Demo extends SchemaImpl {
private static final long serialVersionUID = 979506244;
/**
* The reference instance of <code>demo</code>
*/
public static final Demo DEMO = new Demo();
/**
* The table <code>demo.student</code>.
*/
public final Student STUDENT = com.demo.main.jooq.tables.Student.STUDENT;
/**
* The table <code>demo.s_class</code>.
*/
public final SClass S_CLASS = com.demo.main.jooq.tables.SClass.S_CLASS;
/**
* No further instances allowed
*/
private Demo() {
super("demo", null);
}
/**
* {@inheritDoc}
*/
@Override
public Catalog getCatalog() {
return DefaultCatalog.DEFAULT_CATALOG;
}
@Override
public final List<Table<?>> getTables() {
List result = new ArrayList();
result.addAll(getTables0());
return result;
}
private final List<Table<?>> getTables0() {
return Arrays.<Table<?>>asList(
Student.STUDENT,
SClass.S_CLASS);
}
}
Indexes.java存放的是表的主键(索引)
/*
* This file is generated by jOOQ.
*/
package com.demo.main.jooq;
import com.demo.main.jooq.tables.SClass;
import javax.annotation.Generated;
import org.jooq.Index;
import org.jooq.OrderField;
import org.jooq.impl.Internal;
/**
* A class modelling indexes of tables of the <code>demo</code> schema.
*/
@Generated(
value = {
"http://www.jooq.org",
"jOOQ version:3.11.9"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class Indexes {
// -------------------------------------------------------------------------
// INDEX definitions
// -------------------------------------------------------------------------
public static final Index S_CLASS_PRIMARY = Indexes0.S_CLASS_PRIMARY;
// -------------------------------------------------------------------------
// [#1459] distribute members to avoid static initialisers > 64kb
// -------------------------------------------------------------------------
private static class Indexes0 {//数据库中设置SClass.ID为主键
public static Index S_CLASS_PRIMARY = Internal.createIndex("PRIMARY", SClass.S_CLASS, new OrderField[] { SClass.S_CLASS.ID }, true);
}
}
Keys.java里面有两个类Identities0存放的自增字段,UniqueKeys0存放的是唯一字段
/*
* This file is generated by jOOQ.
*/
package com.demo.main.jooq;
import com.demo.main.jooq.tables.SClass;
import com.demo.main.jooq.tables.records.SClassRecord;
import javax.annotation.Generated;
import org.jooq.Identity;
import org.jooq.UniqueKey;
import org.jooq.impl.Internal;
/**
* A class modelling foreign key relationships and constraints of tables of
* the <code>demo</code> schema.
*/
@Generated(
value = {
"http://www.jooq.org",
"jOOQ version:3.11.9"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class Keys {
// -------------------------------------------------------------------------
// IDENTITY definitions
// -------------------------------------------------------------------------
public static final Identity<SClassRecord, Integer> IDENTITY_S_CLASS = Identities0.IDENTITY_S_CLASS;
// -------------------------------------------------------------------------
// UNIQUE and PRIMARY KEY definitions
// -------------------------------------------------------------------------
public static final UniqueKey<SClassRecord> KEY_S_CLASS_PRIMARY = UniqueKeys0.KEY_S_CLASS_PRIMARY;
// -------------------------------------------------------------------------
// FOREIGN KEY definitions
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// [#1459] distribute members to avoid static initialisers > 64kb
// -------------------------------------------------------------------------
private static class Identities0 {//自增
public static Identity<SClassRecord, Integer> IDENTITY_S_CLASS = Internal.createIdentity(SClass.S_CLASS, SClass.S_CLASS.ID);
}
private static class UniqueKeys0 {//主键
public static final UniqueKey<SClassRecord> KEY_S_CLASS_PRIMARY = Internal.createUniqueKey(SClass.S_CLASS, "KEY_s_class_PRIMARY", SClass.S_CLASS.ID);
}
}
Tables.java里面存放的是表名,一般都是通过这个类去访问表和字段的
/*
* This file is generated by jOOQ.
*/
package com.demo.main.jooq;
import com.demo.main.jooq.tables.SClass;
import com.demo.main.jooq.tables.Student;
import javax.annotation.Generated;
/**
* Convenience access to all tables in demo
*/
@Generated(
value = {
"http://www.jooq.org",
"jOOQ version:3.11.9"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class Tables {
/**
* The table <code>demo.student</code>.
*/
public static final Student STUDENT = com.demo.main.jooq.tables.Student.STUDENT;
/**
* The table <code>demo.s_class</code>.
*/
public static final SClass S_CLASS = com.demo.main.jooq.tables.SClass.S_CLASS;
}
tables包下每个类的作用
下面的两个类对应着数据库的表。
类里面就是表的字段,里面有字段的数据类型和长度(注:只展示一个类的代码,方便理解)
/*
* This file is generated by jOOQ.
*/
package com.demo.main.jooq.tables;
import com.demo.main.jooq.Demo;
import com.demo.main.jooq.Indexes;
import com.demo.main.jooq.Keys;
import com.demo.main.jooq.tables.records.SClassRecord;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Generated;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Identity;
import org.jooq.Index;
import org.jooq.Name;
import org.jooq.Record;
import org.jooq.Schema;
import org.jooq.Table;
import org.jooq.TableField;
import org.jooq.UniqueKey;
import org.jooq.impl.DSL;
import org.jooq.impl.TableImpl;
/**
* This class is generated by jOOQ.
*/
@Generated(
value = {
"http://www.jooq.org",
"jOOQ version:3.11.9"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class SClass extends TableImpl<SClassRecord> {
private static final long serialVersionUID = -1991044853;
/**
* The reference instance of <code>demo.s_class</code>
*/
public static final SClass S_CLASS = new SClass();
/**
* The class holding records for this type
*/
@Override
public Class<SClassRecord> getRecordType() {
return SClassRecord.class;
}
/**
* The column <code>demo.s_class.id</code>.
*/
public final TableField<SClassRecord, Integer> ID = createField("id", org.jooq.impl.SQLDataType.INTEGER.nullable(false).identity(true), this, "");
/**
* The column <code>demo.s_class.classname</code>.
*/
public final TableField<SClassRecord, String> CLASSNAME = createField("classname", org.jooq.impl.SQLDataType.VARCHAR(255), this, "");
/**
* Create a <code>demo.s_class</code> table reference
*/
public SClass() {
this(DSL.name("s_class"), null);
}
/**
* Create an aliased <code>demo.s_class</code> table reference
*/
public SClass(String alias) {
this(DSL.name(alias), S_CLASS);
}
/**
* Create an aliased <code>demo.s_class</code> table reference
*/
public SClass(Name alias) {
this(alias, S_CLASS);
}
private SClass(Name alias, Table<SClassRecord> aliased) {
this(alias, aliased, null);
}
private SClass(Name alias, Table<SClassRecord> aliased, Field<?>[] parameters) {
super(alias, null, aliased, parameters, DSL.comment(""));
}
public <O extends Record> SClass(Table<O> child, ForeignKey<O, SClassRecord> key) {
super(child, key, S_CLASS);
}
/**
* {@inheritDoc}
*/
@Override
public Schema getSchema() {
return Demo.DEMO;
}
/**
* {@inheritDoc}
*/
@Override
public List<Index> getIndexes() {
return Arrays.<Index>asList(Indexes.S_CLASS_PRIMARY);
}
/**
* {@inheritDoc}
*/
@Override
public Identity<SClassRecord, Integer> getIdentity() {
return Keys.IDENTITY_S_CLASS;
}
/**
* {@inheritDoc}
*/
@Override
public UniqueKey<SClassRecord> getPrimaryKey() {
return Keys.KEY_S_CLASS_PRIMARY;
}
/**
* {@inheritDoc}
*/
@Override
public List<UniqueKey<SClassRecord>> getKeys() {
return Arrays.<UniqueKey<SClassRecord>>asList(Keys.KEY_S_CLASS_PRIMARY);
}
/**
* {@inheritDoc}
*/
@Override
public SClass as(String alias) {
return new SClass(DSL.name(alias), this);
}
/**
* {@inheritDoc}
*/
@Override
public SClass as(Name alias) {
return new SClass(alias, this);
}
/**
* Rename this table
*/
@Override
public SClass rename(String name) {
return new SClass(DSL.name(name), null);
}
/**
* Rename this table
*/
@Override
public SClass rename(Name name) {
return new SClass(name, null);
}
}
daos包下类的作用
这里只生成了一个因为另一张表没有设置索引
daos包下面的dao层会有自动生成的一些定义好的主键查询的方法
/*
* This file is generated by jOOQ.
*/
package com.demo.main.jooq.tables.daos;
import com.demo.main.jooq.tables.SClass;
import com.demo.main.jooq.tables.records.SClassRecord;
import java.util.List;
import javax.annotation.Generated;
import org.jooq.Configuration;
import org.jooq.impl.DAOImpl;
/**
* This class is generated by jOOQ.
*/
@Generated(
value = {
"http://www.jooq.org",
"jOOQ version:3.11.9"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class SClassDao extends DAOImpl<SClassRecord, com.demo.main.jooq.tables.pojos.SClass, Integer> {
/**
* Create a new SClassDao without any configuration
*/
public SClassDao() {
super(SClass.S_CLASS, com.demo.main.jooq.tables.pojos.SClass.class);
}
/**
* Create a new SClassDao with an attached configuration
*/
public SClassDao(Configuration configuration) {
super(SClass.S_CLASS, com.demo.main.jooq.tables.pojos.SClass.class, configuration);
}
/**
* {@inheritDoc}
*/
@Override
protected Integer getId(com.demo.main.jooq.tables.pojos.SClass object) {
return object.getId();
}
/**
* Fetch records that have <code>id IN (values)</code>
*/
public List<com.demo.main.jooq.tables.pojos.SClass> fetchById(Integer... values) {
return fetch(SClass.S_CLASS.ID, values);
}
/**
* Fetch a unique record that has <code>id = value</code>
*/
public com.demo.main.jooq.tables.pojos.SClass fetchOneById(Integer value) {
return fetchOne(SClass.S_CLASS.ID, value);
}
/**
* Fetch records that have <code>classname IN (values)</code>
*/
public List<com.demo.main.jooq.tables.pojos.SClass> fetchByClassname(String... values) {
return fetch(SClass.S_CLASS.CLASSNAME, values);
}
}
pojos包下每个类的作用
pojos包下面顾名思义就是实体类了(注:只展示一个类的代码,方便理解)
/*
* This file is generated by jOOQ.
*/
package com.demo.main.jooq.tables.pojos;
import java.io.Serializable;
import javax.annotation.Generated;
/**
* This class is generated by jOOQ.
*/
@Generated(
value = {
"http://www.jooq.org",
"jOOQ version:3.11.9"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class SClass implements Serializable {
private static final long serialVersionUID = 1278405963;
private Integer id;
private String classname;
public SClass() {}
public SClass(SClass value) {
this.id = value.id;
this.classname = value.classname;
}
public SClass(
Integer id,
String classname
) {
this.id = id;
this.classname = classname;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getClassname() {
return this.classname;
}
public void setClassname(String classname) {
this.classname = classname;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("SClass (");
sb.append(id);
sb.append(", ").append(classname);
sb.append(")");
return sb.toString();
}
}
record包每个类的作用
下面记录一些表字段(注:只展示一个类的代码,方便理解)
/*
* This file is generated by jOOQ.
*/
package com.demo.main.jooq.tables.records;
import com.demo.main.jooq.tables.SClass;
import javax.annotation.Generated;
import org.jooq.Field;
import org.jooq.Record1;
import org.jooq.Record2;
import org.jooq.Row2;
import org.jooq.impl.UpdatableRecordImpl;
/**
* This class is generated by jOOQ.
*/
@Generated(
value = {
"http://www.jooq.org",
"jOOQ version:3.11.9"
},
comments = "This class is generated by jOOQ"
)
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class SClassRecord extends UpdatableRecordImpl<SClassRecord> implements Record2<Integer, String> {
private static final long serialVersionUID = -7367157;
/**
* Setter for <code>demo.s_class.id</code>.
*/
public void setId(Integer value) {
set(0, value);
}
/**
* Getter for <code>demo.s_class.id</code>.
*/
public Integer getId() {
return (Integer) get(0);
}
/**
* Setter for <code>demo.s_class.classname</code>.
*/
public void setClassname(String value) {
set(1, value);
}
/**
* Getter for <code>demo.s_class.classname</code>.
*/
public String getClassname() {
return (String) get(1);
}
// -------------------------------------------------------------------------
// Primary key information
// -------------------------------------------------------------------------
/**
* {@inheritDoc}
*/
@Override
public Record1<Integer> key() {
return (Record1) super.key();
}
// -------------------------------------------------------------------------
// Record2 type implementation
// -------------------------------------------------------------------------
/**
* {@inheritDoc}
*/
@Override
public Row2<Integer, String> fieldsRow() {
return (Row2) super.fieldsRow();
}
/**
* {@inheritDoc}
*/
@Override
public Row2<Integer, String> valuesRow() {
return (Row2) super.valuesRow();
}
/**
* {@inheritDoc}
*/
@Override
public Field<Integer> field1() {
return SClass.S_CLASS.ID;
}
/**
* {@inheritDoc}
*/
@Override
public Field<String> field2() {
return SClass.S_CLASS.CLASSNAME;
}
/**
* {@inheritDoc}
*/
@Override
public Integer component1() {
return getId();
}
/**
* {@inheritDoc}
*/
@Override
public String component2() {
return getClassname();
}
/**
* {@inheritDoc}
*/
@Override
public Integer value1() {
return getId();
}
/**
* {@inheritDoc}
*/
@Override
public String value2() {
return getClassname();
}
/**
* {@inheritDoc}
*/
@Override
public SClassRecord value1(Integer value) {
setId(value);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public SClassRecord value2(String value) {
setClassname(value);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public SClassRecord values(Integer value1, String value2) {
value1(value1);
value2(value2);
return this;
}
// -------------------------------------------------------------------------
// Constructors
// -------------------------------------------------------------------------
/**
* Create a detached SClassRecord
*/
public SClassRecord() {
super(SClass.S_CLASS);
}
/**
* Create a detached, initialised SClassRecord
*/
public SClassRecord(Integer id, String classname) {
super(SClass.S_CLASS);
set(0, id);
set(1, classname);
}
}