使用jOOQ代替Mybatis(一)
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是比较强大的工具,这里先简单介绍一下使用,下一篇稍微深入介绍一下
