JOOQ快速入门

JOOQ

1. JOOQ快速入门

环境配置:

Springboot 2.7.15

Jdk 8

Gradle 7.4.2

  • 步骤 1:创建 Spring Boot 项目,引入 JOOQ 依赖。

    首先引入JOOQ,配置build.gradle文件

    plugins {
        id 'java' // 使用 Java 插件,使项目成为 Java 项目
        id 'org.springframework.boot' version '2.7.15' // 使用 Spring Boot 插件,指定版本为 2.7.15
        id 'io.spring.dependency-management' version '1.0.15.RELEASE' // 使用 Spring 依赖管理插件,指定版本为 1.0.15.RELEASE
        id 'nu.studer.jooq' version '4.2' // 使用 JOOQ 插件,指定版本为 4.2
    }
    
    group = 'com.hzp' // 指定项目的 Group ID,通常用于唯一标识一个项目的组织或公司
    version = '0.0.1-SNAPSHOT' // 指定项目的版本号,用于区分不同版本的发布
    
    java {
        sourceCompatibility = '1.8' // 设置源代码和目标字节码的兼容性为 Java 8
    }
    
    repositories {
        mavenCentral() // 配置 Maven 中央仓库,用于获取项目依赖的库文件
    }
    
    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter' // 添加 Spring Boot 核心依赖,包含了开发 Web 应用所需的基本库和工具
        testImplementation 'org.springframework.boot:spring-boot-starter-test' // 添加 Spring Boot 测试依赖,用于编写单元测试
        implementation 'org.springframework.boot:spring-boot-starter-web' // 添加 Spring Boot Web 相关依赖,用于开发 Web 应用
        implementation 'org.springframework.boot:spring-boot-starter-jooq' // 添加 Spring Boot JOOQ 依赖,用于与数据库交互
        implementation group: 'mysql', name: 'mysql-connector-java', version: '8.0.33' // 添加 MySQL 数据库驱动依赖,用于连接和操作 MySQL 数据库
        jooqRuntime(group: 'mysql', name: 'mysql-connector-java', version: '8.0.33') // 添加 JOOQ 运行时依赖,用于在运行时执行 JOOQ 生成的代码
    }
    jooq {
        version = '3.12.3' // JOОQ 版本号
        edition = 'OSS' // 使用开源版本
    
        generateSchemaSourceOnCompilation = false // 不在编译期间自动生成 Schema 源码
    
        sample(sourceSets.main) { // 配置 JOОQ 代码生成器使用的样例
            jdbc {
                driver = 'com.mysql.cj.jdbc.Driver' // 数据库驱动类
                url = 'jdbc:mysql://localhost:3306/demo?currentSchema=baseuc-dev&useUnicode=true&characterEncoding=utf-8' // 数据库连接 URL
                user = 'root' // 数据库用户名
                password = 'root' // 数据库密码
            }
            generator {
                name = 'org.jooq.codegen.DefaultGenerator' // JOОQ 代码生成器的类名
                strategy {
                    name = 'org.jooq.codegen.DefaultGeneratorStrategy' // JOОQ 代码生成策略的类名
                }
                database {
                    inputSchema = 'demo' // 输入的数据库 Schema 名称,如果是Mysql那么输入数据库库名
                    outputSchema = 'hzp' // 生成的数据库 Schema 名称
                    includes = 'user | goods' // 包含的数据库表名称,多个表名使用竖线分隔
                }
    
                generate {
                    relations = true // 是否生成对应数据库表之间关系的代码
                    deprecated = false // 是否生成已过时(deprecated)的代码
                    records = true // 是否生成记录(Record)类代码
                    immutablePojos = true // 是否生成不可变(immutable)的 Plain Old Java Objects(POJOs)
                    fluentSetters = true // 是否为生成的代码启用流畅的 Setter 方法
    
                }
                target {
                    packageName = 'com.tcc.auth.infrastructure.dao' // 生成的代码包名
                }
            }
        }
    }
    
    tasks.named('test') {
        useJUnitPlatform()
    }
    

    配置日志文件,在resource文件夹下新建logback.xml文件,配置JOOQ输出SQL语句

    <configuration>
        <!-- 输出到控制台 -->
        <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
            </encoder>
        </appender>
        <!-- 配置 JOOQ 的日志级别为 DEBUG -->
        <logger name="org.jooq.tools.LoggerListener" level="DEBUG"/>
        <!-- 根据需要指定其他 logger -->
        <!-- 根 logger -->
        <root level="INFO">
            <appender-ref ref="CONSOLE"/>
        </root>
    </configuration>
    
  • 步骤 2:配置数据库连接,包括数据库驱动、URL、用户名和密码等。

    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
        username: root
        password: root
        driver-class-name: com.mysql.cj.jdbc.Driver
        hikari:
          connection-timeout: 10000
          validation-timeout: 3000
          idle-timeout: 500000
          max-lifetime: 500000
          maximum-pool-size: 10
          minimum-idle: 5
    
  • 步骤 3:生成代码,使用 JOOQ 自动生成实体类和查询接口。

    点击jooq生成工具,生成实体类

    在这里插入图片描述

  • 步骤 4:编写简单的 CRUD 操作,演示 JOOQ 的基本用法。

    创建一个UserService接口,编写简易方法,获取数据库中所有内容

    public interface UserService {
    /**
         * 获取所有的用户
         * @return
         */
        public List<User> getAllUsers();
    }
    

    创建UserServiceImpl实现类

    @Service
    public class UserServiceImpl implements UserService{
        @Resource
        DSLContext dsl;
    
        @Override
        public List<User> getAllUsers() {
            //JOOQ使用类似于SQL语句的方式进行查询
            Result<Record> fetch = dsl.select().from(USER).fetch();
            //使用`into(xxx.class)`可以将返回的Record类型转换成所需要的类型
            List<User> userList = fetch.into(User.class);
            return userList;
        }
    }
    
    

    编写测试类

    @Test
    void getAllUsersTest() {
        List<User> allUsers = userService.getAllUsers();
        allUsers.forEach(System.out::println);
    }
    
  • 步骤 5:运行项目,验证功能是否正常。

    在这里插入图片描述

    项目运行正常

