首页 > 其他 > 详细

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

时间:2020-11-28 14:25:40      阅读:29      评论:0      收藏:0      [点我收藏+]

原文翻译

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

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

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

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

由于我已经有了JPA模型,因此可以从中生成数据库模式DDL,为此,我们可以使用hibernatetool ant任务。

<插件>
	<groupId> org.apache.maven.plugins </ groupId>
	<artifactId> maven-antrun-plugin </ artifactId>
	<执行>
		<执行>
			<id> generate-test-sql-scripts </ id>
			<phase>生成测试资源</ phase>
			<目标>
				<goal>运行</ goal>
			</ goals>
			<配置>
				<任务>
					<属性名称=“ maven_test_classpath” refid =“ maven.test.classpath” />
					<path id =“ hibernate_tools_path”>
						<pathelement path =“ $ {maven_test_classpath}” />
					</ path>
					<属性名称=“ 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 =“;” 格式=“ true” />
						<hbm2ddl drop =“ true” create =“ false” export =“ false”
								 outputfilename =“ drop_db.sql”
								 delimiter =“;” 格式=“ true” />
					</ hibernatetool>
				</ tasks>
			</ configuration>
		</ execution>
	</ executions>
	<依赖项>
		<依赖性>
			<groupId> org.hibernate </ groupId>
			<artifactId>休眠实体经理</ artifactId>
			<version> $ {hibernate.version} </ version>
			<排除>
				<排除>
					<groupId> org.slf4j </ groupId>
					<artifactId> slf4j-api </ artifactId>
				</ exclusion>
			</ exclusions>
		</ dependency>
		<依赖性>
			<groupId> org.hibernate </ groupId>
			<artifactId>休眠工具</ artifactId>
			<version> $ {hibernate.tools.version} </ version>
			<排除>
				<排除>
					<groupId> org.hibernate </ groupId>
					<artifactId> hibernate-commons-批注</ artifactId>
				</ exclusion>
			</ exclusions>
		</ dependency>
		<依赖性>
			<groupId> org.slf4j </ groupId>
			<artifactId> slf4j-api </ artifactId>
			<version> $ {slf4j.version} </ version>
		</ 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,但不幸的是它没有保存插件执行之间的状态。

<插件>
	<groupId> org.codehaus.mojo </ groupId>
	<artifactId> sql-maven-plugin </ artifactId>
	<依赖项>
		<依赖性>
			<groupId> org.hsqldb </ groupId>
			<artifactId> hsqldb </ artifactId>
			<version> $ {hsqldb.version} </ version>
		</ dependency>
	</ dependencies>
	<配置>
		<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>
	<执行>
		<执行>
			<id>创建测试编译数据</ id>
			<phase>过程测试资源</ phase>
			<inherited> true </ inherited>
			<目标>
				<goal>执行</ goal>
			</ goals>
			<配置>
				<orderFile>升序</ orderFile>
				<文件集>
					<basedir> $ {project.build.directory} / test-classes / hsqldb / </ basedir>
					<包括>
						<include> create_db.sql </ include>
					</ includes>
				</ fileset>
				<autocommit> true </ autocommit>
			</ configuration>
		</ execution>
	</ executions>
</ plugin>

因此,HSQLDB现在已由我们的JPA生成的架构填充,并且我们终于可以调用JOOQ代码生成来构建表映射。

