最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析Java數(shù)據(jù)庫操作工具包jOOQ的使用

 更新時間:2024年04月03日 14:44:03   作者:磊磊落落  
jOOQ?是一個輕量級的?Java?ORM(對象關系映射)框架,可用來構建復雜的?SQL?查詢,這篇文章主要來和大家介紹一下jOOQ的使用,需要的可以參考下

jOOQ 是一個輕量級的 Java ORM(對象關系映射)框架,可用來構建復雜的 SQL 查詢。jOOQ 可以根據(jù)數(shù)據(jù)庫表自動生成對應的 Java 類,且字段類型與數(shù)據(jù)庫一一對應,減少了 SQL 注入的風險。

本文即是對 jOOQ 的初探,包括四個部分:準備數(shù)據(jù)庫和測試數(shù)據(jù)、jOOQ Java 代碼生成、jOOQ 初步使用,以及 jOOQ 與 Spring Boot 的集成。

開始各個部分前,列出本文涉及的各軟件版本:

Java:20(BellSoft LibericaJDK)

Maven:3.9.2

MySQL:8.1.0

jOOQ:3.18.6

Spring Boot:3.1.3

1 準備數(shù)據(jù)庫、表和測試數(shù)據(jù)

探索 jOOQ 的使用之前,需要有一個數(shù)據(jù)庫和幾張表。學生課程系統(tǒng)就是一個不錯的業(yè)務場景,既接近實際又涉及連表等復雜查詢,很適合用來作演示學習。

本文為學生課程系統(tǒng)創(chuàng)建了一個 school 數(shù)據(jù)庫,并在其下創(chuàng)建了三張表 student(學生表)、course(課程表)和 score(成績表)。

如下為完整的建庫、建表和數(shù)據(jù)插入語句:

-- 創(chuàng)建數(shù)據(jù)庫 school
DROP DATABASE IF EXISTS school;
CREATE DATABASE school DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

-- 使用數(shù)據(jù)庫 school
USE school;

-- 創(chuàng)建學生表
DROP TABLE IF EXISTS student;
CREATE TABLE student (
  no INT NOT NULL,                   -- 編號
  name VARCHAR(20) NOT NULL,         -- 姓名
  gender ENUM('男', '女') NOT NULL,  -- 性別
  birthday DATETIME,                 -- 出生日期
  CONSTRAINT PRIMARY KEY (no)        -- 編號為主鍵
);

-- 為學生表插入數(shù)據(jù)
INSERT INTO student VALUES
  (1, '閆浩然', '男', '1999-09-01'),
  (2, '肖雪', '女', '2000-03-21'),
  (3, '張如意', '女', '2001-08-08');

-- 創(chuàng)建課程表
DROP TABLE IF EXISTS course;
CREATE TABLE course (
  no INT NOT NULL,             -- 編號
  name VARCHAR(20) NOT NULL,   -- 名稱
  CONSTRAINT PRIMARY KEY (no)  -- 編號為主鍵
);

-- 為課程表插入數(shù)據(jù)
INSERT INTO course VALUES
  (1, '語文'),
  (2, '數(shù)學'),
  (3, '英語');

-- 創(chuàng)建成績表
DROP TABLE IF EXISTS score;
CREATE TABLE score (
  student_no INT NOT NULL,                                     -- 學生編號
  course_no INT NOT NULL,                                      -- 課程編號
  degree DECIMAL(4, 1) NOT NULL,                               -- 分數(shù)
  CONSTRAINT PRIMARY KEY (student_no, course_no),              -- 學生編號與課程編號為聯(lián)合主鍵
  CONSTRAINT FOREIGN KEY (student_no) REFERENCES student(no),  -- 學生編號為外鍵
  CONSTRAINT FOREIGN KEY (course_no) REFERENCES course(no)     -- 課程編號為外鍵
);

-- 為成績表插入數(shù)據(jù)
INSERT INTO score VALUES
  (1, 1, 90.5),
  (1, 2, 88.0),
  (1, 3, 98.0),
  (2, 1, 78.5),
  (2, 2, 68.0),
  (2, 3, 93.0),
  (3, 1, 83.0),
  (3, 2, 94.5),
  (3, 3, 73.0);

2 jOOQ Java 代碼生成

該部分嘗試用 jOOQ Maven 插件(jooq-codegen-maven)的方式來生成 Java 代碼。

本文使用的是在本地搭建的 MySQL 數(shù)據(jù)庫,將第一部分的 SQL 語句在數(shù)據(jù)庫執(zhí)行后,即可以嘗試使用 jOOQ Maven 插件來生成 Java 代碼了(主要是表相關的 Java 類和 POJO 類)。

插件jooq-codegen-maven在 Maven 配置文件pom.xml中的配置信息如下:

<plugin>
    <groupId>org.jooq</groupId>
    <artifactId>jooq-codegen-maven</artifactId>
    <version>${jooq.version}</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <jdbc>
            <driver>com.mysql.cj.jdbc.Driver</driver>
            <url>jdbc:mysql://localhost:3306/school</url>
            <user>root</user>
            <password>root</password>
        </jdbc>
        <generator>
            <generate>
                <pojos>true</pojos>
            </generate>
            <database>
                <includes>.*</includes>
                <inputSchema>school</inputSchema>
            </database>
            <target>
                <packageName>com.leileiluoluo.jooq.model.generated</packageName>
                <directory>src/main/java</directory>
            </target>
        </generator>
    </configuration>
</plugin>

然后,使用如下命令生成 Java 代碼:

mvn clean generate-sources

可以看到,代碼被生成到了src/main/java文件夾下的com.leileiluoluo.jooq.model.generated包下。

3 jOOQ 初步使用

使用 jOOQ 的一個主要目的可能是想借力其豐富的 SQL 構造能力。

下面即會使用 jOOQ 以及在第二部分生成的 Java 代碼(主要是表相關的類和 POJO 類)來實現(xiàn)一些常用的查詢。

如下即是使用 jOOQ 來查詢所有 Student 的一段示例代碼:

import com.leileiluoluo.jooq.model.generated.tables.pojos.Student;
import org.jooq.DSLContext;
import org.jooq.SQLDialect;
import org.jooq.impl.DSL;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.List;

import static com.leileiluoluo.jooq.model.generated.Tables.STUDENT;

public class JOOQSimpleQueryTest {

