Classpath woes with hibernate.physical_naming_strategy with JPADatabase

41 views
Skip to first unread message

Jens Teglhus Møller

unread,
Sep 17, 2019, 4:57:16 AM9/17/19
to jOOQ User Group
Hi

I'm trying to get schema generation using JPADatabase to work with spring boot.

In my initial testing I got everything working to the point where there was a mismatch with the table names when executing queries (generator not using same naming strategy as spring app).

I have a 3 module maven setup with jpa-model, jooq-model and spring-app (simplified example can be seen here: https://github.com/djarnis73/jooq-spring-jpa-example).

I saw the documentation regarding setting hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy but when i do that the code generator fails since it cannot find the class.

[ERROR] Failed to execute goal org.jooq:jooq-codegen-maven:3.12.1:generate (default) on project jooq-model: Error running jOOQ code generation tool: Error while exporting schema: Unable to resolve name [org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy] as strategy [org.hibernate.boot.model.naming.PhysicalNamingStrategy]: Unable to load class [org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy]: Could not load requested class : org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy -> [Help 1]

I tried adding

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>${spring.boot.version}</version>
</dependency>

I also tried adding the dependency several other places, but I think it should be a plugin dependency.

I have verified that org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy is in the org.springframework.boot:spring-boot jar file

And when running maven with -X i get the following:

[DEBUG] Populating class realm plugin>org.jooq:jooq-codegen-maven:3.12.1
[DEBUG]   Included: org.jooq:jooq-codegen-maven:jar:3.12.1
[DEBUG]   Included: org.springframework.boot:spring-boot:jar:2.1.8.RELEASE
(others removed for brevity)

I'm testing with jooq 3.12.1, spring boot 2.1.8.RELEASE

I have not been able to get it working, can anyone give me a hint or point me to a working example.

Best regards Jens

Lukas Eder

unread,
Sep 17, 2019, 8:30:18 AM9/17/19
to jOOQ User Group
Hi Jens,

This seems to be a dependency issue - a very unfortunate one at that.

We do some magic to work around some Maven limitations where project dependencies are not automatically on the classpath of a plugin. We did this such that users don't have to repeat adding the JDBC driver dependency all the time. The relevant trick was implemented here: https://github.com/jOOQ/jOOQ/issues/2886

But in this particular case, it appears that transitive dependencies cannot be looked up this way, for example both Hibernate and the JPA API are missing.

I can get your project to compile and generate code using this patch:

diff --git a/jooq-model/pom.xml b/jooq-model/pom.xml
index 9cfd3b9..f4fda74 100644
--- a/jooq-model/pom.xml
+++ b/jooq-model/pom.xml
@@ -45,6 +45,16 @@
                         <artifactId>spring-boot</artifactId>
                         <version>${spring.boot.version}</version>
                     </dependency>
+                    <dependency>
+                        <groupId>org.jooq</groupId>
+                        <artifactId>jooq-meta-extensions</artifactId>
+                        <version>${jooq.version}</version>
+                    </dependency>
+                    <dependency>
+                        <groupId>javax.persistence</groupId>
+                        <artifactId>javax.persistence-api</artifactId>
+                        <version>2.2</version>
+                    </dependency>
                 </dependencies>
 
                 <!-- The plugin should hook into the generate goal -->
diff --git a/pom.xml b/pom.xml
index e9fd6c1..ac13a30 100644
--- a/pom.xml
+++ b/pom.xml
@@ -84,4 +84,21 @@
       <artifactId>lombok</artifactId>
     </dependency>
   </dependencies>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>3.8.1</version>
+          <configuration>
+            <source>11</source>
+            <target>11</target>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+
 </project>

This is very annoying, of course, and without significant maven-fu (who has that) can only be achieved by randomly adding more dependencies until it works. I tend to think that this is by design in Maven, but it may well be that we're misunderstanding something, or that we could add another hack like the one where we found JDBC drivers from the project classpath. In fact, again, our workaround already managed to find jooq-meta-extensions for you, but not its transitive dependencies.

I have created a feature request to try to solve this for a future version of jOOQ:

I hope this helps,
Lukas

--
You received this message because you are subscribed to the Google Groups "jOOQ User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jooq-user+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jooq-user/ffef98dc-c1df-4191-9397-6825c63c54cc%40googlegroups.com.

Jens Teglhus Møller

unread,
Sep 18, 2019, 10:03:42 AM9/18/19
to jOOQ User Group
Hi Lukas

Thanks for your answer. I managed to get it to build with your suggested dependency changes.

But it did not affect the resulting table names. In the example I would expect the entity SampleTable to become SAMPLE_TABLE (it does when creating the database through a spring boot application) but it ends up as SAMPLETABLE.

When running maven build build with -X flag i get the following interesting output:

[DEBUG] Executing query          : select "INFORMATION_SCHEMA"."TABLES"."TABLE_SCHEMA", "INFORMATION_SCHEMA"."TABLES"."TABLE_NAME", "INFORMATION_SCHEMA"."TABLES"."REMARKS" from "INFORMATION_SCHEMA"."TABLES" where "INFORMATION_SCHEMA"."TABLES"."TABLE_SCHEMA" in (cast(? as varchar)) order by "INFORMATION_SCHEMA"."TABLES"."TABLE_SCHEMA", "INFORMATION_SCHEMA"."TABLES"."TABLE_NAME"
[DEBUG] -> with bind values      : select "INFORMATION_SCHEMA"."TABLES"."TABLE_SCHEMA", "INFORMATION_SCHEMA"."TABLES"."TABLE_NAME", "INFORMATION_SCHEMA"."TABLES"."REMARKS" from "INFORMATION_SCHEMA"."TABLES" where "INFORMATION_SCHEMA"."TABLES"."TABLE_SCHEMA" in ('PUBLIC') order by "INFORMATION_SCHEMA"."TABLES"."TABLE_SCHEMA", "INFORMATION_SCHEMA"."TABLES"."TABLE_NAME"
[DEBUG] Fetched result           : +------------+------------+-------+
[DEBUG]                          : |TABLE_SCHEMA|TABLE_NAME  |REMARKS|
[DEBUG]                          : +------------+------------+-------+
[DEBUG]                          : |PUBLIC      |SAMPLETABLE |       |
[DEBUG]                          : |PUBLIC      |SAMPLE_TABLE|       |
[DEBUG]                          : +------------+------------+-------+
[DEBUG] Fetched row(s)           : 2
[DEBUG] Include                  : Including PUBLIC.SAMPLETABLE because of pattern .*
[WARNING] Ambiguous type name      : The object SAMPLE_TABLE generates a type jooqexample.jooqmodel.tables.SampleTable which conflicts with the existing type jooqexample.jooqmodel.tables.Sampletable on some operating systems. Use a custom generator strategy to disambiguate the types.
[DEBUG] Exclude                  : Excluding PUBLIC.SAMPLE_TABLE because of filter org.jooq.codegen.JavaGenerator$AvoidAmbiguousClassesFilter@48a46b0f
[INFO] Tables fetched           : 2 (1 included, 1 excluded)

Any clues as to why hibernate creates both SAMPLETABLE & SAMPLE_TABLE?

Best regards Jens

Lukas Eder

unread,
Sep 18, 2019, 11:33:44 AM9/18/19
to jOOQ User Group
Well, one thing that can be said here is that you have two hibernates on the classpath, which you can see when you run "mvn dependency:tree -Dverbose"

- org.hibernate:hibernate-core:jar:5.3.10.Final 
- org.hibernate:hibernate-core:jar:5.4.2.Final 

Perhaps that helps?

--
You received this message because you are subscribed to the Google Groups "jOOQ User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jooq-user+...@googlegroups.com.

Jens Teglhus Møller

unread,
Sep 24, 2019, 8:43:23 AM9/24/19
to jOOQ User Group
Hi

Sorry for my late reply, got caught up by work and stuff.

No, that is not the problem. I tried removing the spring app module, which removed the duplicate and the problem was still there.

I will try to see if I can reproduce it from command line, so I can debug/turn on some more hibernate logging, then I will revert.

Best regards Jens
To unsubscribe from this group and stop receiving emails from it, send an email to jooq...@googlegroups.com.

Jens Teglhus Møller

unread,
Sep 25, 2019, 7:15:16 AM9/25/19
to jOOQ User Group
Ok, after spending some time in the debugger I found out that it is related to useAttributeConverters. If set to true (it is by default), the schema hibernate generation is run twice once with the hibernate.physical_naming_strategy set and once without.

from JPADatabase line 179 to 183:
export.create(EnumSet.of(TargetType.DATABASE), metadata.buildMetadata());

if (useAttributeConverters)
loadAttributeConverters(metadata.getAnnotatedClasses());

Hibernate creates the tables in both line 179 & 183.

I'm not sure if that is a bug or a feature, but I can see that the AttributeConverterExtracter class defines its own hibernate properties:

private final Properties properties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", JPADatabase.HIBERNATE_DIALECT);
properties.put("hibernate.hbm2ddl.auto", "create-drop");
return properties;
}

So tables are created again without the wanted naming strategy.

If I set useAttributeConverters to false it only generates tables once with the expected naming strategy.

Best regards Jens

Lukas Eder

unread,
Sep 26, 2019, 3:55:42 AM9/26/19
to jOOQ User Group
Hi Jens,

Thanks a lot for chasing this to such detail.

That's interesting, though. I'm not sure why that additional Hibernate PersistenceUnit instance should affect the code generator. We should probably pass user-defined hibernate.* or javax.persistence.* configuration to that instance as well, either way, because the reason for that Extractor is that we need Hibernate again to give us column-identifier/converter pairs, and without the naming strategy, the column identifiers in those pairs would be wrong as well. But that's not the issue you ran into.

I still think there's a wrong version of Hibernate on your classpath because of Spring Boot (which we're not using in this particular integration test). But we'll definitely fix this issue ASAP, and include it in 3.12.2:

Thanks,
Lukas



To unsubscribe from this group and stop receiving emails from it, send an email to jooq-user+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jooq-user/aef06073-13ae-45fd-81c9-e793ace47e98%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages