JOOQ是个啥?作为开发者的我来说从来没用过甚至没听过,还是来到了这家公司才听到并且用到了这个ORM框架,用了这么久来浅浅评测一下JOOQ。

这是他的官网:JOOQ官网,号称是可以不用写SQL的ORM框架,我们先来看一段他究竟是个什么样的风格:
java
create.select(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, count())
.from(AUTHOR)
.join(BOOK).on(AUTHOR.ID.equal(BOOK.AUTHOR_ID))
.where(BOOK.LANGUAGE.eq("DE"))
.and(BOOK.PUBLISHED.gt(date("2008-01-01")))
.groupBy(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)
.having(count().gt(5))
.orderBy(AUTHOR.LAST_NAME.asc().nullsFirst())
.limit(2)
.offset(1)
没错,这就是一个SQL!一个纯Java风格的一个sql,可以直接写在service层的java代码
上手困难
当时作者接手这个项目的时候研究了好久,前期非常的痛苦,因为很多的sql你都得找到JOOQ的书写方式,然而网上关于它的资料非常非常少,甚至都没几个开发知道他的存在,没想到出师未捷身先死,sql都知道写了,但是不知道怎么写出来,然后就去问GPT,但是GPT给出的都是都是原生的JOOQ,而我们公司是进过一层自己的封装的。那没办法,只得问同事,有时候同事甚至也不知道,最后没辙,一条SQL可以写出来的查询,非要通过Java代码多查询几次数据库,用java给结果拼接到一起。

↑ 同事的吐槽
影响开发效率
就像上一条说的,明明一条sql可以写出来的查询,非要拆成几条简单的JOOQ用java组装。而且为了一个写法要拼命的找到对应的JOOQ,非常影响开发效率。最让人啼笑皆非的是,在工位上无意发现了上一个离职的同事写的一句话,短短几个字,把我们现同事笑得前仰后合。(特别是划掉的那两个字)

不能写SQL
没错,你想写都写不了,不像mybatis那样可以在xml文件里面写sql,导致你熟悉的sql技能在这个框架中被一刀砍掉了。哪怕你写了十年的sql,在jooq上面,你还是要从0学习他的语法,把你会的sql转换为jooq语法
优点
但是,你要说JOOQ一无是处吗?我想不是的,作者用久了之后习惯了觉得没那么差,甚至有同事很喜欢JOOQ。例如下面这位(还说出了公司的JOOQ是世界上最好用的ORM框架):

出错概率小
我们平时写mybatis的时候,sql写在xml里面,有时候字段错了或者少打了个空格,或者参数没绑定对,结果都是报错,害得项目运行起来报错才察觉到。
但是JOOQ不会,毕竟是用纯java写的,因为都是在IDEA编译期间进行的检查,如果你哪个字段错了IDEA就会立马标红,项目都运行不起来。

更优雅
不可否认的是如果你的查询条件很简单的话你直接使用JOOQ可能更简单,特别是加上AI编程插件,直接全部自动补全了,甚至1s钟写一个sql!!而如果是mybatis的化又需要在mapper层加方法,在xml中写sql,写参数绑定。
java
public List<ExamRegistExpand> assignedList(List<String> examJoinRoomIds) {
return examRegistExpandCommonDao.execute(e -> e.select(
EXAM_REGIST_EXPAND.ID, EXAM_REGIST_EXPAND.EXAM_JOIN_ROOM_ID, EXAM_REGIST_EXPAND.IS_ARRANGE_FLAG
)
.from(EXAM_REGIST_EXPAND)
.where(EXAM_REGIST_EXPAND.EXAM_JOIN_ROOM_ID.in(examJoinRoomIds))
.fetchInto(ExamRegistExpand.class));
}
如果是mybatis的化代码就会是这样的:
java
<select id="assignedList" resultType="com.example.model.ExamRegistExpand">
SELECT id, exam_join_room_id, is_arrange_flag
FROM exam_regist_expand
WHERE exam_join_room_id IN
<foreach item="examJoinRoomId" index="index" collection="list"
open="(" separator="," close=")">
#{examJoinRoomId}
</foreach>
</select>
public interface ExamRegistExpandMapper {
List<ExamRegistExpand> assignedList(@Params("list") List<String> examJoinRoomIds);
}
public List<ExamRegistExpand> getAssignedList(List<String> examJoinRoomIds) {
return examRegistExpandMapper.assignedList(examJoinRoomIds);
}
嗯,好像确实很优雅,直接在service层里面写了,少了一个mapper层(虽然有点破坏mvc规范)
更自由
可以在构造返回结果里面进行格外的操作:

如果是mybatis的话有两种方法实现这种功能:通过mysql的函数直接构建,但是会有局限,例如只能做简单的转换,甚至如果不是用的是mysql的化都不支持这样的。第二种方式就是使用java代码在返回的类中通过for循环来修改里面的内容。
但是JOOQ直接通过上面这样优雅且 自由的代码编写方式来实现格式的转换(不仅限图中的案例)。
