JOOQ入门指南

JOOQ

JOOQ提供了SQLBuilder功能 ,数据迁移功能,SQL执行能力,执行生命周期的管理等属性。相较hibernate,JOOQ执行SQL的过程对程序员的可见性更高。相较于mybatis SQL脚本的管理更为灵活,在使用上减少了配置文件的管理和配置。

JOOQ的目标并不是成为完整实现JPA协议的ORM框架,其更专注于SQL的执行,想要实现的是OLTP和大数据清洗场景下的数据管理.它并不是JAP框架的替代,相反,它更想成为JPA协议框架的补充。

Whenever SQL is a good fit, jOOQ is a good fit. Whenever you’re operating and persisting the object graph, JPA is a good fit.And sometimes, it’s best to combine both。

代码生成

type1:命令行生成

命令行如下:

 java -classpath jooq-3.13.2.jar;jooq-meta-3.13.2.jar;jooq-codegen-3.13.2.jar;reactive-    streams-1.0.2.jar;mysql-connector-java-8.0.20.jar;. org.jooq.codegen.GenerationTool /jooq.xml

在此之前需要准备1.java运行环境;2.执行命令行涉及的包;3.jooq.xml配置


<configuration xmlns="http://www.jooq.org/xsd/jooq-codegen-3.13.0.xsd">
    
    <jdbc>
        <driver>driver>
        <url>url>
        <user>user>
        <password>password>
    jdbc>

    <generator>
        
        <name>org.jooq.codegen.JavaGeneratorname>

        <database>
            
            <name>org.jooq.meta.mysql.MySQLDatabasename>

            
            <inputSchema>jooqinputSchema>

            
            <includes>.*includes>

            
            <excludes>excludes>
        database>
        <generate>
            
            <daos>truedaos>
            <pojos>truepojos>

            
            <javaTimeTypes>truejavaTimeTypes>
            
            
            <springAnnotations>truespringAnnotations>
            <pojosToString>truepojosToString>
        generate>
        <target>
            
            <packageName>包名packageName>

            
            <directory>C:/workspace/MySQLTest/src/main/javadirectory>
        target>
    generator>
configuration>
type2:maven+springboot 生成
mvn clean install

需要准备1.java运行环境;2.执行命令行涉及的包;3.jooq.xml配置;4.maven 环境 ;5 包含jooq的相关依赖的

pom.xml

pom.xml如下


<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.0modelVersion>
   <parent>
      <groupId>org.springframework.bootgroupId>
      <artifactId>spring-boot-starter-parentartifactId>
      <version>2.3.1.RELEASEversion>
      <relativePath/> 
   parent>
   <groupId>com.*.jooqgroupId>
   <artifactId>demoartifactId>
   <version>0.0.1-SNAPSHOTversion>
   <name>demoname>
   <description>Demo project for Spring Bootdescription>

   <properties>
      <java.version>1.8java.version>
   properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.bootgroupId>
         <artifactId>spring-boot-starter-jooqartifactId>
      dependency>
      <dependency>
         <groupId>org.springframework.bootgroupId>
         <artifactId>spring-boot-starter-webartifactId>
      dependency>

      <dependency>
         <groupId>org.springframework.bootgroupId>
         <artifactId>spring-boot-devtoolsartifactId>
         <scope>runtimescope>
         <optional>trueoptional>
      dependency>
      <dependency>
         <groupId>mysqlgroupId>
         <artifactId>mysql-connector-javaartifactId>
         <scope>runtimescope>
      dependency>
      <dependency>
         <groupId>org.springframework.bootgroupId>
         <artifactId>spring-boot-starter-testartifactId>
         <scope>testscope>
         <exclusions>
            <exclusion>
               <groupId>org.junit.vintagegroupId>
               <artifactId>junit-vintage-engineartifactId>
            exclusion>
         exclusions>
      dependency>
      

   dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-maven-pluginartifactId>
         plugin>
         <plugin>
            <groupId>org.jooqgroupId>
            <artifactId>jooq-codegen-mavenartifactId>
            <version>3.13.2version>
            <executions>
               <execution>
                  <goals>
                     <goal>generategoal>
                  goals>
               execution>
            executions>
            <dependencies>
               <dependency>
                  <groupId>mysqlgroupId>
                  <artifactId>mysql-connector-javaartifactId>
                  <version>8.0.20version>
               dependency>
            dependencies>
            <configuration>
                
               <configurationFile>src/main/resources/jooq.xmlconfigurationFile>
            configuration>
         plugin>
      plugins>
   build>

