{"id":19474,"date":"2013-12-10T19:00:31","date_gmt":"2013-12-10T17:00:31","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=19474"},"modified":"2013-12-10T00:03:25","modified_gmt":"2013-12-09T22:03:25","slug":"jooq-facts-from-jpa-annotations-to-jooq-table-mappings","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html","title":{"rendered":"JOOQ Facts: From JPA Annotations to JOOQ Table Mappings"},"content":{"rendered":"<p><a href=\"http:\/\/www.jooq.org\/\">JOOQ<\/a> is a neat framework, and it addresses a long issue I\u2019ve had with advanced dynamic filtered queries. While Hibernate and JPA come with a useful Criteria API, which I\u2019ve been using for quite some time, there are understandable limits to what you can do with those. For instance, you cannot go beyond simple SQL operations (e.g JOINS, NESTED SLECTS, AGGREGATION) and do something like: <a href=\"http:\/\/www.jooq.org\/doc\/3.2\/manual-single-page\/#window-functions\">window functions<\/a>, <a href=\"http:\/\/www.jooq.org\/doc\/3.2\/manual-single-page\/#user-defined-functions\">user-defined functions<\/a> or <a href=\"http:\/\/www.jooq.org\/doc\/3.2\/manual-single-page\/#sequences-and-serials\">easy sequencing<\/a> to name a few.<\/p>\n<p>JOOQ doesn\u2019t feel like competing with Hibernate, but instead I feel like it completes it. I\u2019ve been using Hibernate for the WRITE part of my Data Layer, hence its name or the \u201cPersisting\u201d part in JPA. For simple to medium complex queries, Hibernate does its best, but I don\u2019t have to solely rely on it for all my queries, am I? There is also a drawback to querying properties and that\u2019s because you sometimes have to add an association to your Domain Model just for the sake of querying it for a small number of use cases.<\/p>\n<p>So, since I\u2019m not afraid of writing native queries, I could therefore do it in a <a href=\"http:\/\/www.jooq.org\/doc\/2.6\/manual\/sql-building\/sql-statements\/dsl-and-non-dsl\/\">DSL<\/a> fashion and vendor-independent way.<\/p>\n<p>While you can go with string-based column naming, JOOQ offers a better approach through the use of a type-safe Metadata, so the first thing we need to do is to generate our table mapping for our database schema.<\/p>\n<p>Since, I already have a JPA Model, I can generate a database schema DDL from it, and for that we can use the hibernatetool ant task.<\/p>\n<pre class=\" brush:xml\">&lt;plugin&gt;\r\n\t&lt;groupId&gt;org.apache.maven.plugins&lt;\/groupId&gt;\r\n\t&lt;artifactId&gt;maven-antrun-plugin&lt;\/artifactId&gt;\r\n\t&lt;executions&gt;\r\n\t\t&lt;execution&gt;\r\n\t\t\t&lt;id&gt;generate-test-sql-scripts&lt;\/id&gt;\r\n\t\t\t&lt;phase&gt;generate-test-resources&lt;\/phase&gt;\r\n\t\t\t&lt;goals&gt;\r\n\t\t\t\t&lt;goal&gt;run&lt;\/goal&gt;\r\n\t\t\t&lt;\/goals&gt;\r\n\t\t\t&lt;configuration&gt;\r\n\t\t\t\t&lt;tasks&gt;\r\n\t\t\t\t\t&lt;property name=\"maven_test_classpath\" refid=\"maven.test.classpath\"\/&gt;\r\n\t\t\t\t\t&lt;path id=\"hibernate_tools_path\"&gt;\r\n\t\t\t\t\t\t&lt;pathelement path=\"${maven_test_classpath}\"\/&gt;\r\n\t\t\t\t\t&lt;\/path&gt;\r\n\t\t\t\t\t&lt;property name=\"hibernate_tools_classpath\" refid=\"hibernate_tools_path\"\/&gt;\r\n\t\t\t\t\t&lt;taskdef name=\"hibernatetool\"\r\n\t\t\t\t\t\t\t classname=\"org.hibernate.tool.ant.HibernateToolTask\"\/&gt;\r\n\t\t\t\t\t&lt;mkdir dir=\"${project.build.directory}\/test-classes\/hsqldb\"\/&gt;\r\n\t\t\t\t\t&lt;hibernatetool destdir=\"${project.build.directory}\/test-classes\/hsqldb\"&gt;\r\n\t\t\t\t\t\t&lt;classpath refid=\"hibernate_tools_path\"\/&gt;\r\n\t\t\t\t\t\t&lt;jpaconfiguration persistenceunit=\"testPersistenceUnit\"\r\n\t\t\t\t\t\t\t\t\t\t  propertyfile=\"src\/test\/resources\/META-INF\/spring\/jdbc.properties\"\/&gt;\r\n\t\t\t\t\t\t&lt;hbm2ddl drop=\"false\" create=\"true\" export=\"false\"\r\n\t\t\t\t\t\t\t\t outputfilename=\"create_db.sql\"\r\n\t\t\t\t\t\t\t\t delimiter=\";\" format=\"true\"\/&gt;\r\n\t\t\t\t\t\t&lt;hbm2ddl drop=\"true\" create=\"false\" export=\"false\"\r\n\t\t\t\t\t\t\t\t outputfilename=\"drop_db.sql\"\r\n\t\t\t\t\t\t\t\t delimiter=\";\" format=\"true\"\/&gt;\r\n\t\t\t\t\t&lt;\/hibernatetool&gt;\r\n\t\t\t\t&lt;\/tasks&gt;\r\n\t\t\t&lt;\/configuration&gt;\r\n\t\t&lt;\/execution&gt;\r\n\t&lt;\/executions&gt;\r\n\t&lt;dependencies&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.hibernate&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;hibernate-entitymanager&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${hibernate.version}&lt;\/version&gt;\r\n\t\t\t&lt;exclusions&gt;\r\n\t\t\t\t&lt;exclusion&gt;\r\n\t\t\t\t\t&lt;groupId&gt;org.slf4j&lt;\/groupId&gt;\r\n\t\t\t\t\t&lt;artifactId&gt;slf4j-api&lt;\/artifactId&gt;\r\n\t\t\t\t&lt;\/exclusion&gt;\r\n\t\t\t&lt;\/exclusions&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.hibernate&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;hibernate-tools&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${hibernate.tools.version}&lt;\/version&gt;\r\n\t\t\t&lt;exclusions&gt;\r\n\t\t\t\t&lt;exclusion&gt;\r\n\t\t\t\t\t&lt;groupId&gt;org.hibernate&lt;\/groupId&gt;\r\n\t\t\t\t\t&lt;artifactId&gt;hibernate-commons-annotations&lt;\/artifactId&gt;\r\n\t\t\t\t&lt;\/exclusion&gt;\r\n\t\t\t&lt;\/exclusions&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.slf4j&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;slf4j-api&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${slf4j.version}&lt;\/version&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.slf4j&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;slf4j-simple&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${slf4j.version}&lt;\/version&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t&lt;\/dependencies&gt;\r\n&lt;\/plugin&gt;<\/pre>\n<p>This will generate a \u201ccreate_db.sql\u201d database DDL script, which we\u2019ll use to populate a temporary file-based HSQLDB, using \u201cmaven.sql.plugin\u201d. I would have prefered the in-memory HSQLDB but unfortunately it didn\u2019t save the state between plugin executions.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<pre class=\" brush:xml\">&lt;plugin&gt;\r\n\t&lt;groupId&gt;org.codehaus.mojo&lt;\/groupId&gt;\r\n\t&lt;artifactId&gt;sql-maven-plugin&lt;\/artifactId&gt;\r\n\t&lt;dependencies&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.hsqldb&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;hsqldb&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${hsqldb.version}&lt;\/version&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t&lt;\/dependencies&gt;\r\n\t&lt;configuration&gt;\r\n\t\t&lt;driver&gt;org.hsqldb.jdbc.JDBCDriver&lt;\/driver&gt;\r\n\t\t&lt;url&gt;jdbc:hsqldb:file:${project.build.directory}\/hsqldb\/db;shutdown=true&lt;\/url&gt;\r\n\t\t&lt;username&gt;sa&lt;\/username&gt;\r\n\t\t&lt;password&gt;&lt;\/password&gt;\r\n\t\t&lt;autocommit&gt;true&lt;\/autocommit&gt;\r\n\t\t&lt;settingsKey&gt;hsql-db-test&lt;\/settingsKey&gt;\r\n\t&lt;\/configuration&gt;\r\n\t&lt;executions&gt;\r\n\t\t&lt;execution&gt;\r\n\t\t\t&lt;id&gt;create-test-compile-data&lt;\/id&gt;\r\n\t\t\t&lt;phase&gt;process-test-resources&lt;\/phase&gt;\r\n\t\t\t&lt;inherited&gt;true&lt;\/inherited&gt;\r\n\t\t\t&lt;goals&gt;\r\n\t\t\t\t&lt;goal&gt;execute&lt;\/goal&gt;\r\n\t\t\t&lt;\/goals&gt;\r\n\t\t\t&lt;configuration&gt;\r\n\t\t\t\t&lt;orderFile&gt;ascending&lt;\/orderFile&gt;\r\n\t\t\t\t&lt;fileset&gt;\r\n\t\t\t\t\t&lt;basedir&gt;${project.build.directory}\/test-classes\/hsqldb\/&lt;\/basedir&gt;\r\n\t\t\t\t\t&lt;includes&gt;\r\n\t\t\t\t\t\t&lt;include&gt;create_db.sql&lt;\/include&gt;\r\n\t\t\t\t\t&lt;\/includes&gt;\r\n\t\t\t\t&lt;\/fileset&gt;\r\n\t\t\t\t&lt;autocommit&gt;true&lt;\/autocommit&gt;\r\n\t\t\t&lt;\/configuration&gt;\r\n\t\t&lt;\/execution&gt;\r\n\t&lt;\/executions&gt;\r\n&lt;\/plugin&gt;<\/pre>\n<p>So the HSQLDB is now populated with our JPA generated schema, and we can finally call the JOOQ code generation to build the table mapping.<\/p>\n<pre class=\" brush:xml\">&lt;plugin&gt;\r\n\t&lt;groupId&gt;org.jooq&lt;\/groupId&gt;\r\n\t&lt;artifactId&gt;jooq-codegen-maven&lt;\/artifactId&gt;\r\n\t&lt;executions&gt;\r\n\t\t&lt;execution&gt;\r\n\t\t\t&lt;phase&gt;process-test-classes&lt;\/phase&gt;\r\n\t\t\t&lt;goals&gt;\r\n\t\t\t\t&lt;goal&gt;generate&lt;\/goal&gt;\r\n\t\t\t&lt;\/goals&gt;\r\n\t\t&lt;\/execution&gt;\r\n\t&lt;\/executions&gt;\r\n\t&lt;dependencies&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.hsqldb&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;hsqldb&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${hsqldb.version}&lt;\/version&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t&lt;\/dependencies&gt;\r\n\t&lt;configuration&gt;\r\n\t\t&lt;jdbc&gt;\r\n\t\t\t&lt;driver&gt;org.hsqldb.jdbc.JDBCDriver&lt;\/driver&gt;\r\n\t\t\t&lt;url&gt;jdbc:hsqldb:file:${project.build.directory}\/hsqldb\/db&lt;\/url&gt;\r\n\t\t\t&lt;user&gt;sa&lt;\/user&gt;\r\n\t\t\t&lt;password&gt;&lt;\/password&gt;\r\n\t\t&lt;\/jdbc&gt;\r\n\t\t&lt;generator&gt;\r\n\t\t\t&lt;name&gt;org.jooq.util.JavaGenerator&lt;\/name&gt;\r\n\t\t\t&lt;database&gt;\r\n\t\t\t\t&lt;name&gt;org.jooq.util.hsqldb.HSQLDBDatabase&lt;\/name&gt;\r\n\t\t\t\t&lt;includes&gt;.*&lt;\/includes&gt;\r\n\t\t\t\t&lt;excludes&gt;&lt;\/excludes&gt;\r\n\t\t\t\t&lt;inputSchema&gt;PUBLIC&lt;\/inputSchema&gt;\r\n\t\t\t&lt;\/database&gt;\r\n\t\t\t&lt;generate&gt;&lt;\/generate&gt;\r\n\t\t\t&lt;target&gt;\r\n\t\t\t\t&lt;packageName&gt;vladmihalcea.jooq.schema&lt;\/packageName&gt;\r\n\t\t\t\t&lt;directory&gt;target\/generated-sources\/jooq&lt;\/directory&gt;\r\n\t\t\t&lt;\/target&gt;\r\n\t\t&lt;\/generator&gt;\r\n\t&lt;\/configuration&gt;\r\n&lt;\/plugin&gt;<\/pre>\n<p>Running through maven we get the table mapping generated, so let\u2019s compare a JPA meta model for the Image class to the associated JOOQ table mapping:<\/p>\n<p>The JPA meta model looks like:<\/p>\n<pre class=\" brush:java\">@StaticMetamodel(Image.class)\r\npublic abstract class Image_ {\r\n\r\n\tpublic static volatile SingularAttribute&lt;Image, Product&gt; product;\r\n\tpublic static volatile SingularAttribute&lt;Image, Long&gt; id;\r\n\tpublic static volatile SetAttribute&lt;Image, Version&gt; versions;\r\n\tpublic static volatile SingularAttribute&lt;Image, Integer&gt; index;\r\n\tpublic static volatile SingularAttribute&lt;Image, String&gt; name;\r\n\r\n}<\/pre>\n<p>and the JOOQ table mapping<\/p>\n<pre class=\" brush:java\">@javax.annotation.Generated(value    = { \"http:\/\/www.jooq.org\", \"3.2.0\" },\r\n                            comments = \"This class is generated by jOOQ\")\r\n@java.lang.SuppressWarnings({ \"all\", \"unchecked\", \"rawtypes\" })\r\npublic class Image extends org.jooq.impl.TableImpl&lt;vladmihalcea.jooq.schema.tables.records.ImageRecord&gt; {\r\n\r\n\tprivate static final long serialVersionUID = 1596930978;\r\n\r\n\t\/**\r\n\t * The singleton instance of &lt;code&gt;PUBLIC.IMAGE&lt;\/code&gt;\r\n\t *\/\r\n\tpublic static final vladmihalcea.jooq.schema.tables.Image IMAGE = new vladmihalcea.jooq.schema.tables.Image();\r\n\r\n\t\/**\r\n\t * The class holding records for this type\r\n\t *\/\r\n\t@Override\r\n\tpublic java.lang.Class&lt;vladmihalcea.jooq.schema.tables.records.ImageRecord&gt; getRecordType() {\r\n\t\treturn vladmihalcea.jooq.schema.tables.records.ImageRecord.class;\r\n\t}\r\n\r\n\t\/**\r\n\t * The column &lt;code&gt;PUBLIC.IMAGE.ID&lt;\/code&gt;. \r\n\t *\/\r\n\tpublic final org.jooq.TableField&lt;vladmihalcea.jooq.schema.tables.records.ImageRecord, java.lang.Long&gt; ID = createField(\"ID\", org.jooq.impl.SQLDataType.BIGINT.nullable(false), this);\r\n\r\n\t\/**\r\n\t * The column &lt;code&gt;PUBLIC.IMAGE.INDEX&lt;\/code&gt;. \r\n\t *\/\r\n\tpublic final org.jooq.TableField&lt;vladmihalcea.jooq.schema.tables.records.ImageRecord, java.lang.Integer&gt; INDEX = createField(\"INDEX\", org.jooq.impl.SQLDataType.INTEGER, this);\r\n\r\n\t\/**\r\n\t * The column &lt;code&gt;PUBLIC.IMAGE.NAME&lt;\/code&gt;. \r\n\t *\/\r\n\tpublic final org.jooq.TableField&lt;vladmihalcea.jooq.schema.tables.records.ImageRecord, java.lang.String&gt; NAME = createField(\"NAME\", org.jooq.impl.SQLDataType.VARCHAR.length(255), this);\r\n\r\n\t\/**\r\n\t * The column &lt;code&gt;PUBLIC.IMAGE.PRODUCT_ID&lt;\/code&gt;. \r\n\t *\/\r\n\tpublic final org.jooq.TableField&lt;vladmihalcea.jooq.schema.tables.records.ImageRecord, java.lang.Long&gt; PRODUCT_ID = createField(\"PRODUCT_ID\", org.jooq.impl.SQLDataType.BIGINT, this);\r\n\r\n\t\/**\r\n\t * Create a &lt;code&gt;PUBLIC.IMAGE&lt;\/code&gt; table reference\r\n\t *\/\r\n\tpublic Image() {\r\n\t\tsuper(\"IMAGE\", vladmihalcea.jooq.schema.Public.PUBLIC);\r\n\t}\r\n\r\n\t\/**\r\n\t * Create an aliased &lt;code&gt;PUBLIC.IMAGE&lt;\/code&gt; table reference\r\n\t *\/\r\n\tpublic Image(java.lang.String alias) {\r\n\t\tsuper(alias, vladmihalcea.jooq.schema.Public.PUBLIC, vladmihalcea.jooq.schema.tables.Image.IMAGE);\r\n\t}\r\n\r\n\t\/**\r\n\t * {@inheritDoc}\r\n\t *\/\r\n\t@Override\r\n\tpublic org.jooq.Identity&lt;vladmihalcea.jooq.schema.tables.records.ImageRecord, java.lang.Long&gt; getIdentity() {\r\n\t\treturn vladmihalcea.jooq.schema.Keys.IDENTITY_IMAGE;\r\n\t}\r\n\r\n\t\/**\r\n\t * {@inheritDoc}\r\n\t *\/\r\n\t@Override\r\n\tpublic org.jooq.UniqueKey&lt;vladmihalcea.jooq.schema.tables.records.ImageRecord&gt; getPrimaryKey() {\r\n\t\treturn vladmihalcea.jooq.schema.Keys.SYS_PK_10059;\r\n\t}\r\n\r\n\t\/**\r\n\t * {@inheritDoc}\r\n\t *\/\r\n\t@Override\r\n\tpublic java.util.List&lt;org.jooq.UniqueKey&lt;vladmihalcea.jooq.schema.tables.records.ImageRecord&gt;&gt; getKeys() {\r\n\t\treturn java.util.Arrays.&lt;org.jooq.UniqueKey&lt;vladmihalcea.jooq.schema.tables.records.ImageRecord&gt;&gt;asList(vladmihalcea.jooq.schema.Keys.SYS_PK_10059, vladmihalcea.jooq.schema.Keys.UK_OQBG3YIU5I1E17SL0FEAWT8PE);\r\n\t}\r\n\r\n\t\/**\r\n\t * {@inheritDoc}\r\n\t *\/\r\n\t@Override\r\n\tpublic java.util.List&lt;org.jooq.ForeignKey&lt;vladmihalcea.jooq.schema.tables.records.ImageRecord, ?&gt;&gt; getReferences() {\r\n\t\treturn java.util.Arrays.&lt;org.jooq.ForeignKey&lt;vladmihalcea.jooq.schema.tables.records.ImageRecord, ?&gt;&gt;asList(vladmihalcea.jooq.schema.Keys.FK_9W522RC4D0KFDKQ390IHV92GB);\r\n\t}\r\n\r\n\t\/**\r\n\t * {@inheritDoc}\r\n\t *\/\r\n\t@Override\r\n\tpublic vladmihalcea.jooq.schema.tables.Image as(java.lang.String alias) {\r\n\t\treturn new vladmihalcea.jooq.schema.tables.Image(alias);\r\n\t}\r\n}<\/pre>\n<p>Now we also need to make Maven aware of our newly generated JOOQ Metadata classes, so it can compile them in a next test-compile phase.<\/p>\n<pre class=\" brush:xml\">&lt;plugin&gt;\r\n  &lt;groupId&gt;org.codehaus.mojo&lt;\/groupId&gt;\r\n  &lt;artifactId&gt;build-helper-maven-plugin&lt;\/artifactId&gt;\r\n  &lt;executions&gt;\r\n    &lt;execution&gt;\r\n      &lt;id&gt;add-source&lt;\/id&gt;\r\n      &lt;phase&gt;process-test-sources&lt;\/phase&gt;\r\n      &lt;goals&gt;\r\n        &lt;goal&gt;add-test-source&lt;\/goal&gt;\r\n      &lt;\/goals&gt;\r\n      &lt;configuration&gt;\r\n        &lt;sources&gt;\r\n          &lt;source&gt;${project.build.directory}\/generated-sources\/java&lt;\/source&gt;\r\n        &lt;\/sources&gt;\r\n      &lt;\/configuration&gt;\r\n    &lt;\/execution&gt;\r\n  &lt;\/executions&gt;\r\n&lt;\/plugin&gt;\r\n<\/pre>\n<p>Now I can start playing with JOOQ. Let\u2019s add the DSLContext to our Spring application context:<\/p>\n<pre class=\" brush:xml\">\r\n&lt;bean id=&quot;jooqContext&quot; class=&quot;org.jooq.impl.DSL&quot; factory-method=&quot;using&quot;&gt;\r\n    &lt;constructor-arg ref=&quot;dataSource&quot;\/&gt;\r\n    &lt;constructor-arg value=&quot;#{T(org.jooq.SQLDialect).HSQLDB}&quot;\/&gt;\r\n&lt;\/bean\r\n<\/pre>\n<p>And we will write a test to check if everything works properly:<\/p>\n<pre class=\" brush:xml\">\r\nprivate List&lt;ImageProductDTO&gt; getImageProductDTOs_JOOQ() {\r\n    return transactionTemplate.execute(new TransactionCallback&lt;List&lt;ImageProductDTO&gt;&gt;() {\r\n        @Override\r\n        public List&lt;ImageProductDTO&gt; doInTransaction(TransactionStatus transactionStatus) {\r\n            return jooqContext\r\n                    .select(IMAGE.NAME, PRODUCT.NAME)\r\n                    .from(IMAGE)\r\n                    .join(PRODUCT).on(IMAGE.PRODUCT_ID.equal(PRODUCT.ID))\r\n                    .where(PRODUCT.NAME.likeIgnoreCase(&quot;%tv%&quot;))\r\n                        .and(IMAGE.INDEX.greaterThan(0))\r\n                    .orderBy(IMAGE.NAME.asc())\r\n                    .fetch().into(ImageProductDTO.class);\r\n        }\r\n    });\r\n}\r\n<\/pre>\n<p>Which generates the following SQL<\/p>\n<pre class=\" brush:xml\">\r\nSELECT &quot;PUBLIC&quot;.&quot;image&quot;.&quot;name&quot;,\r\n              &quot;PUBLIC&quot;.&quot;product&quot;.&quot;name&quot;\r\nFROM     &quot;PUBLIC&quot;.&quot;image&quot;\r\n              JOIN &quot;PUBLIC&quot;.&quot;product&quot;\r\n                  ON &quot;PUBLIC&quot;.&quot;image&quot;.&quot;product_id&quot; = &quot;PUBLIC&quot;.&quot;product&quot;.&quot;id&quot;\r\nWHERE   ( Lower(&quot;PUBLIC&quot;.&quot;product&quot;.&quot;name&quot;) LIKE Lower('%tv%')\r\n                  AND &quot;PUBLIC&quot;.&quot;image&quot;.&quot;index&quot; &gt; 0 )\r\nORDER   BY &quot;PUBLIC&quot;.&quot;image&quot;.&quot;name&quot; ASC  \r\n<\/pre>\n<p>This is the first time I used JOOQ, and it didn\u2019t take me too much time to browse the documentation and to have everything set up in my Hibernate Facts coding example. The JOOQ query building feels natural, it\u2019s like writing native SQL code, so I don\u2019t have to actually learn the API to know how to use it. I will proudly add it to my Java Data Toolbox.<\/p>\n<blockquote>\n<p>This coding example generates the JOOQ mappings into the test-classes folder and so you can\u2019t use them from within the main\/java source files. This can be solved, but it requires refactoring the existing solution by moving the model classes into a separate Maven module. You could generate the JOOQ schema in this separate module, where before packaging you would move the schema classes from test-classes to the classes folder. Then you would have to include this new module, where you would normally make use of the JOOQ schema.<\/p>\n<\/blockquote>\n<div style=\"border: 1px solid #D8D8D8; background: #FAFAFA; width: 100%; padding-left: 5px;\"><b><i>Reference: <\/i><\/b><a href=\"http:\/\/vladmihalcea.wordpress.com\/2013\/12\/06\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings\/\">JOOQ Facts: From JPA Annotations to JOOQ Table Mappings<\/a> from our <a href=\"http:\/\/www.javacodegeeks.com\/jcg\">JCG partner<\/a> Vlad Mihalcea at the <a href=\"http:\/\/vladmihalcea.wordpress.com\/\">Vlad Mihalcea&#8217;s Blog<\/a> blog.<\/div>\n","protected":false},"excerpt":{"rendered":"<p>JOOQ is a neat framework, and it addresses a long issue I\u2019ve had with advanced dynamic filtered queries. While Hibernate and JPA come with a useful Criteria API, which I\u2019ve been using for quite some time, there are understandable limits to what you can do with those. For instance, you cannot go beyond simple SQL &hellip;<\/p>\n","protected":false},"author":507,"featured_media":38135,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[662,256,33],"class_list":["post-19474","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-databases","tag-jooq","tag-jpa"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>JOOQ Facts: From JPA Annotations to JOOQ Table Mappings<\/title>\n<meta name=\"description\" content=\"JOOQ is a neat framework, and it addresses a long issue I\u2019ve had with advanced dynamic filtered queries. While Hibernate and JPA come with a useful\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"JOOQ Facts: From JPA Annotations to JOOQ Table Mappings\" \/>\n<meta property=\"og:description\" content=\"JOOQ is a neat framework, and it addresses a long issue I\u2019ve had with advanced dynamic filtered queries. While Hibernate and JPA come with a useful\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/vlad.mihalcea.71\" \/>\n<meta property=\"article:published_time\" content=\"2013-12-10T17:00:31+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/03\/jooq-2-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Vlad Mihalcea\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Vlad Mihalcea\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html\"},\"author\":{\"name\":\"Vlad Mihalcea\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/2c2d5059ee4fd88b1b3b9e52efc5b129\"},\"headline\":\"JOOQ Facts: From JPA Annotations to JOOQ Table Mappings\",\"datePublished\":\"2013-12-10T17:00:31+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html\"},\"wordCount\":624,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2015\\\/03\\\/jooq-2-logo.jpg\",\"keywords\":[\"Databases\",\"jOOQ\",\"JPA\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html\",\"name\":\"JOOQ Facts: From JPA Annotations to JOOQ Table Mappings\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2015\\\/03\\\/jooq-2-logo.jpg\",\"datePublished\":\"2013-12-10T17:00:31+00:00\",\"description\":\"JOOQ is a neat framework, and it addresses a long issue I\u2019ve had with advanced dynamic filtered queries. While Hibernate and JPA come with a useful\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2015\\\/03\\\/jooq-2-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2015\\\/03\\\/jooq-2-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"JOOQ Facts: From JPA Annotations to JOOQ Table Mappings\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/2c2d5059ee4fd88b1b3b9e52efc5b129\",\"name\":\"Vlad Mihalcea\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f9f4ac0b2229b9f9fb993393b822ffbf63e60c1665a244176d3c4728565a9a9f?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f9f4ac0b2229b9f9fb993393b822ffbf63e60c1665a244176d3c4728565a9a9f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f9f4ac0b2229b9f9fb993393b822ffbf63e60c1665a244176d3c4728565a9a9f?s=96&d=mm&r=g\",\"caption\":\"Vlad Mihalcea\"},\"description\":\"Vlad Mihalcea is a software architect passionate about software integration, high scalability and concurrency challenges.\",\"sameAs\":[\"http:\\\/\\\/vladmihalcea.wordpress.com\\\/\",\"https:\\\/\\\/www.facebook.com\\\/vlad.mihalcea.71\",\"http:\\\/\\\/www.linkedin.com\\\/pub\\\/vlad-mihalcea\\\/20\\\/a59\\\/580\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/vlad-mihalcea\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"JOOQ Facts: From JPA Annotations to JOOQ Table Mappings","description":"JOOQ is a neat framework, and it addresses a long issue I\u2019ve had with advanced dynamic filtered queries. While Hibernate and JPA come with a useful","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html","og_locale":"en_US","og_type":"article","og_title":"JOOQ Facts: From JPA Annotations to JOOQ Table Mappings","og_description":"JOOQ is a neat framework, and it addresses a long issue I\u2019ve had with advanced dynamic filtered queries. While Hibernate and JPA come with a useful","og_url":"https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_author":"https:\/\/www.facebook.com\/vlad.mihalcea.71","article_published_time":"2013-12-10T17:00:31+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/03\/jooq-2-logo.jpg","type":"image\/jpeg"}],"author":"Vlad Mihalcea","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Vlad Mihalcea","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html"},"author":{"name":"Vlad Mihalcea","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/2c2d5059ee4fd88b1b3b9e52efc5b129"},"headline":"JOOQ Facts: From JPA Annotations to JOOQ Table Mappings","datePublished":"2013-12-10T17:00:31+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html"},"wordCount":624,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/03\/jooq-2-logo.jpg","keywords":["Databases","jOOQ","JPA"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html","url":"https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html","name":"JOOQ Facts: From JPA Annotations to JOOQ Table Mappings","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/03\/jooq-2-logo.jpg","datePublished":"2013-12-10T17:00:31+00:00","description":"JOOQ is a neat framework, and it addresses a long issue I\u2019ve had with advanced dynamic filtered queries. While Hibernate and JPA come with a useful","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/03\/jooq-2-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/03\/jooq-2-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/jooq-facts-from-jpa-annotations-to-jooq-table-mappings.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"JOOQ Facts: From JPA Annotations to JOOQ Table Mappings"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/2c2d5059ee4fd88b1b3b9e52efc5b129","name":"Vlad Mihalcea","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/f9f4ac0b2229b9f9fb993393b822ffbf63e60c1665a244176d3c4728565a9a9f?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f9f4ac0b2229b9f9fb993393b822ffbf63e60c1665a244176d3c4728565a9a9f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f9f4ac0b2229b9f9fb993393b822ffbf63e60c1665a244176d3c4728565a9a9f?s=96&d=mm&r=g","caption":"Vlad Mihalcea"},"description":"Vlad Mihalcea is a software architect passionate about software integration, high scalability and concurrency challenges.","sameAs":["http:\/\/vladmihalcea.wordpress.com\/","https:\/\/www.facebook.com\/vlad.mihalcea.71","http:\/\/www.linkedin.com\/pub\/vlad-mihalcea\/20\/a59\/580"],"url":"https:\/\/www.javacodegeeks.com\/author\/vlad-mihalcea"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/19474","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/507"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=19474"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/19474\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/38135"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=19474"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=19474"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=19474"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}