1. 序章

このチュートリアルでは、 jOOQ (Javaオブジェクト指向クエリ)を使用してアプリケーションを実行するクイックツアーを行います。 このライブラリは、データベーステーブルに基づいてJavaクラスを生成し、流暢なAPIを介してタイプセーフなSQLクエリを作成できるようにします。

セットアップ全体、PostgreSQLデータベース接続、およびCRUD操作のいくつかの例について説明します。

2. Mavenの依存関係

jOOQライブラリの場合、次の3つのjOOQ依存関係が必要です。

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

PostgreSQLドライバーにも1つの依存関係が必要です。

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.2.16</version>
</dependency>

3. データベース構造

始める前に、例の簡単なDBスキーマを作成しましょう。 単純な作成者記事の関係を使用します。

create table AUTHOR
(
    ID         integer PRIMARY KEY,
    FIRST_NAME varchar(255),
    LAST_NAME  varchar(255),
    AGE        integer
);

create table ARTICLE
(
    ID          integer PRIMARY KEY,
    TITLE       varchar(255) not null,
    DESCRIPTION varchar(255),
    AUTHOR_ID   integer
        CONSTRAINT fk_author_id REFERENCES AUTHOR
);

4. データベース接続

それでは、データベース接続する方法を見てみましょう。

まず、ユーザー、パスワード、およびデータベースへの完全なURLを提供する必要があります。 これらのプロパティを使用して、DriverManagerとそのgetConnectionメソッドを使用して、Connectionオブジェクトを作成します。

String userName = "user";
String password = "pass";
String url = "jdbc:postgresql://db_host:5432/baeldung";
Connection conn = DriverManager.getConnection(url, userName, password);

次に、DSLContextのインスタンスを作成する必要があります。 このオブジェクトは、jOOQインターフェイスのエントリポイントになります。

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

この例では、 POSTGRES 方言を渡しますが、H2、MySQL、SQLiteなどの他の方言はほとんどありません。

5. コード生成

データベーステーブルのJavaクラスを生成するには、次のjooq-config.xmlファイルが必要です。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<configuration xmlns="http://www.jooq.org/xsd/jooq-codegen-3.13.0.xsd">
    
    <jdbc>
        <driver>org.postgresql.Driver</driver>
        <url>jdbc:postgresql://db_url:5432/baeldung_database</url>
        <user>username</user>
        <password>password</password>
    </jdbc>

    <generator>
        <name>org.jooq.codegen.JavaGenerator</name>

        <database>
            <name>org.jooq.meta.postgres.PostgresDatabase</name>
            <inputSchema>public</inputSchema>
            <includes>.*</includes>
            <excludes></excludes>
        </database>

        <target>
            <packageName>com.baeldung.jooq.model</packageName>
            <directory>C:/projects/baeldung/tutorials/jooq-examples/src/main/java</directory>
        </target>
    </generator>
</configuration>

カスタム構成では、変更が必要ですデータベースのクレデンシャルを配置するセクションと生成するクラスのパッケージ名と場所ディレクトリを構成するセクション。

jOOQコード生成ツールを実行するには、次のコードを実行する必要があります。

GenerationTool.generate(
  Files.readString(
    Path.of("jooq-config.xml")
  )    
);

生成が完了すると、次の2つのクラスが取得され、それぞれがデータベーステーブルに対応します。

com.baeldung.model.generated.tables.Article;
com.baeldung.model.generated.tables.Author;

6. CRUD操作

それでは、jOOQライブラリで実行できるいくつかの基本的なCRUD操作を見てみましょう。

6.1. 作成

まず、新しいArticleレコードを作成しましょう。 そのためには、適切なテーブル参照をパラメーターとして使用して、newRecordメソッドを呼び出す必要があります。

ArticleRecord article = context.newRecord(Article.ARTICLE);

Article.ARTICLE 変数は、ARTICLEデータベーステーブルへの参照インスタンスです。 これは、コード生成中にjOOQによって自動的に作成されました。

次に、必要なすべてのプロパティに値を設定できます。

article.setId(2);
article.setTitle("jOOQ examples");
article.setDescription("A few examples of jOOQ CRUD operations");
article.setAuthorId(1);

最後に、レコードに対して store メソッドを呼び出して、データベースに保存する必要があります。

article.store();

6.2. 読む

それでは、データベースから値を読み取る方法を見てみましょう。 例として、すべての作成者を選択しましょう。

Result<Record> authors = context.select()
  .from(Author.AUTHOR)
  .fetch();

ここでは、selectメソッドをfrom句と組み合わせて使用して、どのテーブルから読み取るかを示しています。 fetch メソッドを呼び出すと、SQLクエリが実行され、生成された結果が返されます。

ResultオブジェクトはIterableインターフェースを実装しているため、各要素を簡単に繰り返すことができます。 また、単一のレコードにアクセスしながら、適切なフィールド参照を指定して getValue メソッドを使用することにより、そのパラメーターを取得できます。

authors.forEach(author -> {
    Integer id = author.getValue(Author.AUTHOR.ID);
    String firstName = author.getValue(Author.AUTHOR.FIRST_NAME);
    String lastName = author.getValue(Author.AUTHOR.LAST_NAME);
    Integer age = author.getValue(Author.AUTHOR.AGE);

    System.out.printf("Author %s %s has id: %d and age: %d%n", firstName, lastName, id, age);
});

選択クエリを特定のフィールドのセットに制限できます。 記事IDとタイトルのみを取得してみましょう。

Result<Record2<Integer, String>> articles = context.select(Article.ARTICLE.ID, Article.ARTICLE.TITLE)
  .from(Author.AUTHOR)
  .fetch();

fetchOneメソッドを使用して単一のオブジェクトを選択することもできます。 これのパラメーターは、テーブル参照と適切なレコードに一致する条件です。

この例では、IDが1のAuthorを選択します。

AuthorRecord author = context.fetchOne(Author.AUTHOR, Author.AUTHOR.ID.eq(1))

条件に一致するレコードがない場合、fetchOneメソッドはnullを返します。

6.3. 更新

特定のレコードを更新するには、DSLContextオブジェクトからのupdateメソッドを、変更する必要のあるすべてのフィールドのsetメソッド呼び出しと組み合わせて使用できます。 このステートメントの後には、適切な一致条件を持つwhere句を続ける必要があります。

context.update(Author.AUTHOR)
  .set(Author.AUTHOR.FIRST_NAME, "David")
  .set(Author.AUTHOR.LAST_NAME, "Brown")
  .where(Author.AUTHOR.ID.eq(1))
  .execute();

更新クエリは、executeメソッドを呼び出した後にのみ実行されます。 戻り値として、更新されたレコードの数に等しい整数を取得します。

store メソッドを実行して、すでにフェッチされているレコードを更新することもできます。

ArticleRecord article = context.fetchOne(Article.ARTICLE, Article.ARTICLE.ID.eq(1));
article.setTitle("A New Article Title");
article.store();

store メソッドは、操作が成功した場合は 1 を返し、更新が不要な場合は0を返します。 たとえば、条件に一致するものはありませんでした。

6.4. 削除

特定のレコードを削除するには、[X43X]DSLContextオブジェクトからdeleteメソッドを使用できます。 削除条件は、次のwhere句のパラメーターとして渡す必要があります。

context.delete(Article.ARTICLE)
  .where(Article.ARTICLE.ID.eq(1))
  .execute();

削除クエリは、executeメソッドを呼び出した後にのみ実行されます。 戻り値として、削除されたレコードの数に等しい整数を取得します。

delete メソッドを実行して、すでにフェッチされているレコードを削除することもできます。

ArticleRecord articleRecord = context.fetchOne(Article.ARTICLE, Article.ARTICLE.ID.eq(1));
articleRecord.delete();

delete メソッドは、操作が成功した場合は 1 を返し、削除が不要な場合は0を返します。 たとえば、条件に一致するものがない場合です。

7. 結論

この記事では、jOOQフレームワークを使用して単純なCRUDアプリケーションを構成および作成する方法を学習しました。 いつものように、すべてのソースコードはGitHubで入手できます。