project>

springboot 整合JOOQ

官方给出的方法为在启动配置中添加

#src\main\resources\application.properties 
spring.jooq.sql-dialect=H2

代码生成器生成的dao不可直接使用,这是因为生成的代码中提供了两个dao构造器,其中一个

import org.jooq.Configuration;
import org.jooq.DSLContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository("authorDao")
public class AuthorDaoExt extends AuthorDao{
    @Autowired
    private DSLContext dsl;
    @Autowired
    public AuthorDaoExt(Configuration configuration) {
        super(configuration);
    }
//    @Autowired  当以这个构造器为spring 托管时会导致springboot的dataSource配置无法生效
//    public AuthorDaoExt() {
//        super();
//    }
}

JOOQ可扩展组件:https://www.jooq.org/doc/3.14/manual/getting-started/use-cases/jooq-for-pros/

JOOQ作为SQL构造器

import org.jooq.DSLContext;
import org.jooq.Query;
import org.jooq.SQLDialect;
import org.jooq.conf.ParamType;
import org.jooq.impl.DefaultDSLContext;
//静态导入
import static org.jooq.impl.DSL.field;
import static org.jooq.impl.DSL.table;


public class JOOQBuilder {
    private static DSLContext create = new DefaultDSLContext(SQLDialect.MYSQL);

    public static void main(String[] args) {
        //将JOOQ做为一个SQL构造器
        Query query = (Query)          create.select().from(table("AUTHOR")).where(field("AUTHOR.ID").eq("1"));
        //打印SQL,PreparedStatement SQL
         System.out.println(query.getSQL());
        //打印SQL
        System.out.println(query.getSQL(ParamType.INLINED));
    }


}

连接数据库

import org.jooq.*;
import org.jooq.impl.DefaultDSLContext;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import static  com.*.jooqdemo.dao.Tables.*;