<插件>
	<groupId> org.jooq </ groupId>
	<artifactId> jooq-codegen-maven </ artifactId>
	<执行>
		<执行>
			<phase>过程测试类</ phase>
			<目标>
				<goal>生成</ goal>
			</ goals>
		</ execution>
	</ executions>
	<依赖项>
		<依赖性>
			<groupId> org.hsqldb </ groupId>
			<artifactId> hsqldb </ artifactId>
			<version> $ {hsqldb.version} </ version>
		</ dependency>
	</ dependencies>
	<配置>
		<jdbc>
			<driver> org.hsqldb.jdbc.JDBCDriver </ driver>
			<url> jdbc:hsqldb:file:$ {project.build.directory} / hsqldb / db </ url>
			<user> sa </ user>
			<password> </ password>
		</ jdbc>
		<发电机>
			<name> org.jooq.util.JavaGenerator </ name>
			<数据库>
				<name> org.jooq.util.hsqldb.HSQLDBDatabase </ name>
				<includes>。* </ includes>
				<excludes> </ excludes>
				<inputSchema> PUBLIC </ inputSchema>
			</数据库>
			<generate> </ generate>
			<目标>
				<packageName> vladmihalcea.jooq.schema </ packageName>
				<directory> target / generated-sources / jooq </ directory>
			</ target>
		</ generator>
	</ configuration>
</ plugin>

通过maven运行,我们生成了表映射,因此让我们将Image类的JPA元模型与关联的JOOQ表映射进行比较:

JPA元模型如下所示:

@StaticMetamodel(Image.class)
公共抽象类Image_ {

	公共静态挥发性SingularAttribute <Image,Product>产品;
	公共静态挥发物SingularAttribute <Image,Long> id;
	公共静态volatile SetAttribute <Image,Version>版本;
	公共静态挥发性SingularAttribute <Image,Integer>索引;
	公共静态volatile SingularAttribute <图像,字符串>名称;

}

和JOOQ表映射

