Generating code from JPA annotated entities is broken

瀏覽次數:76 次
跳到第一則未讀訊息

ahmed...@gmail.com

未讀,
2016年11月30日 上午10:46:472016/11/30
收件者:jOOQ User Group、lukas...@datageekery.com
An exception is thrown when generating code from JPA via JPADatabase in meta-extensions. I even made sure to use the same version of hibernate as meta-extensions (hibernate-core:5.0.0.Final with jooq-meta-extensions:3.8.6)

Stack trace:
org.jooq.exception.DataAccessException: Error while exporting schema
 at org
.jooq.util.jpa.JPADatabase.create0(JPADatabase.java:144)
 at org
.jooq.util.AbstractDatabase.create(AbstractDatabase.java:209)
 at org
.jooq.util.AbstractDatabase.create(AbstractDatabase.java:201)
 at org
.jooq.util.AbstractDatabase.getDialect(AbstractDatabase.java:183)
 at org
.jooq.util.JavaGenerator.generate(JavaGenerator.java:232)
 at org
.jooq.util.GenerationTool.run(GenerationTool.java:529)
 at org
.jooq.util.GenerationTool.generate(GenerationTool.java:198)
 at com
.myappp.GenerateJooqCode.main(GenerateJooqCode.java:43)
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.connections.spi.ConnectionProvider]
 at org
.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:244)
 at org
.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:208)
 at org
.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:189)
 at org
.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.buildJdbcConnectionAccess(JdbcEnvironmentInitiator.java:145)
 at org
.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:66)
 at org
.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35)
 at org
.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88)
 at org
.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:234)
 at org
.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:208)
 at org
.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:189)
 at org
.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51)
 at org
.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94)
 at org
.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:217)
 at org
.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:189)
 at org
.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352)
 at org
.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111)
 at org
.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:83)
 at org
.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:418)
 at org
.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:87)
 at org
.hibernate.boot.MetadataSources.buildMetadata(MetadataSources.java:179)
 at org
.jooq.util.jpa.JPADatabase.create0(JPADatabase.java:140)
 
... 7 more
Caused by: java.lang.ClassCastException: org.jooq.util.jpa.JPADatabase$1 cannot be cast to java.lang.String
 at org
.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator.getConfiguredConnectionProviderName(ConnectionProviderInitiator.java:174)
 at org
.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator.initiateService(ConnectionProviderInitiator.java:109)
 at org
.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator.initiateService(ConnectionProviderInitiator.java:41)
 at org
.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88)
 at org
.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:234)
 
... 27 more


The issue seems to be that JPADatabase is being registered for connection provider as an instantiated Class object, whereas hibernate is expecting it to be just the String name of the class and hibernate does it's own instantiation:

From org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator

@Override
public ConnectionProvider initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
...
 
ConnectionProvider connectionProvider = null;
 
final String providerName = getConfiguredConnectionProviderName( configurationValues );
 
if ( providerName != null ) {
 connectionProvider
= instantiateExplicitConnectionProvider( providerName, strategySelector );
 
}
...
}


private String getConfiguredConnectionProviderName( Map configurationValues ) {
 
String providerName = (String) configurationValues.get( AvailableSettings.CONNECTION_PROVIDER );
 
if ( LEGACY_CONNECTION_PROVIDER_MAPPING.containsKey( providerName ) ) {
 
final String actualProviderName = LEGACY_CONNECTION_PROVIDER_MAPPING.get( providerName );
 
DeprecationLogger.DEPRECATION_LOGGER.connectionProviderClassDeprecated( providerName, actualProviderName );
 providerName
= actualProviderName;
 
}
 
return providerName;
}

The exception is thrown here: String providerName = (String) configurationValues.get( AvailableSettings.CONNECTION_PROVIDER ); because the get returns a JPADatabase java object rather than a String, which of course cannot be cast to a String

When I run exactly the same jooq-config.xml but with database name="org.jooq.util.postgres.PostgresDatabase" instead of "org.jooq.util.jpa.JPADatabase" it works fine.

ahmed...@gmail.com

未讀,
2016年11月30日 中午12:13:462016/11/30
收件者:jOOQ User Group、lukas...@datageekery.com、ahmed...@gmail.com
I created a CustomConnectionProvider class:

package com.myapp;

import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class CustomConnectionProvider implements ConnectionProvider {
private final Connection connection;

public CustomConnectionProvider() throws SQLException {
this.connection = DriverManager.getConnection("jdbc:h2:mem:jooq-meta-extensions", "sa", "");
}

@SuppressWarnings("rawtypes")
@Override
public boolean isUnwrappableAs(Class unwrapType) {
return false;
}

@Override
public <T> T unwrap(Class<T> unwrapType) {
return null;
}

@Override
public Connection getConnection() {
return connection;
}

@Override
public void closeConnection(Connection conn) throws SQLException {
}

@Override
public boolean supportsAggressiveRelease() {
return true;
}
}

then I cloned the JPADatabase object and modified from this:
MetadataSources metadata = new MetadataSources(
new StandardServiceRegistryBuilder()
.applySetting("hibernate.dialect", "org.hibernate.dialect.H2Dialect")
.applySetting("javax.persistence.schema-generation-connection", connection)

// [#5607] JPADatabase causes warnings - This prevents them
.applySetting(AvailableSettings.CONNECTION_PROVIDER, new ConnectionProvider() {
@SuppressWarnings("rawtypes")
@Override
public boolean isUnwrappableAs(Class unwrapType) {
return false;
}
@Override
public <T> T unwrap(Class<T> unwrapType) {
return null;
}
@Override
public Connection getConnection() {
return connection;
}
@Override
public void closeConnection(Connection conn) throws SQLException {}

@Override
public boolean supportsAggressiveRelease() {
return true;
}
})
.build()
);

to be this:

MetadataSources metadata = new MetadataSources(
new StandardServiceRegistryBuilder()
.applySetting("hibernate.dialect", "org.hibernate.H2Dialect")
.applySetting("javax.persistence.schema-generation-connection", connection)

// [#5607] JPADatabase causes warnings - This prevents them
.applySetting(AvailableSettings.CONNECTION_PROVIDER, "com.myapp.CustomConnectionProvider")
.build()
);

Then I ran the code generation using com.myapp.CustomJPADatabase instead of org.jooq.util.jpa.JPADatabase and everything worked fine and code was generated. Of course I wish it just worked out of the box instead of having to do this hack.

Lukas Eder

未讀,
2016年12月2日 上午8:43:502016/12/2
收件者:jooq...@googlegroups.com
Hi Ahmed,

Thanks for your report.

This is a regression that came in with https://github.com/jOOQ/jOOQ/issues/5607 (merged via https://github.com/jOOQ/jOOQ/issues/5611). In jOOQ 3.9, the Hibernate dependency was upgraded to 5.2, where the code you've replaced works as expected.

I've created another issue to revert this regression:

Thanks again!
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+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

回覆所有人
回覆作者
轉寄
0 則新訊息