JOOQ是什么

     Jooq(Java Object Oriented Querying)java面向对象查询,是一种ORM框架,轻量,简单并且足够灵活。对于写Java的码农来说ORMS再也熟悉不过了,不管是Hibernate或者Mybatis,都能简单的使用实体映射来访问数据库。但有时候这些对象关系映射又显得笨拙,没有直接使用原生sql来的灵活和简单,而且对于一些复杂的操作支持的不友好。JOOQ 既吸取了传统ORM操作数据的简单性和安全性,又保留了原生sql的灵活性,它更像是介于 ORMS和JDBC的中间层。对于喜欢写sql的码农来说,JOOQ可以完全满足你控制欲,可以是用Java代码写出sql的感觉来。就像官网说的那样 :get back in control of your sql。【jOOQ generates Java code from your database and lets you build type safe SQL queries through its fluent API.】

JOOQ的优点,通过官网和一些文章总结优点如下:

1.代码够简单和清晰。遇到不会写的sql可以充分利用IDEA代码提示功能轻松完成。

2.保留了传统ORM 的优点,简单操作性,安全性,类型安全等。不需要复杂的配置,并且可以利用Java 8 Stream API 做更加复杂的数据转换。

3.支持主流的RDMS和更多的特性,如self-joins,union,存储过程,复杂的子查询等等。

4.丰富的Fluent API和完善文档。

5.runtime schema mapping 可以支持多个数据库schema访问。简单来说使用一个连接池可以访问N个DB schema,使用比较多的就是SaaS应用的多租户场景。

与原生SQL比较
原生sql语句:

SELECT TITLE
FROM BOOK
WHERE BOOK.PUBLISHED_IN = 2011
ORDER BY BOOK.TITLE
SELECT AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, COUNT(*)
FROM AUTHOR
JOIN BOOK ON AUTHOR.ID = BOOK.AUTHOR_ID
WHERE BOOK.LANGUAGE = 'DE'
AND BOOK.PUBLISHED > DATE '2008-01-01'
GROUP BY AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME
HAVING COUNT(*) > 5
ORDER BY AUTHOR.LAST_NAME ASC NULLS FIRST
LIMIT 2
OFFSET 1

jooq语法:

create.select(BOOK.TITLE).from(BOOK).where(BOOK.PUBLISHED_IN.eq(2011)).orderBy(BOOK.TITLE)
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)

简单的初步demo:

