初步了解JOOQ并实现简单 - - - CRUD(一)

个人博客网:wushaopei.com  

一、 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

JOOQ的优点

相对于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应用的多租户场景。

二、示例

SQL语句:

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  

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)

三、创建数据库

我们要创建一个名为library的数据库,和一个author表,在表中插入zhang3,li4数据。

DATABASE `library`;

USE `library`;

CREATE TABLE `author` (
  `id` int NOT NULL,
  `first_name` varchar(255) DEFAULT NULL,
  `last_name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

INSERT INTO `author` (`id`, `first_name`, `last_name`) VALUES ('1', '3', 'zhang'), ('2', '4', 'li');

四、添加MAVEN依赖

① 添加 JOOQ 依赖

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

②添加 mysql 数据库驱动依赖 (根据连接的数据库而定)

 <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.41</version>
      </dependency>

五 、映射生成 author类的java类

这里,要使用jOOQ的命令行工具生成映射到author表的Java类。

代码生成的最简单的方法是将jOOQ的3个jar文件和MySQL Connector jar文件复制到一个临时目录(本示例中目录是test-generated), 然后创建一个如下所示的library.xml(名字随意修改)

目录结构:

library.xml配置文件内容:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<configuration xmlns="http://www.jooq.org/xsd/jooq-codegen-3.9.2.xsd">
    <!-- Configure the database connection here -->
    <jdbc>
        <driver>com.mysql.jdbc.Driver</driver>
        <!-- 数据库url -->
        <url>jdbc:mysql://localhost:3306/library?useUnicode=true&amp;characterEncoding=UTF-8</url>
        <!-- 数据库账号 -->
        <user>root</user>
        <!-- 数据库账号密码 -->
        <password>root</password>
    </jdbc>

    <generator>
        <!-- The default code generator. You can override this one, to generate your own code style.
             Supported generators:
             - org.jooq.util.JavaGenerator
             - org.jooq.util.ScalaGenerator
             Defaults to org.jooq.util.JavaGenerator -->
        <name>org.jooq.util.JavaGenerator</name>

        <database>
            <!-- The database type. The format here is:
                 org.util.[database].[database]Database -->
            <name>org.jooq.util.mysql.MySQLDatabase</name>

            <!-- The database schema (or in the absence of schema support, in your RDBMS this
                 can be the owner, user, database name) to be generated -->
            <inputSchema>library</inputSchema>

            <!-- All elements that are generated from your schema
                 (A Java regular expression. Use the pipe to separate several expressions)
                 Watch out for case-sensitivity. Depending on your database, this might be important! -->
            <includes>.*</includes>

            <!-- All elements that are excluded from your schema
                 (A Java regular expression. Use the pipe to separate several expressions).
                 Excludes match before includes, i.e. excludes have a higher priority -->
            <excludes></excludes>
        </database>

        <target>
            <!-- The destination package of your generated classes (within the destination directory) -->
            <!-- 生成的包名,生成的类在此包下 -->
            <packageName>test.generated</packageName>

            <!-- The destination directory of your generated classes. Using Maven directory layout here -->
            <!-- 输出的目录 -->
            <directory>J:\IDEA_Work_Space\maven_jooq_demo\src\main\java</directory>
        </target>
    </generator>
</configuration>

在Windows中,cdtest-generated目录,执行以下命令:

注意jar包的版本号与您本地对应上,在这个例子中,jOOQ使用3.9.5,MySQL使用5.1.41。

java -classpath jooq-3.9.5.jar;jooq-meta-3.9.5.jar;jooq-codegen-3.9.5.jar;mysql-connector-java-5.1.41.jar; org.jooq.util.GenerationTool library.xml

如果一切正常,您应该在控制台输出中看到这些信息:

并会生成如下java文件:

六、连接到你的数据库

在工程中编写一个测试类Main.java

package com.jooq.cn;

import org.jooq.DSLContext;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
import org.jooq.impl.DSL;

import java.sql.Connection;
import java.sql.DriverManager;

import static test.generated.tables.Author.AUTHOR;

public class Main {

    public static void main(String[] args) {

        //用户名
        String userName = "root";
        //密码
        String password = "root";
        //mysql链接url
        String url = "jdbc:mysql://localhost:3306/library";
        Connection conn;
        try {
             //这是JDBC Mysql连接
             conn = DriverManager.getConnection(url, userName, password); 
             //基于JOOQ实现的简单查询
             //传入Connection连接对象、数据方言得到一个DSLContext的实例,然后使用DSL对象查询得到一个Result对象。
            DSLContext using = DSL.using(conn, SQLDialect.MYSQL);
            Result<Record> fetch = using.select().from(AUTHOR).fetch();


            //for循环输出结果
            for (Record record : fetch) {
                Integer id = record.getValue(AUTHOR.ID);
                String firstName = record.getValue(AUTHOR.FIRST_NAME);
                String lastName = record.getValue(AUTHOR.LAST_NAME);
                /**
                 * 控制台输出
                 * ID: 1 first name: 3 last name: zhang
                 * ID: 2 first name: 4 last name: li
                 */
                System.out.println("ID:"+id + "firstName"+ firstName + "lastName: " + lastName);
            }
            //关闭连接
            conn.close();

        }catch (Exception e){
            e.printStackTrace();
        }

    }
}

注意:DSLContext不会主动关闭连接,需要我们手动关闭。

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  Thank you for using jOOQ 3.9.5
                                      
ID:1firstName3lastName: zhang
ID:2firstName4lastName: li

Process finished with exit code 0

GitHub

<think>好的,用户之前问过关于jOOQ实现通用CRUD的问题,现在又转向询问如何使用jOOQ操作达梦数据库。我需要先分析用户的需求。达梦数据库是国产的关系型数据库,用户可能在项目中需要适配国产化环境。用户可能已经熟悉jOOQ的基本操作,现在需要迁移到特定的数据库,因此需要了解配置和注意事项。 首先,我应该回顾jOOQ支持达梦的情况。记得jOOQ支持多种数据库,但达梦可能不在默认支持的方言中。需要确认jOOQ版本是否支持达梦的SQL方言。例如,达梦通常兼容Oracle或PostgreSQL,可能需要使用类似Oracle的方言配置。 接下来,用户可能需要配置DSLContext时选择正确的SQLDialect。比如使用SQLDialect.DEFAULT或者尝试ORACLE。同时,驱动类和连接字符串的配置也是关键,需要给出示例。 然后,考虑到jOOQ代码生成部分,用户需要使用达梦的JDBC驱动来生成代码。这里需要指导用户如何在pom.xml或gradle中配置依赖,以及生成器配置中的JDBC连接信息。 另外,达梦可能有特定的语法或数据类型与标准SQL不同,需要提醒用户注意这些差异,比如分页查询的写法、自增主键的处理,以及数据类型映射的问题。例如,达梦的分页可能使用Oracle的ROWNUM或者LIMIT/OFFSET,需要根据实际情况调整。 此外,事务管理和Spring集成也是用户可能关心的点,需要说明如何通过@Transactional注解管理事务,以及在Spring Boot中配置数据源和jOOQ的DSLContext。 还要考虑到用户可能遇到的具体问题,比如连接失败、SQL语法错误等,需要给出排查步骤,例如检查驱动版本、方言设置、网络连接等。 最后,总结最佳实践,帮助用户高效使用jOOQ操作达梦数据库,比如保持jOOQ版本更新、利用达梦的特性、调试SQL日志等。 整个过程中需要保持回答结构清晰,分步骤说明配置和注意事项,确保用户能够按照指导进行操作,避免常见问题。同时,代码示例要准确,特别是JDBC URL、驱动类名和生成器配置,这些是用户直接需要复制修改的部分。需要确认达梦的最新驱动版本,可能需要用户根据实际情况调整版本号。 还需要提醒用户,如果遇到特定的兼容性问题,可能需要自定义jOOQ的绑定或转换器来处理达梦特有的数据类型或函数。这部分可能需要更深入的配置,但作为初步指导,可以先提到常见的注意事项,复杂情况建议查阅官方文档或社区支持。 总之,回答需要覆盖配置步骤、代码生成、CRUD操作示例、常见问题解决和最佳实践,确保用户能够顺利在达梦数据库上使用jOOQ进行开发。</think>以下是使用jOOQ操作达梦数据库的详细指南: --- ### 、环境配置关键步骤 #### 1. 添加达梦JDBC驱动 ```xml <!-- pom.xml --> <dependency> <groupId>com.dameng</groupId> <artifactId>DmJdbcDriver</artifactId> <version>8.1.2.141</version> <!-- 根据实际版本调整 --> </dependency> ``` #### 2. 配置数据源 ```yaml # application.yml spring: datasource: url: jdbc:dm://localhost:5236/SAMPLE?schema=SYSDBA username: SYSDBA password: SYSDBA001 driver-class-name: dm.jdbc.driver.DmDriver ``` #### 3. 配置jOOQ方言 ```java @Bean public DSLContext dslContext(DataSource dataSource) { return DSL.using(dataSource, SQLDialect.DEFAULT); // 或显式指定 SQLDialect.DM 如果jOOQ已支持 } ``` --- ### 二、代码生成配置 ```xml <!-- jOOQ代码生成插件配置 --> <configuration> <jdbc> <driver>dm.jdbc.driver.DmDriver</driver> <url>jdbc:dm://localhost:5236/SAMPLE</url> <user>SYSDBA</user> <password>SYSDBA001</password> </jdbc> <generator> <database> <name>org.jooq.meta.dameng.DamengDatabase</name> <includes>.*</includes> <inputSchema>SYSDBA</inputSchema> </database> <generate> <daos>true</daos> </generate> </generator> </configuration> ``` --- ### 三、达梦特有语法处理 #### 1. 分页查询实现 ```java // 使用达梦的LIMIT/OFFSET语法 dsl.selectFrom(TABLE) .orderBy(TABLE.CREATE_TIME.desc()) .limit(10) .offset(20) .fetch(); ``` #### 2. 自增主键处理 ```java // 插入后获取自增ID(需表配置IDENTITY列) dsl.insertInto(USER, USER.NAME, USER.AGE) .values("张三", 25) .returning(USER.ID) .fetchOne() .getId(); ``` --- ### 四、事务管理示例 ```java @Transactional public void transferMoney(Long from, Long to, BigDecimal amount) { // 扣款 dsl.update(ACCOUNT) .set(ACCOUNT.BALANCE, ACCOUNT.BALANCE.subtract(amount)) .where(ACCOUNT.ID.eq(from)) .execute(); // 加款 dsl.update(ACCOUNT) .set(ACCOUNT.BALANCE, ACCOUNT.BALANCE.add(amount)) .where(ACCOUNT.ID.eq(to)) .execute(); } ``` --- ### 五、常见问题解决方案 #### 1. 连接失败排查 - 检查驱动版本与达梦数据库版本对应关系 - 确认端口号默认5236是否开放 - 验证SYSDBA账户密码策略 #### 2. SQL语法兼容问题 ```java // 达梦不支持ON DUPLICATE KEY UPDATE语法,改用merge dsl.mergeInto(USER) .using(DSL.dual()) .on(USER.ID.eq(123)) .whenMatchedThenUpdate() .set(USER.NAME, "李四") .whenNotMatchedThenInsert(USER.ID, USER.NAME) .values(123, "李四") .execute(); ``` #### 3. 数据类型映射 | 达梦类型 | jOOQ映射类型 | |---------------|------------------| | BIGINT | Long | | DECIMAL | BigDecimal | | VARCHAR | String | | TIMESTAMP | LocalDateTime | | BLOB | byte[] | --- ### 六、性能优化建议 1. **批量插入优化**: ```java dsl.batchInsert(records).execute(); // 自动使用达梦批量协议 ``` 2. **执行计划分析**: ```java // 启用SQL日志分析 Settings settings = new Settings() .withExecuteLogging(true); DSLContext dsl = DSL.using(dataSource, SQLDialect.DEFAULT, settings); ``` 3. **索引使用提示**: ```java dsl.select() .hint("/*+ INDEX(table_name index_name) */") .from(TABLE) .where(...) ``` --- ### 七、与Oracle模式差异处理 当达梦运行在Oracle兼容模式下时: ```java // 显式指定Oracle方言 DSLContext dsl = DSL.using(dataSource, SQLDialect.ORACLE); // 使用Oracle风格的DUAL表 dsl.select(DSL.val(1)).from(DSL.dual()).fetch(); ``` --- ### 八、监控与调试 1. 启用jOOQ日志: ```properties logging.level.org.jooq.tools.LoggerListener=DEBUG ``` 2. 使用达梦监控工具: ```sql -- 查看当前会话 SELECT * FROM V$SESSIONS; -- 分析SQL执行效率 EXPLAIN SELECT * FROM USER; ``` --- **最佳实践总结**: 1. 保持jOOQ版本 >= 3.16(对国产数据库支持更好) 2. 复杂存储过程建议使用原生JDBC调用 3. 定期使用达梦的`DBMS_STATS`包收集统计信息 4. 利用达梦的`DMHS`工具实现数据同步时,注意jOOQ版本兼容性
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值