jooq映射原理

JOOQ是一个简洁的框架,它解决了我在使用高级动态过滤查询时遇到的一个长期问题。 尽管Hibernate和JPA附带了一个有用的Criteria API(我已经使用了很长一段时间),但是您可以使用这些API进行操作有一些可以理解的限制。 例如,您不能超出简单SQL操作(例如,JOINS,NESTED SLECTS,AGGREGATION)并执行类似的操作: 窗口函数 , 用户定义的函数或简单的排序等 。

JOOQ不想和Hibernate竞争,但我觉得它可以完成它。 我一直在将Hibernate用于数据层的WRITE部分,因此使用它的名称或JPA中的“ Persisting”部分。 对于简单到中等复杂的查询,Hibernate会尽力而为,但是我不必仅依靠它来进行所有查询,是吗? 查询属性还有一个缺点,这是因为有时为了仅针对少数用例进行查询,有时必须向域模型添加关联。

因此,由于我不怕编写本机查询,因此可以以DSL方式和独立于供应商的方式来执行此操作。

尽管可以使用基于字符串的列命名,但JOOQ通过使用类型安全的元数据提供了一种更好的方法,因此,我们要做的第一件事是为数据库架构生成表映射。

由于我已经有了JPA模型,因此可以从中生成数据库模式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”数据库DDL脚本,我们将使用“ maven.sql.plugin”将其用于填充基于文件的临时HSQLDB。 我本来希望使用内存中的HSQLDB,但不幸的是它没有保存插件执行之间的状态。

<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>

因此,现在用我们的JPA生成的模式填充了HSQLDB,我们最终可以调用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元模型与关联的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);}
}

现在,我们还需要使Maven意识到我们新生成的JOOQ元数据类,以便它可以在下一个测试编译阶段对其进行编译。

<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>

现在,我可以开始玩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模块中来重构现有解决方案。 您可以在此单独的模块中生成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映射原理

jooq映射原理_JOOQ事实:从JPA批注到JOOQ表映射相关推荐

  1. JOOQ事实:从JPA批注到JOOQ表映射

    JOOQ是一个简洁的框架,它解决了我在使用高级动态过滤查询时遇到的一个长期问题. 虽然Hibernate和JPA附带了一个有用的Criteria API(我已经使用了很长一段时间),但是使用它们时所能 ...

  2. linux内存映射原理,Linux内存管理实践-使用fault()实现内存映射

    内核态与用户态进行数据交互通常是这样一种模型:内核利用自身的特权通过特定的服务程序采集.接收和处理数据:接着,用户态程序和内核服务程序进行数据交互,或接收内核态的数据,或向内核态写入数据.通过传统的那 ...

  3. 【Linux 内核 内存管理】内存映射原理 ① ( 物理地址空间 | 外围设备寄存器 | 外围设备寄存器的物理地址 映射到 虚拟地址空间 )

    文章目录 一.物理地址空间 二.外围设备寄存器 三.外围设备寄存器物理地址 映射到 虚拟地址空间 一.物理地址空间 " 物理地址空间 " 是 CPU 处理器 在 " 总线 ...

  4. hibernate mysql 映射_Hibernate怎么不用配置mapping就使用数据库表映射实体

    用xml配置时就需要每建一个表就hibernate-cfg-xml里加入它的映射.如果不用加入此代码就实现映射就要用注解的方式,系统会根据你的注解自动映射对应的数据表,实现几乎xml文件的零配置. 例 ...

  5. mysql jpa 批注 视图_通过JPA注解映射视图的实体类 jpa 视图 无主键 @Query注解的用法(Spring Data JPA) jpa 使用sql语句...

    参考: https://blog.csdn.net/qq465235530/article/details/68064074 https://www.cnblogs.com/zj0208/p/6008 ...

  6. mysql jpa 批注 视图_JPA 批注参考

    在 JPA 之前,Java EE 应用程序将持续类表示为容器管理的实体 bean.使用 JPA,您可以将任何普通的旧式 Java 对象 (POJO) 类指定为 JPA 实体:一个应使用 JPA 持续性 ...

  7. 【嵌入式07】寄存器映射原理详解,GPIO端口的初始化设置步骤

    本文主要介绍STM32F103系列芯片的地址映射和寄存器映射原理,GPIO端口的初始化设置步骤. 一.STM32F103系列芯片的地址映射和寄存器映射原理 1.什么是寄存器? 2.地址映射和寄存器映射 ...

  8. Linux 操作系统原理 — 内存 — 基于 MMU 硬件单元的虚/实地址映射技术

    目录 文章目录 目录 前文列表 物理地址与虚拟地址 内存空间的组织方式 虚拟地址空间的编址 内核态地址空间 用户态地址空间 内-外存空间的交换与虚拟存储空间之间的映射关系 缺页异常 前文列表 < ...

  9. 淘宝文件系统文件映射原理及实现

    文章目录 1 文件系统映射原理 1.1 文件映射应用场景 1.2 文件映射相关函数介绍 2 文件映射实战 1 文件系统映射原理 1.1 文件映射应用场景 主要应用场景如下: 进程间共享信息. 实现文件 ...

最新文章

  1. 一个对称性解释三个宇宙学难题;引力波碰撞会发光?粘液霉菌助力寻找宇宙网 | 一周科技速览...
  2. c++读取json文件_SPARK入门 - json文件读取
  3. linux内核杂记(14)-Linux kernel release 5.x(1)
  4. 使用java代码判断一个字符串里是否包含中文字符
  5. 奋战杭电ACM(DAY10)1015
  6. mongodb 系列 ~ mongo 用户验证系列
  7. oracle导入1542错误,Oracle 12c:ORA-28040 ORA-01017
  8. linux控制协程参数,Linux高性能网络:协程系列05-协程实现之原语操作
  9. mysql索引 倒排表_mysql倒排的优化
  10. tree 树 搜索关键字
  11. STM32工程,Keil软件新建工程详细步骤
  12. T19136 交通指挥系统 题解
  13. 最小二乘估计-LSE(Least Square Estimate)
  14. 项目经理也分三六九等,初级项目经理和高级项目经理的区别
  15. HashMap常见面试问题总结
  16. 深入理解裸机与RTOS开发模式
  17. Python当前时间是一年中第几周
  18. Python 调用WebService接口出错-suds.transport.TransportError: HTTP Error 401: Unauthori
  19. [OHIF-Viewers]医疗数字阅片-医学影像-querySelector() 选择器语法-将画布(canvas)图像保存成本地图片的方法...
  20. java号码分身_电话号码分身

热门文章

  1. 【Manacher】最长双回文串(luogu 4555)
  2. 【递归】桐桐的递归函数
  3. 网络流及建模专题(上)
  4. Zookeeper面试题
  5. [编程入门]阶乘求和:求Sn=1!+2!+3!+4!+5!+…+n!之值,其中n是一个数字(n不超过20)。
  6. springboot点击运行没反应,什么都不显示的解决方式
  7. 求从 1 到 100 之间所有奇数的平方和
  8. java 组件化_(原创)搭建一个组件化的监控平台
  9. 使用maven聚合安装多个maven工程到本地仓库报错的解决方法:child module pom.xml does not exist
  10. java泛型程序设计——Varargs 警告+不能实例化类型变量