使用jOOQ代替Mybatis(一)

发表于2020-01-18,长度3283, 524个单词, 9分钟读完
Flag Counter

jooq是老外提供的函数式SQL解决方案。目标是减少开发人员在SQL设计上的时间,让我们能把更多时间放在业务逻辑的编写上。不管是使用mybatis还是hibernate,都不能完美解决每个方面:hibernate能让我们的开发变得智能,mybatis能让我们利用原生SQL的强大:它们彼此的优势都是对方最大的劣势。jooq将它们的能力进行了折中,这里我们简单学习一下。

预备:移除mybatis依赖

如果你的项目本来就没有使用其他ORM框架,这里就不用处理了。

如果之前使用了mybatis,需要把相关依赖、代码生成、分页扩展等都移除。可以参考《使用Mybatis-plus代替原生Mybatis》。

增加jooq依赖

把下面三个坐标都加入:

<dependency>
    <groupId>org.jooq</groupId>
    <artifactId>jooq</artifactId>
    <version>3.9.6</version>
</dependency>
<dependency>
    <groupId>org.jooq</groupId>
    <artifactId>jooq-meta</artifactId>
    <version>3.9.6</version>
</dependency>
<dependency>
    <groupId>org.jooq</groupId>
    <artifactId>jooq-codegen</artifactId>
    <version>3.9.6</version>
</dependency>

这是开源版的坐标,jooq还提供了专业版的依赖,不过是收费的,而且也不在maven中心库

使用jooq生成sql

这是jooq提供的一个基础功能,但是不一定常用,这里简单演示一下。

首先引入org.jooq.DSLContext:

@Autowired
private DSLContext create;

为什么能引入呢?因为spring-boot已经帮我们封装好了:

org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration.DslContextConfiguration#jooqConfiguration

如果不能通过IoC拿到,可以先创建connection对象:java.sql.DriverManager#getConnection(java.lang.String, java.lang.String, java.lang.String),然后使用DSL.using(connection, SQLDialect.MYSQL)拿到

然后执行类似如下的代码即可:

String sql = create.select(field("BOOK.TITLE"), field("AUTHOR.FIRST_NAME"), field("AUTHOR.LAST_NAME"))
        .from(table("BOOK"))
        .join(table("AUTHOR"))
        .on(field("BOOK.AUTHOR_ID").eq(field("AUTHOR.ID")))
        .where(field("BOOK.PUBLISHED_IN").eq(1948))
        .getSQL();
System.out.println(sql);

输出结果是:

select BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME from BOOK join AUTHOR on BOOK.AUTHOR_ID = AUTHOR.ID where BOOK.PUBLISHED_IN = ?

这是将jooq作为SQL构建器使用,作用就是将生产的sql文本传给其他中间件,如hibernate、jdbc等直接使用。并且使用了变量绑定。

使用jooq执行sql

既然能生产sql,当然也能执行sql。将生成语句中的getSQL()方法换成fetch()即可:

Result<Record3<Object, Object, Object>> fetch = create.select(field("BOOK.TITLE"), field("AUTHOR.FIRST_NAME"), field("AUTHOR.LAST_NAME"))
        .from(table("BOOK"))
        .join(table("AUTHOR"))
        .on(field("BOOK.AUTHOR_ID").eq(field("AUTHOR.ID")))
        .where(field("BOOK.PUBLISHED_IN").eq(1948))
        .fetch();
System.out.println(fetch);

如果命中记录,输出比较个性:

+----------+-----------------+----------------+
|BOOK.TITLE|AUTHOR.FIRST_NAME|AUTHOR.LAST_NAME|
+----------+-----------------+----------------+
|1984      |George           |Orwell          |
+----------+-----------------+----------------+

和mysql自带客户端差不多。

除了执行生成的SQL,还可以直接执行字符串:

Result<Record> fetch = create.fetch("update book_to_book_store set stock = stock + 1 where book_id = 4");
System.out.println(fetch);

这个么有返回结果,打印出来是:

+
|
+

如果已经通过JDBC拿到了ResultSet结果,也可以通过jooq获取:

ResultSet rs = ...; // = connection.createStatement().executeQuery("");
create.fetch(rs);

如果想拿到返回记录的某个字段:

Result<Record3<Object, Object, Object>> fetch = create.select(field("BOOK.TITLE"), field("AUTHOR.FIRST_NAME"), field("AUTHOR.LAST_NAME"))
        .from(table("BOOK"))
        .join(table("AUTHOR"))
        .on(field("BOOK.AUTHOR_ID").eq(field("AUTHOR.ID")))
        .where(field("BOOK.PUBLISHED_IN").eq(1948))
        .fetch();

for (Record r : fetch) {
    System.out.println(r.getValue(field("BOOK.TITLE")));
}

这样可以拿到title字段。

总结

jooq是比较强大的工具,这里先简单介绍一下使用,下一篇稍微深入介绍一下

Written on January 18, 2020
分类: dev, 标签: java database
如果你喜欢,请赞赏! davelet