jooq映射原理_JOOQ事实:从JPA批注到JOOQ表映射
jooq映射原理
JOOQ是一個簡潔的框架,它解決了我在使用高級動態(tài)過濾查詢時遇到的一個長期問題。 盡管Hibernate和JPA附帶了一個有用的Criteria API(我已經(jīng)使用了很長一段時間),但是您可以使用這些API進行操作有一些可以理解的限制。 例如,您不能超出簡單SQL操作(例如,JOINS,NESTED SLECTS,AGGREGATION)并執(zhí)行類似的操作: 窗口函數(shù) , 用戶定義的函數(shù)或簡單的排序等 。
JOOQ不想和Hibernate競爭,但我覺得它可以完成它。 我一直在將Hibernate用于數(shù)據(jù)層的WRITE部分,因此使用它的名稱或JPA中的“ Persisting”部分。 對于簡單到中等復雜的查詢,Hibernate會盡力而為,但是我不必僅依靠它來進行所有查詢,是嗎? 查詢屬性還有一個缺點,這是因為有時為了僅針對少數(shù)用例進行查詢,有時必須向域模型添加關聯(lián)。
因此,由于我不怕編寫本機查詢,因此可以以DSL方式和獨立于供應商的方式來執(zhí)行此操作。
盡管可以使用基于字符串的列命名,但JOOQ通過使用類型安全的元數(shù)據(jù)提供了一種更好的方法,因此,我們要做的第一件事是為數(shù)據(jù)庫架構生成表映射。
由于我已經(jīng)有了JPA模型,因此可以從中生成數(shù)據(jù)庫模式DDL,為此,我們可以使用hibernatetool ant任務。
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-antrun-plugin</artifactId><executions><execution><id>generate-test-sql-scripts</id><phase>generate-test-resources</phase><goals><goal>run</goal></goals><configuration><tasks><property name="maven_test_classpath" refid="maven.test.classpath"/><path id="hibernate_tools_path"><pathelement path="${maven_test_classpath}"/></path><property name="hibernate_tools_classpath" refid="hibernate_tools_path"/><taskdef name="hibernatetool"classname="org.hibernate.tool.ant.HibernateToolTask"/><mkdir dir="${project.build.directory}/test-classes/hsqldb"/><hibernatetool destdir="${project.build.directory}/test-classes/hsqldb"><classpath refid="hibernate_tools_path"/><jpaconfiguration persistenceunit="testPersistenceUnit"propertyfile="src/test/resources/META-INF/spring/jdbc.properties"/><hbm2ddl drop="false" create="true" export="false"outputfilename="create_db.sql"delimiter=";" format="true"/><hbm2ddl drop="true" create="false" export="false"outputfilename="drop_db.sql"delimiter=";" format="true"/></hibernatetool></tasks></configuration></execution></executions><dependencies><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-entitymanager</artifactId><version>${hibernate.version}</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-tools</artifactId><version>${hibernate.tools.version}</version><exclusions><exclusion><groupId>org.hibernate</groupId><artifactId>hibernate-commons-annotations</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>${slf4j.version}</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version>${slf4j.version}</version></dependency></dependencies> </plugin>這將生成一個“ create_db.sql”數(shù)據(jù)庫DDL腳本,我們將使用“ maven.sql.plugin”將其用于填充基于文件的臨時HSQLDB。 我本來希望使用內(nèi)存中的HSQLDB,但不幸的是它沒有保存插件執(zhí)行之間的狀態(tài)。
<plugin><groupId>org.codehaus.mojo</groupId><artifactId>sql-maven-plugin</artifactId><dependencies><dependency><groupId>org.hsqldb</groupId><artifactId>hsqldb</artifactId><version>${hsqldb.version}</version></dependency></dependencies><configuration><driver>org.hsqldb.jdbc.JDBCDriver</driver><url>jdbc:hsqldb:file:${project.build.directory}/hsqldb/db;shutdown=true</url><username>sa</username><password></password><autocommit>true</autocommit><settingsKey>hsql-db-test</settingsKey></configuration><executions><execution><id>create-test-compile-data</id><phase>process-test-resources</phase><inherited>true</inherited><goals><goal>execute</goal></goals><configuration><orderFile>ascending</orderFile><fileset><basedir>${project.build.directory}/test-classes/hsqldb/</basedir><includes><include>create_db.sql</include></includes></fileset><autocommit>true</autocommit></configuration></execution></executions> </plugin>因此,現(xiàn)在用我們的JPA生成的模式填充了HSQLDB,我們最終可以調(diào)用JOOQ代碼生成來構建表映射。
<plugin><groupId>org.jooq</groupId><artifactId>jooq-codegen-maven</artifactId><executions><execution><phase>process-test-classes</phase><goals><goal>generate</goal></goals></execution></executions><dependencies><dependency><groupId>org.hsqldb</groupId><artifactId>hsqldb</artifactId><version>${hsqldb.version}</version></dependency></dependencies><configuration><jdbc><driver>org.hsqldb.jdbc.JDBCDriver</driver><url>jdbc:hsqldb:file:${project.build.directory}/hsqldb/db</url><user>sa</user><password></password></jdbc><generator><name>org.jooq.util.JavaGenerator</name><database><name>org.jooq.util.hsqldb.HSQLDBDatabase</name><includes>.*</includes><excludes></excludes><inputSchema>PUBLIC</inputSchema></database><generate></generate><target><packageName>vladmihalcea.jooq.schema</packageName><directory>target/generated-sources/jooq</directory></target></generator></configuration> </plugin>通過maven運行,我們生成了表映射,因此讓我們將Image類的JPA元模型與關聯(lián)的JOOQ表映射進行比較:
JPA元模型如下所示:
@StaticMetamodel(Image.class) public abstract class Image_ {public static volatile SingularAttribute<Image, Product> product;public static volatile SingularAttribute<Image, Long> id;public static volatile SetAttribute<Image, Version> versions;public static volatile SingularAttribute<Image, Integer> index;public static volatile SingularAttribute<Image, String> 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<vladmihalcea.jooq.schema.tables.records.ImageRecord> {private static final long serialVersionUID = 1596930978;/*** The singleton instance of <code>PUBLIC.IMAGE</code>*/public static final vladmihalcea.jooq.schema.tables.Image IMAGE = new vladmihalcea.jooq.schema.tables.Image();/*** The class holding records for this type*/@Overridepublic java.lang.Class<vladmihalcea.jooq.schema.tables.records.ImageRecord> getRecordType() {return vladmihalcea.jooq.schema.tables.records.ImageRecord.class;}/*** The column <code>PUBLIC.IMAGE.ID</code>. */public final org.jooq.TableField<vladmihalcea.jooq.schema.tables.records.ImageRecord, java.lang.Long> ID = createField("ID", org.jooq.impl.SQLDataType.BIGINT.nullable(false), this);/*** The column <code>PUBLIC.IMAGE.INDEX</code>. */public final org.jooq.TableField<vladmihalcea.jooq.schema.tables.records.ImageRecord, java.lang.Integer> INDEX = createField("INDEX", org.jooq.impl.SQLDataType.INTEGER, this);/*** The column <code>PUBLIC.IMAGE.NAME</code>. */public final org.jooq.TableField<vladmihalcea.jooq.schema.tables.records.ImageRecord, java.lang.String> NAME = createField("NAME", org.jooq.impl.SQLDataType.VARCHAR.length(255), this);/*** The column <code>PUBLIC.IMAGE.PRODUCT_ID</code>. */public final org.jooq.TableField<vladmihalcea.jooq.schema.tables.records.ImageRecord, java.lang.Long> PRODUCT_ID = createField("PRODUCT_ID", org.jooq.impl.SQLDataType.BIGINT, this);/*** Create a <code>PUBLIC.IMAGE</code> table reference*/public Image() {super("IMAGE", vladmihalcea.jooq.schema.Public.PUBLIC);}/*** Create an aliased <code>PUBLIC.IMAGE</code> table reference*/public Image(java.lang.String alias) {super(alias, vladmihalcea.jooq.schema.Public.PUBLIC, vladmihalcea.jooq.schema.tables.Image.IMAGE);}/*** {@inheritDoc}*/@Overridepublic org.jooq.Identity<vladmihalcea.jooq.schema.tables.records.ImageRecord, java.lang.Long> getIdentity() {return vladmihalcea.jooq.schema.Keys.IDENTITY_IMAGE;}/*** {@inheritDoc}*/@Overridepublic org.jooq.UniqueKey<vladmihalcea.jooq.schema.tables.records.ImageRecord> getPrimaryKey() {return vladmihalcea.jooq.schema.Keys.SYS_PK_10059;}/*** {@inheritDoc}*/@Overridepublic java.util.List<org.jooq.UniqueKey<vladmihalcea.jooq.schema.tables.records.ImageRecord>> getKeys() {return java.util.Arrays.<org.jooq.UniqueKey<vladmihalcea.jooq.schema.tables.records.ImageRecord>>asList(vladmihalcea.jooq.schema.Keys.SYS_PK_10059, vladmihalcea.jooq.schema.Keys.UK_OQBG3YIU5I1E17SL0FEAWT8PE);}/*** {@inheritDoc}*/@Overridepublic java.util.List<org.jooq.ForeignKey<vladmihalcea.jooq.schema.tables.records.ImageRecord, ?>> getReferences() {return java.util.Arrays.<org.jooq.ForeignKey<vladmihalcea.jooq.schema.tables.records.ImageRecord, ?>>asList(vladmihalcea.jooq.schema.Keys.FK_9W522RC4D0KFDKQ390IHV92GB);}/*** {@inheritDoc}*/@Overridepublic vladmihalcea.jooq.schema.tables.Image as(java.lang.String alias) {return new vladmihalcea.jooq.schema.tables.Image(alias);} }現(xiàn)在,我們還需要使Maven意識到我們新生成的JOOQ元數(shù)據(jù)類,以便它可以在下一個測試編譯階段對其進行編譯。
<plugin><groupId>org.codehaus.mojo</groupId><artifactId>build-helper-maven-plugin</artifactId><executions><execution><id>add-source</id><phase>process-test-sources</phase><goals><goal>add-test-source</goal></goals><configuration><sources><source>${project.build.directory}/generated-sources/java</source></sources></configuration></execution></executions> </plugin>現(xiàn)在,我可以開始玩JOOQ了。 讓我們將DSLContext添加到我們的Spring應用程序上下文中:
<bean id="jooqContext" class="org.jooq.impl.DSL" factory-method="using"><constructor-arg ref="dataSource"/><constructor-arg value="#{T(org.jooq.SQLDialect).HSQLDB}"/> </bean我們將編寫一個測試來檢查一切是否正常:
private List<ImageProductDTO> getImageProductDTOs_JOOQ() {return transactionTemplate.execute(new TransactionCallback<List<ImageProductDTO>>() {@Overridepublic List<ImageProductDTO> 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模塊中來重構現(xiàn)有解決方案。 您可以在此單獨的模塊中生成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映射原理
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結
以上是生活随笔為你收集整理的jooq映射原理_JOOQ事实:从JPA批注到JOOQ表映射的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Ansoft Maxwell 永磁体表面
- 下一篇: 微软亚洲研究院:NLP将迎来黄金十年