2. 基础CRUD

2.1 查询

  • 基本查询:介绍 JOOQ 的基本,包括选择字段、条件过滤、排序等。

    • 根据字段查询

      • 查询id相同的用户

        首先在接口内创建根据ID查找用户的方法

        /**
         * 根据ID获取用户
         * @return
         */
        public User getUserById(Long id);
        

        实现类实现该方法

        @Override
        public User getUserById(Long id) {
            return dsl.selectFrom(USER).where(USER.ID.eq(id)).fetchOne().into(User.class);
        }
        

        编写测试类进行测试

        @Test
        void getUsersByIDTest() {
            User userById = userService.getUserById(1684830092908216322L);
            System.out.println(userById);//User (1684830092908216322, abc, 123, null)
        }
        
      • 条件过滤

        在接口内创建一个查询Email为空的用户的方法

        /**
         * 获取所有Email为空的用户
         * @return
         */
        public List<User> getAllUsersWithoutEmail();
        

        实体类实现该方法

        @Override
            public List<User> getAllUsersWithoutEmail() {
                List<User> userList = dsl.selectFrom(USER).where(USER.EMAIL.isNull()).fetch().into(User.class);
                return userList;
            }
        

        编写测试类进行测试

        @Test
            void getAllUsersWithoutEmailTest(){
                List<User> allUsersWithoutEmail = userService.getAllUsersWithoutEmail();
                allUsersWithoutEmail.forEach(System.out::println);
            }
        
      • 排序

        接口新建一个方法,实现根据ID进行排序,从小到大

        /**
         * 返回结果根据ID大小排序
         * @return
         */
        public List<User> getAllUsersOrderByID();
        

        编写实现类

        @Override
        public List<User> getAllUsersOrderByID() {
            Result<UserRecord> fetch = dsl.selectFrom(USER).orderBy(USER.ID.asc()).fetch();
            List<User> userList = fetch.into(User.class);
            return userList;
        }
        

        编写测试类进行测试

        @Test
        void getAllUsersOrderByIDTest(){
            List<User> allUsersOrderByID = userService.getAllUsersOrderByID();
            allUsersOrderByID.forEach(System.out::println);
        }
        
  • 连接查询:演示如何进行多表连接查询。

    接口新建方法,根据用户id返回用户拥有的商品

    /**
     * 返回用户所拥有的所有货品
     * @return
     */
    public List<Goods> getGoodsByUserId();
    

    编写实现类

    @Override
    public List<Goods> getGoodsByUserId(Long userId) {
        // 通过DSLContext对象执行查询并获取结果集
        Result<Record> fetch = dsl.select(GOODS.fields()) // 选择GOODS表中的所有列作为查询结果
                .from(USER) // 指定查询的主表为USER表
                .join(GOODS) // 进行USER表和GOODS表的连接操作
                .on(USER.ID.eq(GOODS.USER_ID)) // 指定连接条件,即USER表的ID与GOODS表的USER_ID相等
                .where(USER.ID.eq(userId)) // 添加查询条件,筛选USER表中ID等于给定userId的记录
                .fetch(); // 执行查询并获取结果集
    
        // 将结果集映射到Goods对象列表
        List<Goods> goodsList = fetch.into(Goods.class); // 将Result<Record>对象转换为List<Goods>对象,映射规则为按照字段名与属性名进行对应
    
        return goodsList; // 返回查询结果
    }
    

    编写测试类

    @Test
        void getGoodsByUserIdTest(){
            List<Goods> goodsByUserId = userService.getGoodsByUserId(1684093012058025986L);
            goodsByUserId.forEach(System.out::println);
        }
    
  • 聚合函数和分组:使用 JOOQ 进行聚合函数查询和分组操作。

    接口新建一个方法,统计用户有多少件商品

    /**
     * 统计用户有多少件商品
     * @return
     */
     HashMap<String,Integer> getGoodsCountGroupByUser();
    

    实现类实现方法

    @Override
    public HashMap<String, Integer> getGoodsCountGroupByUser() {
        /*
        dsl.select(USER.USER_NAME, count(GOODS.ID)):选择要查询的列,即用户姓名和商品数量(使用聚合函数count统计商品ID出现的次数)。
        .from(USER):指定要查询的表是USER。
        .leftJoin(GOODS).on(USER.ID.eq(GOODS.USER_ID)):通过左连接将USER表与GOODS表连接起来,连接条件是USER.ID等于GOODS.USER_ID,这样可以关联每个用户所拥有的商品。
        .groupBy(USER.USER_NAME):按照USER.USER_NAME进行分组,这样可以得到每个用户对应的商品数量。
        .fetch():执行查询并获取结果。
         */
        Result<Record2<String, Integer>> fetch = dsl.select(USER.USER_NAME, count(GOODS.ID))
                .from(USER)
                .leftJoin(GOODS).on(USER.ID.eq(GOODS.USER_ID))
                .groupBy(USER.USER_NAME)
                .fetch();
    
    
        HashMap<String, Integer> result = new HashMap<>();
        for (Record2<String, Integer> record : fetch) {
            String s = record.get(USER.USER_NAME);
            Integer integer = record.get(count());
            result.put(s,integer);
        }
        return result;
    }
    

    编写测试类

    @Test
    void getGoodsCountGroupByUser(){
        HashMap<String, Integer> goodsCountGroupByUser = userService.getGoodsCountGroupByUser();
        goodsCountGroupByUser.forEach((s, integer) -> System.out.println("UserName:" + s + ",GoodsNum:" + integer));
    }
    