@ javax.annotation.Generated(value = {“ http://www.jooq.org”,“ 3.2.0”},
                            comments =“此类是由jOOQ生成的”)
@ java.lang.SuppressWarnings({“ all”,“ unchecked”,“ rawtypes”})
公共类Image扩展了org.jooq.impl.TableImpl <vladmihalcea.jooq.schema.tables.records.ImageRecord> {

	私有静态最终长serialVersionUID = 1596930978;

	/ **
	 * <code> PUBLIC.IMAGE </ code>的单例实例
	 * /
	公共静态最终vladmihalcea.jooq.schema.tables.Image图片=新的vladmihalcea.jooq.schema.tables.Image();

	/ **
	 *持有该类型的记录的班级
	 * /
	@Override
	公共java.lang.Class <vladmihalcea.jooq.schema.tables.records.ImageRecord> getRecordType(){
		返回vladmihalcea.jooq.schema.tables.records.ImageRecord.class;
	}

	/ **
	 *列<code> PUBLIC.IMAGE.ID </ code>。 
	 * /
	公共最终org.jooq.TableField <vladmihalcea.jooq.schema.tables.records.ImageRecord,java.lang.Long> ID = createField(“ ID”,org.jooq.impl.SQLDataType.BIGINT.nullable(false),此);

	/ **
	 *列<code> PUBLIC.IMAGE.INDEX </ code>。 
	 * /
	公共最终org.jooq.TableField <vladmihalcea.jooq.schema.tables.records.ImageRecord,java.lang.Integer> INDEX = createField(“ INDEX”,org.jooq.impl.SQLDataType.INTEGER,this);

	/ **
	 *列<code> PUBLIC.IMAGE.NAME </ code>。 
	 * /
	公共最终org.jooq.TableField <vladmihalcea.jooq.schema.tables.records.ImageRecord,java.lang.String> NAME = createField(“ NAME”,org.jooq.impl.SQLDataType.VARCHAR.length(255),这个);

	/ **
	 *列<code> PUBLIC.IMAGE.PRODUCT_ID </ code>。 
	 * /
	公共最终org.jooq.TableField <vladmihalcea.jooq.schema.tables.records.ImageRecord,java.lang.Long> PRODUCT_ID = createField(“ PRODUCT_ID”,org.jooq.impl.SQLDataType.BIGINT,this);

	/ **
	 *创建<code> PUBLIC.IMAGE </ code>表引用
	 * /
	公众形象() {
		super(“ IMAGE”,vladmihalcea.jooq.schema.Public.PUBLIC);
	}

	/ **
	 *创建别名<code> PUBLIC.IMAGE </ code>表引用
	 * /
	公共图片(java.lang.String别名){
		超级(别名,vladmihalcea.jooq.schema.Public.PUBLIC,vladmihalcea.jooq.schema.tables.Image.IMAGE);
	}

	/ **
	 * {@inheritDoc}
	 * /
	@Override
	公共org.jooq.Identity <vladmihalcea.jooq.schema.tables.records.ImageRecord,java.lang.Long> getIdentity(){
		返回vladmihalcea.jooq.schema.Keys.IDENTITY_IMAGE;
	}

	/ **
	 * {@inheritDoc}
	 * /
	@Override
	公共org.jooq.UniqueKey <vladmihalcea.jooq.schema.tables.records.ImageRecord> getPrimaryKey(){
		返回vladmihalcea.jooq.schema.Keys.SYS_PK_10059;
	}

	/ **
	 * {@inheritDoc}
	 * /
	@Override
	公共java.util.List <org.jooq.UniqueKey <vladmihalcea.jooq.schema.tables.records.ImageRecord >> getKeys(){
		返回java.util.Arrays。
	}

	/ **
	 * {@inheritDoc}
	 * /
	@Override
	公共java.util.List <org.jooq.ForeignKey <vladmihalcea.jooq.schema.tables.records.ImageRecord,?>> getReferences(){
		返回java.util.Arrays。<org.jooq.ForeignKey <vladmihalcea.jooq.schema.tables.records.ImageRecord,?>> asList(vladmihalcea.jooq.schema.Keys.FK_9W522RC4D0KFDKQ390IHV92GB);
	}

	/ **
	 * {@inheritDoc}
	 * /
	@Override
	公共vladmihalcea.jooq.schema.tables.Image as(java.lang.String别名){
		返回新的vladmihalcea.jooq.schema.tables.Image(alias);
	}
}

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

<插件>
  <groupId> org.codehaus.mojo </ groupId>
  <artifactId> build-helper-maven-plugin </ artifactId>
  <执行>
    <执行>
      <id>添加源</ id>
      <phase>过程测试源</ phase>
      <目标>
        <goal>添加测试源</ goal>
      </ goals>
      <配置>
        <来源>
          <source> $ {project.build.directory} / generate-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

我们将编写一个测试来检查一切是否正常:

私人列表<ImageProductDTO> getImageProductDTOs_JOOQ(){
    return transactionTemplate.execute(new TransactionCallback <List <ImageProductDTO >>(){
        @Override
        公共列表<ImageProductDTO> doInTransaction(TransactionStatus transactionStatus){
            返回jooqContext
                    。选择(IMAGE.NAME,PRODUCT.NAME)
                    。从图片中)
                    .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

选择“ PUBLIC”。“ image”。“ name”,
              “ PUBLIC”。“产品”。“名称”
来自“公共”。“图像”
              加入“公共”。“产品”
                  ON“ PUBLIC”。“图像”。“ product_id” =“ PUBLIC”。“产品”。“ id”
在哪儿(较低(“ PUBLIC”。“产品”。“名称”)喜欢较低(‘%tv%‘)
                  AND“ PUBLIC”。“ image”。“ index”> 0)
按“ PUBLIC”。“图像”。“名称” ASC排序  

这是我第一次使用JOOQ,花了我太多时间浏览文档并在Hibernate Facts编码示例中进行了所有设置。JOOQ查询的构建感觉很自然,就像编写本机SQL代码一样,因此我不必真正学习API就能知道如何使用它。我将很自豪地将其添加到我的Java Data Toolbox中。

这个编码示例将JOOQ映射生成到test-classes文件夹中,因此您不能在main / java源文件中使用它们。这可以解决,但是需要通过将模型类移动到单独的Maven模块中来重构现有解决方案。您可以在此单独的模块中生成JOOQ模式,在打包之前,您可以在其中将模式类从测试类移至classes文件夹。然后,您将必须包括这个新模块,通常在其中使用JOOQ模式。

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

原文:https://www.cnblogs.com/ScarecrowAnBird/p/14052332.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!