public class JOOQConnter {
    private static DSLContext create;
    private static Connection connection;
    static {
        //基于JDBC创建数据库连接
        final String userName ="root";
        final String password ="*****";
        final String url ="jdbc:mysql://localhost:3306/jooq?serverTimezone=UTC";
        //Driver Conn

        try {
            connection =DriverManager.getConnection(url,userName,password);
            //需要注意,使用jdbc作为JOOQ数据库的连接方案时,连接的生命周期完全被交个用户自己管理,JOOQ不会介入连接的提交或事务回滚和关闭。
            //在实际的ee项目应用中通常会使用datasource作为数据库连接方案,
            // 此时JOOQ自身提供了org.jooq.impl.DataSourceConnectionProvider作为连接管理方案,此外也可以使用其他第三方管理工具
            create = new DefaultDSLContext(connection, SQLDialect.MYSQL);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

    }

    public static void main(String[] args) {
           if(create != null){
               SelectConditionStep query = create.select(AUTHOR.FIRST_NAME).from(AUTHOR).where(AUTHOR.ID.eq(1));
               System.out.println("执行脚本为:"+query.getSQL());
               System.out.println(query.getBindValues());
               //查询返回对象为result
               Result result=query.fetch();
               System.out.println(String.format("返回结果为:\n%s",result));
           }
        try {
            if (connection != null){
                connection.close();
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

    }

}

自定义JOOQ执行监听器

其作用类似与mybtais拦截器

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.time.Duration;
import java.time.LocalDateTime;

import static com.*.jooqdemo.dao.Tables.AUTHOR;

public class JOOQExecuteListener extends DefaultExecuteListener {
    private static DSLContext create;
    private static Connection connection;
    static {
        //基于JDBC创建数据库连接
        final String userName ="root";
        final String password ="*";
        final String url ="jdbc:mysql://localhost:3306/jooq?serverTimezone=UTC";
        //Driver Conn

        try {

            connection = DriverManager.getConnection(url,userName,password);

            Configuration configuration = new DefaultConfiguration().set(connection).set(SQLDialect.MYSQL);
            //注册自定义执行监听器
            //ExecuteListeners are a useful tool to...
            //
            //implement custom logging 自定义日志
            //apply triggers written in Java  添加触发器开关
            //collect query execution statistics 执行信息统计
            configuration.set(new DefaultExecuteListenerProvider(new JOOQExecuteListener()));
            create = new DefaultDSLContext(configuration);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

    }
    public static void main(String[] args) {
        if(create != null){
            SelectConditionStep query =          create.select(AUTHOR.FIRST_NAME).from(AUTHOR).where(AUTHOR.ID.eq(1));
            Result result=query.fetch();
            System.out.println(String.format("返回结果为:\n%s",result));
        }
        try {
            if (connection != null){
                connection.close();
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

    }
    private LocalDateTime beginDate;
    private String executeSql ;
    @Override
    //示例代码用于统计SQL执行
    public void executeStart(ExecuteContext ctx) {
        System.out.println("++++开始执行++++++");
        beginDate = LocalDateTime.now();
        executeSql = ctx.query().getSQL();
        super.executeStart(ctx);
    }

    @Override
    public void executeEnd(ExecuteContext ctx) {
        super.executeEnd(ctx);
        Duration duration =  Duration.between(beginDate,LocalDateTime.now());
        System.out.println(String.format("%s执行时间为%d    ms",executeSql,duration.toMillis()));
    }
}

jooq 事务

jooq本身提供了事务管理的功能,同时也支持事务托管给第三方如spring.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import static com.*.jooqdemo.dao.tables.Author.AUTHOR;

public class JOOQTransactionDemo {

    private DSLContext create;
    private Connection connection;

    private DSLContext initDSL() {
        //基于JDBC创建数据库连接
        final String userName = "root";
        final String password = "*";
        final String url = "jdbc:mysql://localhost:3306/jooq?serverTimezone=UTC";
        //Driver Conn

        try {

            connection = DriverManager.getConnection(url, userName, password);

            Configuration configuration = new DefaultConfiguration().set(connection).set(SQLDialect.MYSQL);
            create = new DefaultDSLContext(configuration);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return create;
    }

    public void transaction() {
        create.transaction(configuration1 -> {
            DSL.using(configuration1)
                    .insertInto(AUTHOR, AUTHOR.ID,AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)
                    .values(6,"George", "Orwell")
                    .returning()
                    .fetchOne();
            //发生异常 事务回滚
            throw new RuntimeException("异常");


        });


    }

    public static void main(String[] args) {
        JOOQTransactionDemo jooqTransactionDemo = new JOOQTransactionDemo();
        jooqTransactionDemo.initDSL();
        jooqTransactionDemo.transaction();
    }
}

many to many

/**
 * 返回当前作者名下的书籍
 * author 和 book为一对多关系
 * public class Author implements Serializable {
 *
 *     private static final long serialVersionUID = 223223344;
 *
 *     private Integer id;
 *     private String  firstName;
 *     private String  lastName;
 *     private List books;
 *     }
 * JOOQ本身并不没有提供many to many 和one to many的支持,但通过扩展Mapper可以实现这样的功能
 * https://www.petrikainulainen.net/programming/jooq/jooq-tips-implementing-a-read-only-   one-to-many-relationship/
 * @param id
 * @return
 */

public com.*.jooq.demo.dao.tables.pojos.Author getAuthorBooks(int id){
    
    Stream<com.*.jooq.demo.dao.tables.pojos.Author> stream = null;
    JdbcMapper<com.*.jooq.demo.dao.tables.pojos.Author> jdbcMapper = = JdbcMapperFactory.newInstance().addKeys("id","books").newMapper(com.*.jooq.demo.dao.tables.pojos.Author.class);
    try {
         Author a = Author.AUTHOR.as("a");
         Book b = Book.BOOK.as("b");
         ResultSet resultSet       =dslContext.select(a.ID.as("id"),a.FIRST_NAME.as("first_name"),
                 a.LAST_NAME.as("last_name"),b.ID.as("books_id"),b.BOOK_NAME.as("books_book_name"),b.PUBLISH_DATE.as("books_publish_date"))
                 .from(a).join(b).on(a.ID.eq(b.AUTHOR_ID)).where(a.ID.eq(id)).fetchResultSet();
         stream = jdbcMapper.stream(resultSet);
    } catch (SQLException throwables) {
        throwables.printStackTrace();
    }
   return  stream.collect(Collectors.toList()).get(0);
}

你可能感兴趣的:(orm,java)