2.2 插入

接口新增方法,插入用户

/**
 * 插入用户
 * @param user
 */
 void addUser(User user);

实现类实现该方法

@Override
public void addUser(User user) {
    dsl.insertInto(USER)
            .set(USER.ID,user.getId())
            .set(USER.USER_NAME, user.getUserName())
            .set(USER.EMAIL, user.getEmail())
            .set(USER.PASSWORD, user.getPassword())
            .execute();
}

测试类测试

@Test
void addUserTest(){
    User user = new User(18L,"TCC","123456","688@qq.com");
    userService.addUser(user);
}

2.3 更新

接口创建方法,更新user

/**
 * 更新用户
 * @param user
 */
 void updateUser(User user);

实体类实现该方法

@Override
public void updateUser(User user) {
    dsl.update(USER)
            .set(USER.USER_NAME, user.getUserName())
            .set(USER.EMAIL, user.getEmail())
            .set(USER.PASSWORD, user.getPassword())
            .where(USER.ID.eq(user.getId())) // 根据用户ID进行更新
            .execute();
}
  • 对于 INSERTUPDATE 操作,.execute() 返回一个表示受影响的行数的整数值。该值表示成功执行操作后所影响的数据库记录行数。
  • 对于 DELETE 操作,.execute() 同样返回一个表示受影响的行数的整数值,表示成功删除的数据库记录行数。

编写测试类测试

@Test
void updateUserTest(){
    User user = new User(18L,"TCC","156","688@qq.com");
    userService.updateUser(user);
}

2.4 删除

接口创建方法,删除user

/**
 * id删除用户
 * @param id
 */
 void deleteUserById(Long id);

实体类实现该方法

@Override
public void deleteUserById(Long id) {
    dsl.deleteFrom(USER)
            .where(USER.ID.eq(id)) // 根据用户ID进行删除
            .execute();
}

编写测试类测试

@Test
void deleteUserTest(){
    userService.deleteUserById(0L);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值