    public static void main(String[] args) {
        String username = "root";
        String password = "root";
        String url = "jdbc:mysql://localhost:3306/school";

        try (Connection conn = DriverManager.getConnection(url, username, password)) {
            DSLContext context = DSL.using(conn, SQLDialect.MYSQL);

            List<Student> students = context.selectFrom(STUDENT)
                    .fetchInto(Student.class);

            students.forEach(student -> {
                System.out.printf("no: %s, name: %s, gender: %s, birthday: %s\n", student.getNo(), student.getName(), student.getGender(), student.getBirthday());
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

可以看到,上面這段代碼首先使用DriverManager.getConnection(url, username, password);來創(chuàng)建了一個數(shù)據(jù)庫連接;然后使用DSL.using(conn, SQLDialect.MYSQL);來創(chuàng)建了DSLContext對象;然后即可以用DSLContext來像寫 SQL 語句一樣(context.selectFrom(STUDENT).fetchInto(Student.class);)來拼裝查詢語句了,查詢結果會自動轉換為 POJO 類的類型,非常方便快捷。

程序運行結果如下:

no: 1, name: 閆浩然, gender: 男, birthday: 1999-09-01T00:00
no: 2, name: 肖雪, gender: 女, birthday: 2000-03-21T00:00
no: 3, name: 張如意, gender: 女, birthday: 2001-08-08T00:00

上面的示例針對的是單表查詢的情形,下面再看一下復雜查詢的拼裝:

DSLContext context = DSL.using(conn, SQLDialect.MYSQL);

List<Record3<String, String, BigDecimal>> studentCourseScores = context.select(
                STUDENT.NAME,
                COURSE.NAME,
                SCORE.DEGREE
        ).from(SCORE)
        .join(STUDENT).on(SCORE.STUDENT_NO.eq(STUDENT.NO))
        .join(COURSE).on(SCORE.COURSE_NO.eq(COURSE.NO))
        .fetch();

studentCourseScores.forEach(record -> {
    String studentName = record.getValue(STUDENT.NAME);
    String courseName = record.getValue(COURSE.NAME);
    BigDecimal degree = record.getValue(SCORE.DEGREE);
    System.out.printf("student: %s, course: %s, degree: %s\n", studentName, courseName, degree);
});

上面的查詢涉及三個表的連接,依然可以像寫 SQL 一樣來進行構造。

程序運行結果如下:

student: 張如意, course: 語文, degree: 83.0
student: 肖雪, course: 語文, degree: 78.5
student: 閆浩然, course: 語文, degree: 90.5
student: 張如意, course: 數(shù)學, degree: 94.5
student: 肖雪, course: 數(shù)學, degree: 68.0
student: 閆浩然, course: 數(shù)學, degree: 88.0
student: 張如意, course: 英語, degree: 73.0
student: 肖雪, course: 英語, degree: 93.0
student: 閆浩然, course: 英語, degree: 98.0

其對應的 SQL 語句如下:

SELECT
    s.name,
    c.name,
    sc.degree
FROM score sc
JOIN student s
    ON sc.student_no=s.no
JOIN course c
    ON sc.course_no=c.no;

通過這兩段示例程序,即可以看到 jOOQ 的使用非常的簡單。針對單表的查詢,可以直接將結果映射到 POJO 類;對于多表連接等復雜查詢,拼裝起來也并不復雜,且結果可以轉換為一個多值的類RecordN<?, ?, ?, ...>。

4 jOOQ 與 Spring Boot 的集成

第三部分的示例僅適用于本地測試的情形,對于實際的項目,還需要考慮其如何與框架進行集成。

該部分即會探索 jOOQ 與 Spring Boot 的集成,主要會探索兩個方面:DSLContext的自動創(chuàng)建、DAO 層的封裝。

4.1 DSLContext 的自動創(chuàng)建

在 Spring Boot 中使用 jOOQ 時,DSLContext如何進行創(chuàng)建,這些交給spring-boot-starter-jooq就可以了,我們依然在application.xml采用通用的數(shù)據(jù)庫配置即可,DSLContext會由 Spring 容器自動創(chuàng)建,我們只需在需要的地方進行自動注入就可以了。

# application.yaml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/school
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
// StudentDao.java
@Service
public class StudentDaoImpl implements StudentDao {

    @Autowired
    private DSLContext context;

}

4.2 DAO 層的封裝

雖然 jOOQ 也支持自動生成 DAO 層,但其生成的 DAO 層代碼比較泛化,有很多方法可能根本就用不著。所以,經(jīng)過調研后,本人決定僅使用其構建 SQL 的能力(以及自動生成的表相關的類和 POJO 類),DAO 層還是根據(jù)業(yè)務情形自己來實現(xiàn)比較好一些。

如下即是為 Student 查詢設計的 StudentDao 的示例代碼:

// StudentDao.java
package com.leileiluoluo.jooq.dao;

import com.leileiluoluo.jooq.model.generated.tables.pojos.Student;

import java.util.List;
import java.util.Optional;

public interface StudentDao {

    Integer countAll();

    List<Student> listAll();

    List<Student> listWithPagination(int offset, int limit);

    Optional<Student> getByNo(Integer no);

    void save(Student record);

    void update(Student record);

    void deleteByNo(Integer no);

}
// StudentDaoImpl.java
package com.leileiluoluo.jooq.dao.impl;

import com.leileiluoluo.jooq.dao.StudentDao;
import com.leileiluoluo.jooq.model.generated.tables.pojos.Student;
import org.jooq.DSLContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

import static com.leileiluoluo.jooq.model.generated.Tables.STUDENT;

@Service
public class StudentDaoImpl implements StudentDao {

    @Autowired
    private DSLContext context;

    @Override
    public Integer countAll() {
        return context.fetchCount(STUDENT);
    }

    @Override
    public List<Student> listAll() {
        return context.selectFrom(STUDENT)
                .fetchInto(Student.class);
    }

    @Override
    public List<Student> listWithPagination(int offset, int limit) {
        return context.selectFrom(STUDENT)
                .offset(offset)
                .limit(limit)
                .fetchInto(Student.class);
    }

    @Override
    public Optional<Student> getByNo(Integer no) {
        Student student = context.select()
                .from(STUDENT)
                .where(STUDENT.NO.eq(no))
                .fetchOneInto(Student.class);

        return Optional.ofNullable(student);
    }

    @Override
    public void save(Student student) {
        context.insertInto(STUDENT)
                .set(STUDENT.NO, student.getNo())
                .set(STUDENT.NAME, student.getName())
                .set(STUDENT.GENDER, student.getGender())
                .set(STUDENT.BIRTHDAY, student.getBirthday())
                .execute();
    }

    @Override
    public void update(Student student) {
        context.update(STUDENT)
                .set(STUDENT.NAME, student.getName())
                .set(STUDENT.GENDER, student.getGender())
                .set(STUDENT.BIRTHDAY, student.getBirthday())
                .where(
                        STUDENT.NO.eq(student.getNo())
                )
                .execute();
    }

    @Override
    public void deleteByNo(Integer no) {
        context.deleteFrom(STUDENT)
                .where(
                        STUDENT.NO.eq(no)
                ).execute();
    }

}

可以看到,增、刪、改、查都有了,基本滿足了實際業(yè)務中的需要;在其上設計 Service 和 Controller 即可以實現(xiàn)真實的 REST 業(yè)務需求了。

綜上,本文準備了一些測試數(shù)據(jù),探索了 jOOQ 的代碼生成和 SQL 構建能力,最后還思考了其與 Spring Boot 的集成??傮w來看,jOOQ 還是比較易用的,是一個不錯的 MyBatis 或 Hibernate 替代方案。

以上就是淺析Java數(shù)據(jù)庫操作工具包jOOQ的使用的詳細內容,更多關于Java jOOQ數(shù)據(jù)庫操作工具包的資料請關注腳本之家其它相關文章!

相關文章

最新評論

鹿邑县| 隆尧县| 玉环县| 临沧市| 荔浦县| 晋城| 梁河县| 洱源县| 镇康县| 德江县| 荆州市| 许昌市| 武陟县| 梅州市| 息烽县| 定南县| 牡丹江市| 金湖县| 博客| 辽阳市| 银川市| 万宁市| 金坛市| 共和县| 双峰县| 长阳| 黄梅县| 淅川县| 托里县| 万源市| 阳泉市| 洪湖市| 遂宁市| 土默特左旗| 桐柏县| 榆林市| 资阳市| 汉中市| 武穴市| 肥乡县| 依安县|