ORM “杀器”之 JOOQ

ORM “杀器”之 JOOQ

JOOQ是啥?

JOOQ 是基于Java访问关系型数据库的工具包,轻量,简单,并且足够灵活,可以轻松的使用Java面向对象语法来实现各种复杂的sql。对于写Java的码农来说ORMS再也熟悉不过了,不管是Hibernate或者Mybatis,都能简单的使用实体映射来访问数据库。但有时候这些 ‘智能’的对象关系映射又显得笨拙,没有直接使用原生sql来的灵活和简单,而且对于一些如:joins,union, nested selects等复杂的操作支持的不友好。JOOQ 既吸取了传统ORM操作数据的简单性和安全性,又保留了原生sql的灵活性,它更像是介于 ORMS和JDBC的中间层。对于喜欢写sql的码农来说,JOOQ可以完全满足你控制欲,可以是用Java代码写出sql的感觉来。就像官网说的那样 :

get back in control of your sql

maxwon_chuangtong

(图片来自http://www.jooq.org/)

 

这货有啥优点

JOOQ 目前在国内还是很小众,第一次听说这玩意还是通过stream 大神的推荐。对于从SSH成长起来的猿类来说,心里也会质疑 “这玩意用的人那么少,靠不靠谱” ,“会不会有很多坑要踩”。通过对着官方文档写了几个demo,顿时心生敬畏,一个念头冲到脑袋 ” 这东西一定会火”,于是果断在项目中使用。在使用过程中也会遇到各种小问题,通过帮助手册和DEMO都能最终解决。相对于Hibernate或者其他ORMS的,JOOQ的编程模式有很大不同,强大的Fluent API使用起来非常方便和流畅。现在我们的项目(MaxWon)使用JOOQ已经在生产环境运行了很长的一段时间,从来没花太多时间折腾在数据访问层上面。对于开发来说感受最深的就是这货真的很简单很灵活,正如文章标题那样,这是一个‘杀器’。下面是我总结的几点,个人愚见。

  • 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的入门使用方法。

环境
描述名称
平台 JDK 1.8
maven 3.3.9
JOOQ 3.7.3
RDS Mysql 5.7
mysql-connector 5.1.39

maven依赖配置如下:

 

代码生成

目前官方提供了通过java org.jooq.util.GenerationTool来生成映射代码,但过程还是有点繁琐,这里就不演示了。还好万能的maven插件帮助我们解决了这个问题。

配置目标数据库schema信息后运行

如果一切顺利的话,在项目目录下会看到JOOQ自动生成的代码

jooqgenrator

使用数据库的schema信息,JOOQ会自动生成对应的Java Record,这样就可以使用Record来操作对应的数据库和表,不需任何其他的关系映射配置。

下面展示使用JOOQ 增删改查的例子

首先根据mysql connection 信息构造DSLContext,然后使用它来对数据库进行增删改查操作。对于具体方法我就不解释了,懂一点sql我相信都应该能看懂。

上面例子可以窥探出JOOQ DSL 语法风格以及JOOQ的基本使用方法,通过代码可以so easy 的在脑子里映射出对应的sql语句,感觉就像直接写sql一样。但JOOQ和sql不同之处在于它保证了你写的sql语法正确性和类型安全,如果配上IDEA代码提示功能,那就更加完美了,再难写的sql只要 . 一下就会有完整的代码提示。

查看DSL类源码看以看到里面大概有14000多行代码,都是静态方法,里面包含JOOQ支持的各种DB操作。对于常用的的场景使用DSLContext一般都能满足需求,但是对于是一些复杂的需求,如创建一个临时表,column别名,table别名,schema 动态设置,就必须使用DSL来进行操作。

JOOQ最令人满意的就是在实际使用过程中解决问题的灵活性。下面将展示获取商品(prodcut)和商品评论(comment)总量逻辑。product 和comment 是通过product_id 关联。

直接上码

下面是原生sql的版本

通过上面代码的对比可以看出JOOQ既享受了Java封装带来的便捷又保留了原生sql的灵活。

集成数据源

目前流行的数据源DHCP和c3p0大家都很熟悉了,没啥讲的。我们的项目使用的是阿里的 Druid,它是一个用于实时查询和分析的高容错、高性能开源分布式系统,旨在快速处理大规模的数据,并能够实现快速查询和分析。下面就以Druid为例演示把数据源绑定到JOOQ中

添加maven依赖

还是上面的JOOQTest demo,只需要重写getDSLContext 方法

具体Druid配置可以参考官方文档。

事务

JOOQ 官方提供了 TransactionProvider 对事务的支持,只需要在创建DSLContext的时候设置一下。代码如下:

下面展示事务的使用

没错就这么简单,只需要把需要用事务的代码包在transaction里面,假如有异常发生,业务会自动回滚。需要注意一点的是必须使用configuration 重新构建context,要不然不会生效,这也是我为什么没有使用官方提供的事务管理器。正常的项目中一个业务需要组合若干个service 方法来完成,而官方提供的默认事务管理器就需要把所有业务写在一个方法中,这在实际应用中显然是不合理的。幸好JOOQ抽象了事务管理,这样我们就可以集成第三方的事务管理器。

以大家都熟悉的Spring事务管理器为例。添加依赖

 

 

集成完后 transaction 测试方法就可以这样写了

 

其他特性

JOOQ还有很多其他有意思的特性 如对其他语言的支持,数据导出,存储过程,JPA支持等等,感兴趣的可以参阅一下文档。说到文档,不得不说开发者对JOOQ的用心,简单、详细、美观是最直接的感受,并且还有丰富的demo示例,对于编程新手来说上手使用也是手到擒来。

下面我就抱砖引玉,通过demo简单介绍一下ExecuteListener 的使用。ExecuteListener 可以看作是一个JOOQ执行的观察者,它可以监控SQL执行的整个生命周期。并且可以通过执行上下文,做一些个性化的操作。下面SlowQueryListener类的作用就是收集sql执行过程的慢查询日志。

在初始化DSLContext 的时候把SlowQueryListener配置进去 代码如下:

执行时间超过1s的sql,会打印如下日志

 

写在最后

对于在国内占了大半边天的Hibernate/Mybatis,JOOQ还是一个小清新,很多人对它都还陌生。通过上面的简单介绍,也许对你有一点帮助。无论是强大的数据转换能力还是处理业务的灵活性,简洁性,都会带来一些不一样的体验。如果你已经厌倦了ORMS的开发模式,正好又接手一个新的项目,JOOQ也许是一个不错的选择。

 

作者信息

本文系力谱宿云 LeapCloud旗下MaxLeap团队_数据服务组 成员:马传林【原创】

– 力谱宿云 LeapCloud 首发 –

马传林,从事开发工作已经有多年。当前在MaxLeap数据服务组担任开发工程师,主要负责MaxWon服务器开发。

posted @ 2016-09-02 10:13  rj_bian  阅读(13469)  评论(0编辑  收藏  举报