[#6517] JPADatabase should map JPA AttributeConverter types to generated jOOQ Converter
This commit is contained in:
parent
563e7c7938
commit
b1a49eff15
@ -138,13 +138,6 @@
|
||||
</property>
|
||||
</properties>
|
||||
<includes>.*</includes>
|
||||
<forcedTypes>
|
||||
<forcedType>
|
||||
<userType>java.time.Year</userType>
|
||||
<converter>org.jooq.Converter.of(Integer.class, Year.class, new org.jooq.example.jpa.converters.YearConverter()::convertToEntityAttribute, new org.jooq.example.jpa.converters.YearConverter()::convertToDatabaseColumn)</converter>
|
||||
<expression>RELEASE_YEAR</expression>
|
||||
</forcedType>
|
||||
</forcedTypes>
|
||||
</database>
|
||||
<generate>
|
||||
</generate>
|
||||
|
||||
@ -33,7 +33,7 @@ import org.jooq.impl.SchemaImpl;
|
||||
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
|
||||
public class Public extends SchemaImpl {
|
||||
|
||||
private static final long serialVersionUID = 1252977499;
|
||||
private static final long serialVersionUID = 897816362;
|
||||
|
||||
/**
|
||||
* The reference instance of <code>PUBLIC</code>
|
||||
@ -85,9 +85,9 @@ public class Public extends SchemaImpl {
|
||||
|
||||
private final List<Sequence<?>> getSequences0() {
|
||||
return Arrays.<Sequence<?>>asList(
|
||||
Sequences.SYSTEM_SEQUENCE_5B4EAFE5_365F_441D_BC0D_72B0BA27E6CC,
|
||||
Sequences.SYSTEM_SEQUENCE_65506620_5C73_4217_9913_7AB008A3F158,
|
||||
Sequences.SYSTEM_SEQUENCE_805FDF72_C4BB_4AA3_86DB_0EA4233F1A7C);
|
||||
Sequences.SYSTEM_SEQUENCE_89CD2855_22EA_4F63_95A8_18A79F6EC782,
|
||||
Sequences.SYSTEM_SEQUENCE_BE504C6E_CD12_493D_BEC3_FE5DEDA7FE1A,
|
||||
Sequences.SYSTEM_SEQUENCE_C6201643_1CF6_4072_8443_E47AC449BE9D);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -24,17 +24,17 @@ import org.jooq.impl.SequenceImpl;
|
||||
public class Sequences {
|
||||
|
||||
/**
|
||||
* The sequence <code>PUBLIC.SYSTEM_SEQUENCE_5B4EAFE5_365F_441D_BC0D_72B0BA27E6CC</code>
|
||||
* The sequence <code>PUBLIC.SYSTEM_SEQUENCE_89CD2855_22EA_4F63_95A8_18A79F6EC782</code>
|
||||
*/
|
||||
public static final Sequence<Long> SYSTEM_SEQUENCE_5B4EAFE5_365F_441D_BC0D_72B0BA27E6CC = new SequenceImpl<Long>("SYSTEM_SEQUENCE_5B4EAFE5_365F_441D_BC0D_72B0BA27E6CC", Public.PUBLIC, org.jooq.impl.SQLDataType.BIGINT);
|
||||
public static final Sequence<Long> SYSTEM_SEQUENCE_89CD2855_22EA_4F63_95A8_18A79F6EC782 = new SequenceImpl<Long>("SYSTEM_SEQUENCE_89CD2855_22EA_4F63_95A8_18A79F6EC782", Public.PUBLIC, org.jooq.impl.SQLDataType.BIGINT);
|
||||
|
||||
/**
|
||||
* The sequence <code>PUBLIC.SYSTEM_SEQUENCE_65506620_5C73_4217_9913_7AB008A3F158</code>
|
||||
* The sequence <code>PUBLIC.SYSTEM_SEQUENCE_BE504C6E_CD12_493D_BEC3_FE5DEDA7FE1A</code>
|
||||
*/
|
||||
public static final Sequence<Long> SYSTEM_SEQUENCE_65506620_5C73_4217_9913_7AB008A3F158 = new SequenceImpl<Long>("SYSTEM_SEQUENCE_65506620_5C73_4217_9913_7AB008A3F158", Public.PUBLIC, org.jooq.impl.SQLDataType.BIGINT);
|
||||
public static final Sequence<Long> SYSTEM_SEQUENCE_BE504C6E_CD12_493D_BEC3_FE5DEDA7FE1A = new SequenceImpl<Long>("SYSTEM_SEQUENCE_BE504C6E_CD12_493D_BEC3_FE5DEDA7FE1A", Public.PUBLIC, org.jooq.impl.SQLDataType.BIGINT);
|
||||
|
||||
/**
|
||||
* The sequence <code>PUBLIC.SYSTEM_SEQUENCE_805FDF72_C4BB_4AA3_86DB_0EA4233F1A7C</code>
|
||||
* The sequence <code>PUBLIC.SYSTEM_SEQUENCE_C6201643_1CF6_4072_8443_E47AC449BE9D</code>
|
||||
*/
|
||||
public static final Sequence<Long> SYSTEM_SEQUENCE_805FDF72_C4BB_4AA3_86DB_0EA4233F1A7C = new SequenceImpl<Long>("SYSTEM_SEQUENCE_805FDF72_C4BB_4AA3_86DB_0EA4233F1A7C", Public.PUBLIC, org.jooq.impl.SQLDataType.BIGINT);
|
||||
public static final Sequence<Long> SYSTEM_SEQUENCE_C6201643_1CF6_4072_8443_E47AC449BE9D = new SequenceImpl<Long>("SYSTEM_SEQUENCE_C6201643_1CF6_4072_8443_E47AC449BE9D", Public.PUBLIC, org.jooq.impl.SQLDataType.BIGINT);
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ import org.jooq.impl.TableImpl;
|
||||
@SuppressWarnings({ "all", "unchecked", "rawtypes" })
|
||||
public class Film extends TableImpl<FilmRecord> {
|
||||
|
||||
private static final long serialVersionUID = 1113845742;
|
||||
private static final long serialVersionUID = 1030256935;
|
||||
|
||||
/**
|
||||
* The reference instance of <code>PUBLIC.FILM</code>
|
||||
@ -68,7 +68,7 @@ public class Film extends TableImpl<FilmRecord> {
|
||||
/**
|
||||
* The column <code>PUBLIC.FILM.RELEASE_YEAR</code>.
|
||||
*/
|
||||
public final TableField<FilmRecord, Year> RELEASE_YEAR = createField("RELEASE_YEAR", org.jooq.impl.SQLDataType.INTEGER, this, "", org.jooq.Converter.of(Integer.class, Year.class, new org.jooq.example.jpa.converters.YearConverter()::convertToEntityAttribute, new org.jooq.example.jpa.converters.YearConverter()::convertToDatabaseColumn));
|
||||
public final TableField<FilmRecord, Year> RELEASE_YEAR = createField("RELEASE_YEAR", org.jooq.impl.SQLDataType.INTEGER, this, "", new org.jooq.impl.JPAConverter(org.jooq.example.jpa.converters.YearConverter.class));
|
||||
|
||||
/**
|
||||
* The column <code>PUBLIC.FILM.TITLE</code>.
|
||||
|
||||
@ -17673,6 +17673,14 @@ public class Book {
|
||||
<key>packages</key>
|
||||
<value>com.example.entities</value>
|
||||
</property>
|
||||
|
||||
<!-- Whether JPA 2.1 AttributeConverters should be auto-mapped to jOOQ Converters.
|
||||
Custom <forcedType/> configurations will have a higher priority than these auto-mapped converters.
|
||||
This defaults to true. -->
|
||||
<property>
|
||||
<key>use-attribute-converters</key>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</properties>
|
||||
</database>
|
||||
</generator>]]></xml><html>
|
||||
|
||||
@ -37,22 +37,30 @@ package org.jooq.util.jpa;
|
||||
import static org.jooq.tools.StringUtils.defaultIfBlank;
|
||||
import static org.jooq.tools.StringUtils.isBlank;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.Name;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.jooq.impl.JPAConverter;
|
||||
import org.jooq.tools.JooqLogger;
|
||||
import org.jooq.util.SchemaDefinition;
|
||||
import org.jooq.util.h2.H2Database;
|
||||
import org.jooq.util.jaxb.ForcedType;
|
||||
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
@ -84,11 +92,11 @@ import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
*/
|
||||
public class JPADatabase extends H2Database {
|
||||
|
||||
private static final JooqLogger log = JooqLogger.getLogger(JPADatabase.class);
|
||||
static final String HIBERNATE_DIALECT = SQLDialect.H2.thirdParty().hibernateDialect();
|
||||
static final JooqLogger log = JooqLogger.getLogger(JPADatabase.class);
|
||||
|
||||
private Connection connection;
|
||||
private Connection connection;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@Override
|
||||
protected DSLContext create0() {
|
||||
if (connection == null) {
|
||||
@ -99,38 +107,19 @@ public class JPADatabase extends H2Database {
|
||||
log.warn("No packages defined", "It is highly recommended that you provide explicit packages to scan");
|
||||
}
|
||||
|
||||
boolean useAttributeConverters = Boolean.valueOf(getProperties().getProperty("use-attribute-converters", "true"));
|
||||
|
||||
try {
|
||||
connection = DriverManager.getConnection("jdbc:h2:mem:jooq-meta-extensions", "sa", "");
|
||||
|
||||
MetadataSources metadata = new MetadataSources(
|
||||
new StandardServiceRegistryBuilder()
|
||||
.applySetting("hibernate.dialect", "org.hibernate.dialect.H2Dialect")
|
||||
.applySetting("hibernate.dialect", HIBERNATE_DIALECT)
|
||||
.applySetting("javax.persistence.schema-generation-connection", connection)
|
||||
.applySetting("javax.persistence.create-database-schemas", true)
|
||||
|
||||
// [#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;
|
||||
}
|
||||
})
|
||||
.applySetting(AvailableSettings.CONNECTION_PROVIDER, connectionProvider())
|
||||
.build()
|
||||
);
|
||||
|
||||
@ -154,6 +143,9 @@ public class JPADatabase extends H2Database {
|
||||
// Hibernate 5.2 broke 5.0 API again. Here's how to do this now:
|
||||
SchemaExport export = new SchemaExport();
|
||||
export.create(EnumSet.of(TargetType.DATABASE), metadata.buildMetadata());
|
||||
|
||||
if (useAttributeConverters)
|
||||
loadAttributeConverters(metadata.getAnnotatedClasses());
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new DataAccessException("Error while exporting schema", e);
|
||||
@ -163,6 +155,71 @@ public class JPADatabase extends H2Database {
|
||||
return DSL.using(connection);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
ConnectionProvider connectionProvider() {
|
||||
return 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) {}
|
||||
|
||||
@Override
|
||||
public boolean supportsAggressiveRelease() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private final void loadAttributeConverters(Collection<? extends Class<?>> classes) {
|
||||
try {
|
||||
AttributeConverterExtractor extractor = new AttributeConverterExtractor(this, classes);
|
||||
|
||||
attributesLoop:
|
||||
for (Entry<Name, AttributeConverter<?, ?>> entry : extractor.extract().entrySet()) {
|
||||
Class<?> convertToEntityAttribute = null;
|
||||
|
||||
for (Method method : entry.getValue().getClass().getMethods())
|
||||
if ("convertToEntityAttribute".equals(method.getName()))
|
||||
convertToEntityAttribute = method.getReturnType();
|
||||
|
||||
if (convertToEntityAttribute == null) {
|
||||
log.info("AttributeConverter", "Cannot use AttributeConverter: " + entry.getValue().getClass().getName());
|
||||
continue attributesLoop;
|
||||
}
|
||||
|
||||
// Tables can be fully or partially or not at all qualified. Let's just accept any prefix
|
||||
// to the available qualification
|
||||
String regex = "(.*?\\.)?" + entry.getKey().unquotedName().toString().replace(".", "\\.");
|
||||
ForcedType forcedType = new ForcedType()
|
||||
.withExpression("(?i:" + regex + ")")
|
||||
.withUserType(convertToEntityAttribute.getName())
|
||||
.withConverter(String.format("new %s(%s.class)",
|
||||
JPAConverter.class.getName(),
|
||||
entry.getValue().getClass().getName()
|
||||
));
|
||||
|
||||
log.info("AttributeConverter", "Configuring JPA AttributeConverter: " + toString(forcedType));
|
||||
getConfiguredForcedTypes().add(forcedType);
|
||||
}
|
||||
}
|
||||
|
||||
// AttributeConverter is part of JPA 2.1. Older JPA providers may not have this type, yet
|
||||
catch (NoClassDefFoundError e) {
|
||||
log.info("AttributeConverter", "Cannot load AttributeConverters: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<SchemaDefinition> getSchemata0() throws SQLException {
|
||||
List<SchemaDefinition> result = new ArrayList<SchemaDefinition>(super.getSchemata0());
|
||||
|
||||
@ -997,7 +997,7 @@ public abstract class AbstractDatabase implements Database {
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
static final String toString(final Object object) {
|
||||
protected static final String toString(final Object object) {
|
||||
final StringWriter writer = new StringWriter();
|
||||
|
||||
try {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user