JOOQ事実:JPAコメントからJOOQテーブルマッピングへ
JOOQは簡潔なフレームワークであり、高度なダイナミックフィルタクエリーを使用する際に発生する長期的な問題を解決します.HibernateとJPAには有用なCriteria APIが付属していますが(私は長い間使用しています)、それらを使用する際にできることには理解できる制限があります.たとえば、簡単なSQL操作(JOINS、NESTED SLECTS、AGGREGATIONなど)を超えてはいけません.ウィンドウ関数、ユーザー定義関数、簡単なソートなど、似たようなことをします.
JOOQはHibernateと競争したくありませんが、それを達成できると思います.私はずっとHibernateをデータ層のWRITE部分に使用しているので、その名前やJPAの「Persisting」部分を使用しています.単純から中程度の複雑なクエリーでは、Hibernateは最善を尽くしますが、私はそれだけですべてのクエリーを行う必要はありませんよね?クエリー・プロパティにも欠点があります.これは、少数のインスタンスのみをクエリーするために、ドメイン・モデルに関連付けを追加する必要がある場合があります.
したがって、ネイティブ・クエリーの作成は心配しないので、DSL方式とベンダーとは独立した方法で実行できます.
文字列ベースのカラム名を使用することもできますが、JOOQはタイプの安全なメタデータを使用することによってより良い方法を提供しています.そのため、私たちが最初にしなければならないことは、データベース・アーキテクチャのテーブル・マッピングを生成することです.
JPAモデルを持っているので、データベース・モードDDLを生成できます.そのため、hibernatetool antタスクを使用できます.
これにより、「create_db.sql」データベースDDLスクリプトが生成され、「maven.sql.plugin」を使用してファイルベースの一時HSQLDBを埋め込むことができます.メモリのHSQLDBを使いたかったのですが、残念ながらプラグイン実行間の状態は保存されていません.
したがって、HSQLDBは現在、我々のJPAによって生成されたアーキテクチャによって埋め込まれており、最終的にJOOQコード生成を呼び出してテーブルマッピングを構築することができる.
mavenで実行すると、テーブルマッピングが生成されるので、ImageクラスのJPAメタモデルと関連するJOOQテーブルマッピングを比較します.
JPAメタモデルは次のようになります.
JOOQテーブルとのマッピング
次に、次のテストコンパイル段階でコンパイルできるように、Mavenに新しく生成されたJOOQメタデータクラスを認識させる必要があります.
今、JOOQを始めることができます.SpringアプリケーションコンテキストにDSLContextを追加します.
すべてが正常かどうかを確認するテストを作成します.
次のSQLを生成
JOOQを使うのは初めてで、ドキュメントを閲覧するのに時間がかかりすぎてHibernate Facts符号化の例ですべての設定を行いました.JOOQクエリの構築は自然な感じで、ネイティブSQLコードを書くようなものなので、APIの使い方を本当に学ぶ必要はありません.Java Data Toolboxに追加することを誇りに思っています.
このエンコーディング例では、JOOQマッピングをtest-classesフォルダに生成するため、main/javaソースファイルでは使用できません.これは解決できますが、モデルクラスを個別のMavenモジュールに移動することで既存のソリューションを再構築する必要があります.この個別のモジュールでJOOQモードを生成できます.パッケージ化する前に、モードクラスをテストクラスからclassesフォルダに移動できます.次に、この新しいモジュールを含める必要があります.通常、JOOQモードを使用します.
参考:JOOQ事実:JPAコメントから私たちのJCGパートナーVlad MihalceaのVlad MihalceaブログブログのJOOQテーブルマッピングへ.
翻訳:https://www.javacodegeeks.com/2013/12/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html
JOOQはHibernateと競争したくありませんが、それを達成できると思います.私はずっとHibernateをデータ層のWRITE部分に使用しているので、その名前やJPAの「Persisting」部分を使用しています.単純から中程度の複雑なクエリーでは、Hibernateは最善を尽くしますが、私はそれだけですべてのクエリーを行う必要はありませんよね?クエリー・プロパティにも欠点があります.これは、少数のインスタンスのみをクエリーするために、ドメイン・モデルに関連付けを追加する必要がある場合があります.
したがって、ネイティブ・クエリーの作成は心配しないので、DSL方式とベンダーとは独立した方法で実行できます.
文字列ベースのカラム名を使用することもできますが、JOOQはタイプの安全なメタデータを使用することによってより良い方法を提供しています.そのため、私たちが最初にしなければならないことは、データベース・アーキテクチャのテーブル・マッピングを生成することです.
JPAモデルを持っているので、データベース・モードDDLを生成できます.そのため、hibernatetool antタスクを使用できます.
org.apache.maven.plugins
maven-antrun-plugin
generate-test-sql-scripts
generate-test-resources
run
org.hibernate
hibernate-entitymanager
${hibernate.version}
org.slf4j
slf4j-api
org.hibernate
hibernate-tools
${hibernate.tools.version}
org.hibernate
hibernate-commons-annotations
org.slf4j
slf4j-api
${slf4j.version}
org.slf4j
slf4j-simple
${slf4j.version}
これにより、「create_db.sql」データベースDDLスクリプトが生成され、「maven.sql.plugin」を使用してファイルベースの一時HSQLDBを埋め込むことができます.メモリのHSQLDBを使いたかったのですが、残念ながらプラグイン実行間の状態は保存されていません.
org.codehaus.mojo
sql-maven-plugin
org.hsqldb
hsqldb
${hsqldb.version}
org.hsqldb.jdbc.JDBCDriver
jdbc:hsqldb:file:${project.build.directory}/hsqldb/db;shutdown=true
sa
true
hsql-db-test
create-test-compile-data
process-test-resources
true
execute
ascending
${project.build.directory}/test-classes/hsqldb/
create_db.sql
true
したがって、HSQLDBは現在、我々のJPAによって生成されたアーキテクチャによって埋め込まれており、最終的にJOOQコード生成を呼び出してテーブルマッピングを構築することができる.
org.jooq
jooq-codegen-maven
process-test-classes
generate
org.hsqldb
hsqldb
${hsqldb.version}
org.hsqldb.jdbc.JDBCDriver
jdbc:hsqldb:file:${project.build.directory}/hsqldb/db
sa
org.jooq.util.JavaGenerator
org.jooq.util.hsqldb.HSQLDBDatabase
.*
PUBLIC
vladmihalcea.jooq.schema
target/generated-sources/jooq
mavenで実行すると、テーブルマッピングが生成されるので、ImageクラスのJPAメタモデルと関連するJOOQテーブルマッピングを比較します.
JPAメタモデルは次のようになります.
@StaticMetamodel(Image.class)
public abstract class Image_ {
public static volatile SingularAttribute product;
public static volatile SingularAttribute id;
public static volatile SetAttribute versions;
public static volatile SingularAttribute index;
public static volatile SingularAttribute name;
}
JOOQテーブルとのマッピング
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.2.0" },
comments = "This class is generated by jOOQ")
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class Image extends org.jooq.impl.TableImpl {
private static final long serialVersionUID = 1596930978;
/**
* The singleton instance of PUBLIC.IMAGE
*/
public static final vladmihalcea.jooq.schema.tables.Image IMAGE = new vladmihalcea.jooq.schema.tables.Image();
/**
* The class holding records for this type
*/
@Override
public java.lang.Class getRecordType() {
return vladmihalcea.jooq.schema.tables.records.ImageRecord.class;
}
/**
* The column PUBLIC.IMAGE.ID
.
*/
public final org.jooq.TableField ID = createField("ID", org.jooq.impl.SQLDataType.BIGINT.nullable(false), this);
/**
* The column PUBLIC.IMAGE.INDEX
.
*/
public final org.jooq.TableField INDEX = createField("INDEX", org.jooq.impl.SQLDataType.INTEGER, this);
/**
* The column PUBLIC.IMAGE.NAME
.
*/
public final org.jooq.TableField NAME = createField("NAME", org.jooq.impl.SQLDataType.VARCHAR.length(255), this);
/**
* The column PUBLIC.IMAGE.PRODUCT_ID
.
*/
public final org.jooq.TableField PRODUCT_ID = createField("PRODUCT_ID", org.jooq.impl.SQLDataType.BIGINT, this);
/**
* Create a PUBLIC.IMAGE
table reference
*/
public Image() {
super("IMAGE", vladmihalcea.jooq.schema.Public.PUBLIC);
}
/**
* Create an aliased PUBLIC.IMAGE
table reference
*/
public Image(java.lang.String alias) {
super(alias, vladmihalcea.jooq.schema.Public.PUBLIC, vladmihalcea.jooq.schema.tables.Image.IMAGE);
}
/**
* {@inheritDoc}
*/
@Override
public org.jooq.Identity getIdentity() {
return vladmihalcea.jooq.schema.Keys.IDENTITY_IMAGE;
}
/**
* {@inheritDoc}
*/
@Override
public org.jooq.UniqueKey getPrimaryKey() {
return vladmihalcea.jooq.schema.Keys.SYS_PK_10059;
}
/**
* {@inheritDoc}
*/
@Override
public java.util.List> getKeys() {
return java.util.Arrays.>asList(vladmihalcea.jooq.schema.Keys.SYS_PK_10059, vladmihalcea.jooq.schema.Keys.UK_OQBG3YIU5I1E17SL0FEAWT8PE);
}
/**
* {@inheritDoc}
*/
@Override
public java.util.List> getReferences() {
return java.util.Arrays.>asList(vladmihalcea.jooq.schema.Keys.FK_9W522RC4D0KFDKQ390IHV92GB);
}
/**
* {@inheritDoc}
*/
@Override
public vladmihalcea.jooq.schema.tables.Image as(java.lang.String alias) {
return new vladmihalcea.jooq.schema.tables.Image(alias);
}
}
次に、次のテストコンパイル段階でコンパイルできるように、Mavenに新しく生成されたJOOQメタデータクラスを認識させる必要があります.
org.codehaus.mojo
build-helper-maven-plugin
add-source
process-test-sources
add-test-source
${project.build.directory}/generated-sources/java
今、JOOQを始めることができます.SpringアプリケーションコンテキストにDSLContextを追加します.
すべてが正常かどうかを確認するテストを作成します.
private List getImageProductDTOs_JOOQ() {
return transactionTemplate.execute(new TransactionCallback>() {
@Override
public List doInTransaction(TransactionStatus transactionStatus) {
return jooqContext
.select(IMAGE.NAME, PRODUCT.NAME)
.from(IMAGE)
.join(PRODUCT).on(IMAGE.PRODUCT_ID.equal(PRODUCT.ID))
.where(PRODUCT.NAME.likeIgnoreCase("%tv%"))
.and(IMAGE.INDEX.greaterThan(0))
.orderBy(IMAGE.NAME.asc())
.fetch().into(ImageProductDTO.class);
}
});
}
次のSQLを生成
SELECT "PUBLIC"."image"."name",
"PUBLIC"."product"."name"
FROM "PUBLIC"."image"
JOIN "PUBLIC"."product"
ON "PUBLIC"."image"."product_id" = "PUBLIC"."product"."id"
WHERE ( Lower("PUBLIC"."product"."name") LIKE Lower('%tv%')
AND "PUBLIC"."image"."index" > 0 )
ORDER BY "PUBLIC"."image"."name" ASC
JOOQを使うのは初めてで、ドキュメントを閲覧するのに時間がかかりすぎてHibernate Facts符号化の例ですべての設定を行いました.JOOQクエリの構築は自然な感じで、ネイティブSQLコードを書くようなものなので、APIの使い方を本当に学ぶ必要はありません.Java Data Toolboxに追加することを誇りに思っています.
このエンコーディング例では、JOOQマッピングをtest-classesフォルダに生成するため、main/javaソースファイルでは使用できません.これは解決できますが、モデルクラスを個別のMavenモジュールに移動することで既存のソリューションを再構築する必要があります.この個別のモジュールでJOOQモードを生成できます.パッケージ化する前に、モードクラスをテストクラスからclassesフォルダに移動できます.次に、この新しいモジュールを含める必要があります.通常、JOOQモードを使用します.
参考:JOOQ事実:JPAコメントから私たちのJCGパートナーVlad MihalceaのVlad MihalceaブログブログのJOOQテーブルマッピングへ.
翻訳:https://www.javacodegeeks.com/2013/12/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html