import org.jooq.Condition;
import org.jooq.DSLContext;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SelectQuery;
import org.jooq.Table;
import org.jooq.UpdateQuery;
import org.jooq.impl.DSL;import com.dfb.jooq.datapool.BoneCpPool;
import com.jolbox.bonecp.BoneCP;/*** @desc: 简单的增删改查* @name: JooqDao.java* @author: tompai* @email:liinux@qq.com* @createTime: 2019年12月17日 下午7:43:29* @history:* @version: v1.0*/
public class JooqDao {private DSLContext dslContext= null;//获取DSLContext对象private DSLContext getdslContext(){BoneCP boneCP = BoneCpPool.getBoneCP();Connection connection = BoneCpPool.getConnection(boneCP);dslContext = DSL.using(connection);return dslContext;}//简单实体查询public void select(String add){DSLContext getdslContext = getdslContext();Table<Record> table = DSL.table("shangfox_user");SelectQuery<Record> selectQuery = getdslContext.selectQuery(table);//获取查询对象Condition eq = DSL.field("username").eq(add);//查询条件selectQuery.addConditions(eq);//添加查询条件Result<Record> fetch = selectQuery.fetch();for (Object aResult : fetch) {Record record = (Record) aResult;System.out.println(record);System.out.println(record.getValue("username"));}}//实体更新public void update(String name){DSLContext getdslContext = getdslContext();Table<Record> table = DSL.table("shangfox_user");UpdateQuery<Record> updateQuery = getdslContext.updateQuery(table);//获取更新对象updateQuery.addValue(DSL.field("email"), "new-email");//更新email字段的值为new-emailCondition eq = DSL.field("username").eq(name);//更新username为name的email字段updateQuery.addConditions(eq);int execute = updateQuery.execute();System.out.println(execute);select("shangfox1");}//原生态的sql查询public void getVal(){DSLContext getdslContext = getdslContext();Table<Record> table = DSL.table("shangfox_wish");//表名Result<Record> fetch = getdslContext.select().from(table).where("statu = 0").and("id > 4340").orderBy(DSL.field("time").asc()).fetch();for (Object aResult : fetch) {Record record = (Record) aResult;System.out.println(record);}/*Map<String, Object> fetchAnyMap = orderBy.fetchAnyMap();Set<String> keySet = fetchAnyMap.keySet();for(String s:keySet){System.out.println("key--"+s+"--val:"+fetchAnyMap.get(s));}*/}//验证DSL.exists方法public void exits(){DSLContext getdslContext = getdslContext();Condition condition = DSL.exists(DSL.select(DSL.field("username1")));Table<Record> table = DSL.table("shangfox_user");SelectQuery<Record> selectQuery = getdslContext.selectQuery(table);selectQuery.addConditions(condition);Result<Record> fetch = selectQuery.fetch();for (Object aResult : fetch) {Record record = (Record) aResult;System.out.println(record);System.out.println(record.getValue("username"));}}public static void main(String[] args) {JooqDao jooqDao = new JooqDao();
//        jooqDao.select("shangfox");
//        jooqDao.update("shangfox1");
//        jooqDao.exits();jooqDao.getVal();}
}

使用BoneCp数据库连接池:

BoneCP是一个Java数据库连接池库,官方介绍它的速度非常快,测试值高出C3P0、DBCP很多,性能也非常出色,值得一用。

  使用BoneCP有一些要求:

  1)Google Guava library

        2)The SLF4J logging library

  3)JDK1.5 or higher

import java.sql.Connection;
import java.sql.SQLException;import org.jooq.DSLContext;
import org.jooq.impl.DSL;import com.jolbox.bonecp.BoneCP;
import com.jolbox.bonecp.BoneCPConfig;/*** @desc: 连接池管理数据库连接* @name: BoneCpPool .java* @author: tompai* @email:liinux@qq.com* @createTime: 2019年12月17日 下午7:43:29* @history:* @version: v1.0*/
public class BoneCpPool {private static BoneCP boneCp = null;private static BoneCPConfig boneCPConfig = null;// 静态代码块加载配置文件static {// 加载JDBC驱动try {Class.forName("com.mysql.jdbc.Driver");// 注册数据库boneCPConfig = new BoneCPConfig();// bonecp数据库连接池配置String jdbcUrl = "jdbc:mysql://127.0.0.1:3306/wish";// jdbc:mysql://10.10.0.215:3306/che001boneCPConfig.setJdbcUrl(jdbcUrl);boneCPConfig.setUser("root");boneCPConfig.setPassword("tiger");// 数据库连接池的最小连接数boneCPConfig.setMinConnectionsPerPartition(5);// 数据库连接池的最大连接数boneCPConfig.setMaxConnectionsPerPartition(10);boneCPConfig.setPartitionCount(1);// System.out.println("boneCPConfig"+boneCPConfig);} catch (ClassNotFoundException e) {e.printStackTrace();}}// 获取连接池public static BoneCP getBoneCP() {try {boneCp = new BoneCP(boneCPConfig);} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}return boneCp;}// 获取连接public static Connection getConnection(BoneCP boneCpP) {if (boneCpP != null) {try {return boneCpP.getConnection();} catch (SQLException e) {return null;}} else {return null;}}// 关闭连接池public static void closeBoneCP(BoneCP bc) {bc.close();}// 关闭连接public static void closeConnection(Connection con) throws SQLException {con.close();}//public static DSLContext getContext(Connection conDsl) {return DSL.using(conDsl);}
}