HHH-9042 - Envers fails with @Converter and AttributeConverter
This commit is contained in:
parent
180e714b7c
commit
22730624fc
|
@ -1695,4 +1695,9 @@ public interface CoreMessageLogger extends BasicLogger {
|
|||
@LogMessage(level = DEBUG)
|
||||
@Message(value = "Creating pooled optimizer (lo) with [incrementSize=%s; returnClass=%s]", id = 467)
|
||||
void creatingPooledLoOptimizer(int incrementSize, String name);
|
||||
|
||||
@LogMessage(level = WARN)
|
||||
@Message(value = "Unable to interpret type [%s] as an AttributeConverter due to an exception : %s", id = 468)
|
||||
void logBadHbmAttributeConverterType(String type, String exceptionMessage);
|
||||
|
||||
}
|
||||
|
|
|
@ -31,8 +31,10 @@ import java.util.Properties;
|
|||
import javax.persistence.AttributeConverter;
|
||||
|
||||
import org.hibernate.FetchMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.common.reflection.XProperty;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.cfg.AttributeConverterDefinition;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
|
@ -44,6 +46,8 @@ import org.hibernate.id.IdentifierGenerator;
|
|||
import org.hibernate.id.IdentityGenerator;
|
||||
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||
import org.hibernate.id.factory.IdentifierGeneratorFactory;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.converter.AttributeConverterSqlTypeDescriptorAdapter;
|
||||
|
@ -55,14 +59,12 @@ import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
|||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptorRegistry;
|
||||
import org.hibernate.usertype.DynamicParameterizedType;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Any value that maps to columns.
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class SimpleValue implements KeyValue {
|
||||
private static final Logger log = Logger.getLogger( SimpleValue.class );
|
||||
private static final CoreMessageLogger log = CoreLogging.messageLogger( SimpleValue.class );
|
||||
|
||||
public static final String DEFAULT_ID_GEN_STRATEGY = "assigned";
|
||||
|
||||
|
@ -96,6 +98,7 @@ public class SimpleValue implements KeyValue {
|
|||
return metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCascadeDeleteEnabled() {
|
||||
return cascadeDeleteEnabled;
|
||||
}
|
||||
|
@ -114,6 +117,7 @@ public class SimpleValue implements KeyValue {
|
|||
columns.add(formula);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFormula() {
|
||||
Iterator iter = getColumnIterator();
|
||||
while ( iter.hasNext() ) {
|
||||
|
@ -123,27 +127,51 @@ public class SimpleValue implements KeyValue {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnSpan() {
|
||||
return columns.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Selectable> getColumnIterator() {
|
||||
return columns.iterator();
|
||||
}
|
||||
|
||||
public List getConstraintColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public String getTypeName() {
|
||||
return typeName;
|
||||
}
|
||||
public void setTypeName(String type) {
|
||||
this.typeName = type;
|
||||
|
||||
public void setTypeName(String typeName) {
|
||||
if ( typeName != null && typeName.startsWith( AttributeConverterTypeAdapter.NAME_PREFIX ) ) {
|
||||
final String converterClassName = typeName.substring( AttributeConverterTypeAdapter.NAME_PREFIX.length() );
|
||||
final ClassLoaderService cls = getMetadata().getMetadataBuildingOptions()
|
||||
.getServiceRegistry()
|
||||
.getService( ClassLoaderService.class );
|
||||
try {
|
||||
final Class<AttributeConverter> converterClass = cls.classForName( converterClassName );
|
||||
attributeConverterDefinition = new AttributeConverterDefinition( converterClass.newInstance(), false );
|
||||
return;
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.logBadHbmAttributeConverterType( typeName, e.getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
this.typeName = typeName;
|
||||
}
|
||||
|
||||
public void setTable(Table table) {
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createForeignKey() throws MappingException {}
|
||||
|
||||
@Override
|
||||
public void createForeignKeyOfEntity(String entityName) {
|
||||
if ( !hasFormula() && !"none".equals(getForeignKeyName())) {
|
||||
ForeignKey fk = table.createForeignKey( getForeignKeyName(), getConstraintColumns(), entityName );
|
||||
|
@ -151,6 +179,7 @@ public class SimpleValue implements KeyValue {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentifierGenerator createIdentifierGenerator(
|
||||
IdentifierGeneratorFactory identifierGeneratorFactory,
|
||||
Dialect dialect,
|
||||
|
@ -445,13 +474,15 @@ public class SimpleValue implements KeyValue {
|
|||
|
||||
// todo : cache the AttributeConverterTypeAdapter in case that AttributeConverter is applied multiple times.
|
||||
|
||||
final String name = String.format(
|
||||
final String name = AttributeConverterTypeAdapter.NAME_PREFIX + attributeConverterDefinition.getAttributeConverter().getClass().getName();
|
||||
final String description = String.format(
|
||||
"BasicType adapter for AttributeConverter<%s,%s>",
|
||||
entityAttributeJavaType.getSimpleName(),
|
||||
databaseColumnJavaType.getSimpleName()
|
||||
);
|
||||
return new AttributeConverterTypeAdapter(
|
||||
name,
|
||||
description,
|
||||
attributeConverterDefinition.getAttributeConverter(),
|
||||
sqlTypeDescriptorAdapter,
|
||||
entityAttributeJavaType,
|
||||
|
|
|
@ -39,7 +39,10 @@ import org.jboss.logging.Logger;
|
|||
public class AttributeConverterTypeAdapter<T> extends AbstractSingleColumnStandardBasicType<T> {
|
||||
private static final Logger log = Logger.getLogger( AttributeConverterTypeAdapter.class );
|
||||
|
||||
public static final String NAME_PREFIX = "converted::";
|
||||
|
||||
private final String name;
|
||||
private final String description;
|
||||
|
||||
private final Class modelType;
|
||||
private final Class jdbcType;
|
||||
|
@ -47,6 +50,7 @@ public class AttributeConverterTypeAdapter<T> extends AbstractSingleColumnStanda
|
|||
|
||||
public AttributeConverterTypeAdapter(
|
||||
String name,
|
||||
String description,
|
||||
AttributeConverter<? extends T,?> attributeConverter,
|
||||
SqlTypeDescriptor sqlTypeDescriptorAdapter,
|
||||
Class modelType,
|
||||
|
@ -54,6 +58,7 @@ public class AttributeConverterTypeAdapter<T> extends AbstractSingleColumnStanda
|
|||
JavaTypeDescriptor<T> entityAttributeJavaTypeDescriptor) {
|
||||
super( sqlTypeDescriptorAdapter, entityAttributeJavaTypeDescriptor );
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.modelType = modelType;
|
||||
this.jdbcType = jdbcType;
|
||||
this.attributeConverter = attributeConverter;
|
||||
|
@ -77,4 +82,9 @@ public class AttributeConverterTypeAdapter<T> extends AbstractSingleColumnStanda
|
|||
public AttributeConverter<? extends T,?> getAttributeConverter() {
|
||||
return attributeConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.envers.test.entities.converter;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.internal.MetadataImpl;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.envers.test.AbstractEnversTest;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BasicModelingTest extends AbstractEnversTest {
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-9042" )
|
||||
public void testMetamodelBuilding() {
|
||||
StandardServiceRegistry ssr = new StandardServiceRegistryBuilder()
|
||||
.applySetting( AvailableSettings.HBM2DDL_AUTO, "create-drop" )
|
||||
.build();
|
||||
try {
|
||||
Metadata metadata = new MetadataSources( ssr )
|
||||
.addAttributeConverter( SexConverter.class )
|
||||
.addAnnotatedClass( Person.class )
|
||||
.buildMetadata();
|
||||
|
||||
( (MetadataImpl) metadata ).validate();
|
||||
|
||||
PersistentClass personBinding = metadata.getEntityBinding( Person.class.getName() );
|
||||
assertNotNull( personBinding );
|
||||
|
||||
PersistentClass personAuditBinding = metadata.getEntityBinding( Person.class.getName() + "_AUD" );
|
||||
assertNotNull( personAuditBinding );
|
||||
}
|
||||
finally {
|
||||
StandardServiceRegistryBuilder.destroy( ssr );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.envers.test.entities.converter;
|
||||
|
||||
import javax.persistence.Convert;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Entity
|
||||
@Audited
|
||||
public class Person {
|
||||
@Id
|
||||
@GeneratedValue( generator = "increment" )
|
||||
@GenericGenerator( name = "increment", strategy="increment" )
|
||||
private Long id;
|
||||
|
||||
@Convert(converter = SexConverter.class)
|
||||
private Sex sex;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.envers.test.entities.converter;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public enum Sex {
|
||||
MALE,
|
||||
FEMALE;
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.envers.test.entities.converter;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SexConverter implements AttributeConverter<Sex, String> {
|
||||
|
||||
@Override
|
||||
public String convertToDatabaseColumn(Sex attribute) {
|
||||
if (attribute == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (attribute) {
|
||||
case MALE: {
|
||||
return "M";
|
||||
}
|
||||
case FEMALE: {
|
||||
return "F";
|
||||
}
|
||||
default: {
|
||||
throw new IllegalArgumentException( "Unexpected Sex model value [" + attribute + "]" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sex convertToEntityAttribute(String dbData) {
|
||||
if (dbData == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( "M".equals( dbData ) ) {
|
||||
return Sex.MALE;
|
||||
}
|
||||
else if ( "F".equals( dbData ) ) {
|
||||
return Sex.FEMALE;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException( "Unexpected Sex db value [" + dbData + "]" );
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue