HHH-7108 HHH-6608
This commit is contained in:
parent
45118e729d
commit
d0e13b664a
|
@ -2496,6 +2496,7 @@ public final class AnnotationBinder {
|
|||
value.setPersistentClassName( persistentClassName );
|
||||
value.setMappings( mappings );
|
||||
value.setType( inferredData.getProperty(), inferredData.getClassOrElement() );
|
||||
value.setAccessType( propertyAccessor );
|
||||
id = value.make();
|
||||
}
|
||||
rootClass.setIdentifier( id );
|
||||
|
|
|
@ -268,15 +268,15 @@ public class BinderHelper {
|
|||
*/
|
||||
StringBuilder propertyNameBuffer = new StringBuilder( "_" );
|
||||
propertyNameBuffer.append( associatedClass.getEntityName().replace( '.', '_' ) );
|
||||
propertyNameBuffer.append( "_" ).append( columns[0].getPropertyName() );
|
||||
propertyNameBuffer.append( "_" ).append( columns[0].getPropertyName().replace( '.', '_' ) );
|
||||
String syntheticPropertyName = propertyNameBuffer.toString();
|
||||
//find properties associated to a certain column
|
||||
Object columnOwner = findColumnOwner( ownerEntity, columns[0].getReferencedColumn(), mappings );
|
||||
List<Property> properties = findPropertiesByColumns( columnOwner, columns, mappings );
|
||||
//create an embeddable component
|
||||
Property synthProp = null;
|
||||
Property synthProp = null;
|
||||
if ( properties != null ) {
|
||||
//todo how about properties.size() == 1, this should be much simpler
|
||||
//todo how about properties.size() == 1, this should be much simpler
|
||||
Component embeddedComp = columnOwner instanceof PersistentClass ?
|
||||
new Component( mappings, (PersistentClass) columnOwner ) :
|
||||
new Component( mappings, (Join) columnOwner );
|
||||
|
@ -290,8 +290,8 @@ public class BinderHelper {
|
|||
clone.setNaturalIdentifier( false );
|
||||
clone.setGeneration( property.getGeneration() );
|
||||
embeddedComp.addProperty( clone );
|
||||
}
|
||||
synthProp = new SyntheticProperty();
|
||||
}
|
||||
synthProp = new SyntheticProperty();
|
||||
synthProp.setName( syntheticPropertyName );
|
||||
synthProp.setNodeName( syntheticPropertyName );
|
||||
synthProp.setPersistentClass( ownerEntity );
|
||||
|
@ -300,9 +300,9 @@ public class BinderHelper {
|
|||
synthProp.setValue( embeddedComp );
|
||||
synthProp.setPropertyAccessorName( "embedded" );
|
||||
ownerEntity.addProperty( synthProp );
|
||||
//make it unique
|
||||
//make it unique
|
||||
TableBinder.createUniqueConstraint( embeddedComp );
|
||||
}
|
||||
}
|
||||
else {
|
||||
//TODO use a ToOne type doing a second select
|
||||
StringBuilder columnsList = new StringBuilder();
|
||||
|
@ -830,7 +830,7 @@ public class BinderHelper {
|
|||
for (int i = 0; i < aliases.length; i++){
|
||||
if (StringHelper.isNotEmpty(aliases[i].table())){
|
||||
ret.put(aliases[i].alias(), aliases[i].table());
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1289,6 +1289,8 @@ public abstract class CollectionBinder {
|
|||
}
|
||||
elementBinder.setColumns( elementColumns );
|
||||
elementBinder.setType( property, elementClass );
|
||||
elementBinder.setPersistentClassName( propertyHolder.getEntityName() );
|
||||
elementBinder.setAccessType( accessType );
|
||||
collValue.setElement( elementBinder.make() );
|
||||
String orderBy = adjustUserSuppliedValueCollectionOrderingFragment( hqlOrderBy );
|
||||
if ( orderBy != null ) {
|
||||
|
|
|
@ -210,26 +210,25 @@ public class MapBinder extends CollectionBinder {
|
|||
}
|
||||
}
|
||||
|
||||
PersistentClass owner = mapValue.getOwner();
|
||||
AccessType accessType;
|
||||
// FIXME support @Access for collection of elements
|
||||
// String accessType = access != null ? access.value() : null;
|
||||
if ( owner.getIdentifierProperty() != null ) {
|
||||
accessType = owner.getIdentifierProperty().getPropertyAccessorName().equals( "property" ) ? AccessType.PROPERTY
|
||||
: AccessType.FIELD;
|
||||
}
|
||||
else if ( owner.getIdentifierMapper() != null && owner.getIdentifierMapper().getPropertySpan() > 0 ) {
|
||||
Property prop = (Property) owner.getIdentifierMapper().getPropertyIterator().next();
|
||||
accessType = prop.getPropertyAccessorName().equals( "property" ) ? AccessType.PROPERTY
|
||||
: AccessType.FIELD;
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure( "Unable to guess collection property accessor name" );
|
||||
}
|
||||
|
||||
if ( AnnotatedClassType.EMBEDDABLE.equals( classType ) ) {
|
||||
EntityBinder entityBinder = new EntityBinder();
|
||||
PersistentClass owner = mapValue.getOwner();
|
||||
boolean isPropertyAnnotated;
|
||||
//FIXME support @Access for collection of elements
|
||||
//String accessType = access != null ? access.value() : null;
|
||||
if ( owner.getIdentifierProperty() != null ) {
|
||||
isPropertyAnnotated = owner.getIdentifierProperty()
|
||||
.getPropertyAccessorName()
|
||||
.equals( "property" );
|
||||
}
|
||||
else
|
||||
if ( owner.getIdentifierMapper() != null && owner.getIdentifierMapper().getPropertySpan() > 0 ) {
|
||||
Property prop = (Property) owner.getIdentifierMapper().getPropertyIterator().next();
|
||||
isPropertyAnnotated = prop.getPropertyAccessorName().equals( "property" );
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure( "Unable to guess collection property accessor name" );
|
||||
}
|
||||
|
||||
|
||||
PropertyData inferredData;
|
||||
if ( isHibernateExtensionMapping() ) {
|
||||
|
@ -242,7 +241,7 @@ public class MapBinder extends CollectionBinder {
|
|||
|
||||
//TODO be smart with isNullable
|
||||
Component component = AnnotationBinder.fillComponent(
|
||||
holder, inferredData, isPropertyAnnotated ? AccessType.PROPERTY : AccessType.FIELD, true,
|
||||
holder, inferredData, accessType, true,
|
||||
entityBinder, false, false,
|
||||
true, mappings, inheritanceStatePerClass
|
||||
);
|
||||
|
@ -285,6 +284,8 @@ public class MapBinder extends CollectionBinder {
|
|||
else {
|
||||
elementBinder.setType( property, elementClass );
|
||||
}
|
||||
elementBinder.setPersistentClassName( propertyHolder.getEntityName() );
|
||||
elementBinder.setAccessType( accessType );
|
||||
mapValue.setIndex( elementBinder.make() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,6 +188,7 @@ public class PropertyBinder {
|
|||
simpleValueBinder.setType( property, returnedClass );
|
||||
simpleValueBinder.setMappings( mappings );
|
||||
simpleValueBinder.setReferencedEntityName( referencedEntityName );
|
||||
simpleValueBinder.setAccessType( accessType );
|
||||
SimpleValue propertyValue = simpleValueBinder.make();
|
||||
setValue( propertyValue );
|
||||
return makeProperty();
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
package org.hibernate.cfg.annotations;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.sql.Types;
|
||||
import java.util.Calendar;
|
||||
|
@ -40,15 +41,15 @@ import javax.persistence.MapKeyTemporal;
|
|||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.Parameter;
|
||||
import org.hibernate.annotations.Type;
|
||||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
import org.hibernate.annotations.common.reflection.XProperty;
|
||||
import org.hibernate.annotations.common.util.ReflectHelper;
|
||||
import org.hibernate.cfg.AccessType;
|
||||
import org.hibernate.cfg.AttributeConverterDefinition;
|
||||
import org.hibernate.cfg.BinderHelper;
|
||||
import org.hibernate.cfg.Ejb3Column;
|
||||
|
@ -67,6 +68,8 @@ import org.hibernate.type.PrimitiveCharacterArrayClobType;
|
|||
import org.hibernate.type.SerializableToBlobType;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.WrappedMaterializedBlobType;
|
||||
import org.hibernate.usertype.DynamicParameterizedType;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
|
@ -79,6 +82,7 @@ public class SimpleValueBinder {
|
|||
private Ejb3Column[] columns;
|
||||
private String persistentClassName;
|
||||
private String explicitType = "";
|
||||
private String defaultType = "";
|
||||
private Properties typeParameters = new Properties();
|
||||
private Mappings mappings;
|
||||
private Table table;
|
||||
|
@ -88,6 +92,8 @@ public class SimpleValueBinder {
|
|||
//is a Map key
|
||||
private boolean key;
|
||||
private String referencedEntityName;
|
||||
private XProperty xproperty;
|
||||
private AccessType accessType;
|
||||
|
||||
private AttributeConverterDefinition attributeConverterDefinition;
|
||||
|
||||
|
@ -113,6 +119,10 @@ public class SimpleValueBinder {
|
|||
|
||||
public void setReturnedClassName(String returnedClassName) {
|
||||
this.returnedClassName = returnedClassName;
|
||||
|
||||
if ( defaultType.length() == 0 ) {
|
||||
defaultType = returnedClassName;
|
||||
}
|
||||
}
|
||||
|
||||
public void setTable(Table table) {
|
||||
|
@ -135,15 +145,22 @@ public class SimpleValueBinder {
|
|||
return;
|
||||
} //we cannot guess anything
|
||||
XClass returnedClassOrElement = returnedClass;
|
||||
boolean isArray = false;
|
||||
boolean isArray = false;
|
||||
if ( property.isArray() ) {
|
||||
returnedClassOrElement = property.getElementClass();
|
||||
isArray = true;
|
||||
}
|
||||
this.xproperty = property;
|
||||
Properties typeParameters = this.typeParameters;
|
||||
typeParameters.clear();
|
||||
String type = BinderHelper.ANNOTATION_STRING_DEFAULT;
|
||||
if ( ( !key && property.isAnnotationPresent( Temporal.class ) )
|
||||
|
||||
Type annType = property.getAnnotation( Type.class );
|
||||
if ( annType != null ) {
|
||||
setExplicitType( annType );
|
||||
type = explicitType;
|
||||
}
|
||||
else if ( ( !key && property.isAnnotationPresent( Temporal.class ) )
|
||||
|| ( key && property.isAnnotationPresent( MapKeyTemporal.class ) ) ) {
|
||||
|
||||
boolean isDate;
|
||||
|
@ -179,6 +196,7 @@ public class SimpleValueBinder {
|
|||
default:
|
||||
throw new AssertionFailure( "Unknown temporal type: " + temporalType );
|
||||
}
|
||||
explicitType = type;
|
||||
}
|
||||
else if ( property.isAnnotationPresent( Lob.class ) ) {
|
||||
if ( mappings.getReflectionManager().equals( returnedClassOrElement, java.sql.Clob.class ) ) {
|
||||
|
@ -215,42 +233,27 @@ public class SimpleValueBinder {
|
|||
else {
|
||||
type = "blob";
|
||||
}
|
||||
explicitType = type;
|
||||
}
|
||||
//implicit type will check basic types and Serializable classes
|
||||
else if ( ( !key && property.isAnnotationPresent( Enumerated.class ) )
|
||||
|| ( key && property.isAnnotationPresent( MapKeyEnumerated.class ) ) ) {
|
||||
type = EnumType.class.getName();
|
||||
explicitType = type;
|
||||
}
|
||||
|
||||
// implicit type will check basic types and Serializable classes
|
||||
if ( columns == null ) {
|
||||
throw new AssertionFailure( "SimpleValueBinder.setColumns should be set before SimpleValueBinder.setType" );
|
||||
}
|
||||
|
||||
if ( BinderHelper.ANNOTATION_STRING_DEFAULT.equals( type ) ) {
|
||||
if ( returnedClassOrElement.isEnum() ) {
|
||||
type = EnumType.class.getName();
|
||||
typeParameters = new Properties();
|
||||
typeParameters.setProperty( EnumType.ENUM, returnedClassOrElement.getName() );
|
||||
String schema = columns[0].getTable().getSchema();
|
||||
schema = schema == null ? "" : schema;
|
||||
String catalog = columns[0].getTable().getCatalog();
|
||||
catalog = catalog == null ? "" : catalog;
|
||||
typeParameters.setProperty( EnumType.SCHEMA, schema );
|
||||
typeParameters.setProperty( EnumType.CATALOG, catalog );
|
||||
typeParameters.setProperty( EnumType.TABLE, columns[0].getTable().getName() );
|
||||
typeParameters.setProperty( EnumType.COLUMN, columns[0].getName() );
|
||||
javax.persistence.EnumType enumType = getEnumType( property );
|
||||
if ( enumType != null ) {
|
||||
if ( javax.persistence.EnumType.ORDINAL.equals( enumType ) ) {
|
||||
typeParameters.setProperty( EnumType.TYPE, String.valueOf( Types.INTEGER ) );
|
||||
}
|
||||
else if ( javax.persistence.EnumType.STRING.equals( enumType ) ) {
|
||||
typeParameters.setProperty( EnumType.TYPE, String.valueOf( Types.VARCHAR ) );
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure( "Unknown EnumType: " + enumType );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
explicitType = type;
|
||||
|
||||
defaultType = BinderHelper.isEmptyAnnotationValue( type ) ? returnedClassName : type;
|
||||
this.typeParameters = typeParameters;
|
||||
Type annType = property.getAnnotation( Type.class );
|
||||
setExplicitType( annType );
|
||||
|
||||
applyAttributeConverter( property );
|
||||
}
|
||||
|
@ -448,23 +451,6 @@ public class SimpleValueBinder {
|
|||
throw new AssertionFailure( "Unexpected primitive type (VOID most likely) passed to getWrapperEquivalent" );
|
||||
}
|
||||
|
||||
private javax.persistence.EnumType getEnumType(XProperty property) {
|
||||
javax.persistence.EnumType enumType = null;
|
||||
if ( key ) {
|
||||
MapKeyEnumerated enumAnn = property.getAnnotation( MapKeyEnumerated.class );
|
||||
if ( enumAnn != null ) {
|
||||
enumType = enumAnn.value();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Enumerated enumAnn = property.getAnnotation( Enumerated.class );
|
||||
if ( enumAnn != null ) {
|
||||
enumType = enumAnn.value();
|
||||
}
|
||||
}
|
||||
return enumType;
|
||||
}
|
||||
|
||||
private TemporalType getTemporalType(XProperty property) {
|
||||
if ( key ) {
|
||||
MapKeyTemporal ann = property.getAnnotation( MapKeyTemporal.class );
|
||||
|
@ -557,8 +543,26 @@ public class SimpleValueBinder {
|
|||
simpleValue.setJpaAttributeConverterDefinition( attributeConverterDefinition );
|
||||
}
|
||||
else {
|
||||
String type = BinderHelper.isEmptyAnnotationValue( explicitType ) ? returnedClassName : explicitType;
|
||||
org.hibernate.mapping.TypeDef typeDef = mappings.getTypeDef( type );
|
||||
String type;
|
||||
org.hibernate.mapping.TypeDef typeDef;
|
||||
|
||||
if ( !BinderHelper.isEmptyAnnotationValue( explicitType ) ) {
|
||||
type = explicitType;
|
||||
typeDef = mappings.getTypeDef( type );
|
||||
}
|
||||
else {
|
||||
// try implicit type
|
||||
org.hibernate.mapping.TypeDef implicitTypeDef = mappings.getTypeDef( returnedClassName );
|
||||
if ( implicitTypeDef != null ) {
|
||||
typeDef = implicitTypeDef;
|
||||
type = returnedClassName;
|
||||
}
|
||||
else {
|
||||
typeDef = mappings.getTypeDef( defaultType );
|
||||
type = defaultType;
|
||||
}
|
||||
}
|
||||
|
||||
if ( typeDef != null ) {
|
||||
type = typeDef.getTypeClass();
|
||||
simpleValue.setTypeParameters( typeDef.getParameters() );
|
||||
|
@ -582,10 +586,43 @@ public class SimpleValueBinder {
|
|||
if ( timeStampVersionType != null ) {
|
||||
simpleValue.setTypeName( timeStampVersionType );
|
||||
}
|
||||
|
||||
if ( simpleValue.getTypeName() != null && simpleValue.getTypeName().length() > 0
|
||||
&& simpleValue.getMappings().getTypeResolver().basic( simpleValue.getTypeName() ) == null ) {
|
||||
try {
|
||||
Class typeClass = ReflectHelper.classForName( simpleValue.getTypeName() );
|
||||
|
||||
if ( typeClass != null && DynamicParameterizedType.class.isAssignableFrom( typeClass ) ) {
|
||||
Properties parameters = simpleValue.getTypeParameters();
|
||||
if ( parameters == null ) {
|
||||
parameters = new Properties();
|
||||
}
|
||||
parameters.put( DynamicParameterizedType.IS_DYNAMIC, Boolean.toString( true ) );
|
||||
parameters.put( DynamicParameterizedType.RETURNED_CLASS, returnedClassName );
|
||||
parameters.put( DynamicParameterizedType.IS_PRIMARY_KEY, Boolean.toString( key ) );
|
||||
|
||||
parameters.put( DynamicParameterizedType.ENTITY, persistentClassName );
|
||||
parameters.put( DynamicParameterizedType.PROPERTY, xproperty.getName() );
|
||||
parameters.put( DynamicParameterizedType.ACCESS_TYPE, accessType.getType() );
|
||||
simpleValue.setTypeParameters( parameters );
|
||||
}
|
||||
}
|
||||
catch ( ClassNotFoundException cnfe ) {
|
||||
throw new MappingException( "Could not determine type for: " + simpleValue.getTypeName(), cnfe );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setKey(boolean key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public AccessType getAccessType() {
|
||||
return accessType;
|
||||
}
|
||||
|
||||
public void setAccessType(AccessType accessType) {
|
||||
this.accessType = accessType;
|
||||
}
|
||||
}
|
|
@ -23,6 +23,8 @@
|
|||
*/
|
||||
package org.hibernate.mapping;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.sql.CallableStatement;
|
||||
|
@ -36,9 +38,9 @@ import java.util.Properties;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.FetchMode;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.cfg.AccessType;
|
||||
import org.hibernate.cfg.AttributeConverterDefinition;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.cfg.Mappings;
|
||||
|
@ -49,6 +51,7 @@ import org.hibernate.id.IdentityGenerator;
|
|||
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||
import org.hibernate.id.factory.IdentifierGeneratorFactory;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.property.DirectPropertyAccessor;
|
||||
import org.hibernate.type.AbstractSingleColumnStandardBasicType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
|
@ -61,6 +64,7 @@ import org.hibernate.type.descriptor.sql.BasicExtractor;
|
|||
import org.hibernate.type.descriptor.sql.JdbcTypeJavaClassMappings;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptorRegistry;
|
||||
import org.hibernate.usertype.DynamicParameterizedType;
|
||||
|
||||
/**
|
||||
* Any value that maps to columns.
|
||||
|
@ -324,6 +328,11 @@ public class SimpleValue implements KeyValue {
|
|||
if ( typeName == null ) {
|
||||
throw new MappingException( "No type name" );
|
||||
}
|
||||
if ( typeParameters != null
|
||||
&& Boolean.valueOf( typeParameters.getProperty( DynamicParameterizedType.IS_DYNAMIC ) )
|
||||
&& typeParameters.get( DynamicParameterizedType.PARAMETER_TYPE ) == null ) {
|
||||
createParameterImpl();
|
||||
}
|
||||
|
||||
Type result = mappings.getTypeResolver().heuristicType( typeName, typeParameters );
|
||||
if ( result == null ) {
|
||||
|
@ -331,7 +340,7 @@ public class SimpleValue implements KeyValue {
|
|||
if ( table != null ) {
|
||||
msg += ", at table: " + table.getName();
|
||||
}
|
||||
if ( columns!=null && columns.size()>0 ) {
|
||||
if ( columns != null && columns.size() > 0 ) {
|
||||
msg += ", for columns: " + columns;
|
||||
}
|
||||
throw new MappingException( msg );
|
||||
|
@ -510,4 +519,97 @@ public class SimpleValue implements KeyValue {
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void createParameterImpl() {
|
||||
try {
|
||||
String[] columnsNames = new String[columns.size()];
|
||||
for ( int i = 0; i < columns.size(); i++ ) {
|
||||
columnsNames[i] = ( (Column) columns.get( i ) ).getName();
|
||||
}
|
||||
|
||||
AccessType accessType = AccessType.getAccessStrategy( typeParameters
|
||||
.getProperty( DynamicParameterizedType.ACCESS_TYPE ) );
|
||||
final Class classEntity = ReflectHelper.classForName( typeParameters
|
||||
.getProperty( DynamicParameterizedType.ENTITY ) );
|
||||
final String propertyName = typeParameters.getProperty( DynamicParameterizedType.PROPERTY );
|
||||
|
||||
Annotation[] annotations;
|
||||
if ( accessType == AccessType.FIELD ) {
|
||||
annotations = ( (Field) new DirectPropertyAccessor().getGetter( classEntity, propertyName ).getMember() )
|
||||
.getAnnotations();
|
||||
|
||||
}
|
||||
else {
|
||||
annotations = ReflectHelper.getGetter( classEntity, propertyName ).getMethod().getAnnotations();
|
||||
}
|
||||
|
||||
typeParameters.put(
|
||||
DynamicParameterizedType.PARAMETER_TYPE,
|
||||
new ParameterTypeImpl( ReflectHelper.classForName( typeParameters
|
||||
.getProperty( DynamicParameterizedType.RETURNED_CLASS ) ), annotations, table.getCatalog(),
|
||||
table.getSchema(), table.getName(), Boolean.valueOf( typeParameters
|
||||
.getProperty( DynamicParameterizedType.IS_PRIMARY_KEY ) ), columnsNames ) );
|
||||
|
||||
}
|
||||
catch ( ClassNotFoundException cnfe ) {
|
||||
throw new MappingException( "Could not create DynamicParameterizedType for type: " + typeName, cnfe );
|
||||
}
|
||||
}
|
||||
|
||||
private final class ParameterTypeImpl implements DynamicParameterizedType.ParameterType {
|
||||
|
||||
private final Class returnedClass;
|
||||
private final Annotation[] annotationsMethod;
|
||||
private final String catalog;
|
||||
private final String schema;
|
||||
private final String table;
|
||||
private final boolean primaryKey;
|
||||
private final String[] columns;
|
||||
|
||||
private ParameterTypeImpl(Class returnedClass, Annotation[] annotationsMethod, String catalog, String schema,
|
||||
String table, boolean primaryKey, String[] columns) {
|
||||
this.returnedClass = returnedClass;
|
||||
this.annotationsMethod = annotationsMethod;
|
||||
this.catalog = catalog;
|
||||
this.schema = schema;
|
||||
this.table = table;
|
||||
this.primaryKey = primaryKey;
|
||||
this.columns = columns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getReturnedClass() {
|
||||
return returnedClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Annotation[] getAnnotationsMethod() {
|
||||
return annotationsMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCatalog() {
|
||||
return catalog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchema() {
|
||||
return schema;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimaryKey() {
|
||||
return primaryKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumns() {
|
||||
return columns;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,20 +24,22 @@
|
|||
package org.hibernate.type;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.MapKeyEnumerated;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.usertype.DynamicParameterizedType;
|
||||
import org.hibernate.usertype.EnhancedUserType;
|
||||
import org.hibernate.usertype.ParameterizedType;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Enum type mapper
|
||||
|
@ -49,7 +51,7 @@ import org.hibernate.usertype.ParameterizedType;
|
|||
* @author Hardy Ferentschik
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class EnumType implements EnhancedUserType, ParameterizedType, Serializable {
|
||||
public class EnumType implements EnhancedUserType, DynamicParameterizedType, Serializable {
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, EnumType.class.getName());
|
||||
|
||||
|
@ -168,17 +170,37 @@ public class EnumType implements EnhancedUserType, ParameterizedType, Serializab
|
|||
}
|
||||
|
||||
public void setParameterValues(Properties parameters) {
|
||||
String enumClassName = parameters.getProperty( ENUM );
|
||||
try {
|
||||
enumClass = ReflectHelper.classForName( enumClassName, this.getClass() ).asSubclass( Enum.class );
|
||||
}
|
||||
catch ( ClassNotFoundException exception ) {
|
||||
throw new HibernateException( "Enum class not found", exception );
|
||||
}
|
||||
ParameterType reader = (ParameterType) parameters.get( PARAMETER_TYPE );
|
||||
|
||||
String type = parameters.getProperty( TYPE );
|
||||
if ( type != null ) {
|
||||
sqlType = Integer.decode( type );
|
||||
if ( reader != null ) {
|
||||
enumClass = reader.getReturnedClass().asSubclass( Enum.class );
|
||||
|
||||
javax.persistence.EnumType enumType = getEnumType( reader );
|
||||
if ( enumType != null ) {
|
||||
if ( javax.persistence.EnumType.ORDINAL.equals( enumType ) ) {
|
||||
sqlType = Types.INTEGER;
|
||||
}
|
||||
else if ( javax.persistence.EnumType.STRING.equals( enumType ) ) {
|
||||
sqlType = Types.VARCHAR;
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure( "Unknown EnumType: " + enumType );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
String enumClassName = (String) parameters.get( ENUM );
|
||||
try {
|
||||
enumClass = ReflectHelper.classForName( enumClassName, this.getClass() ).asSubclass( Enum.class );
|
||||
}
|
||||
catch ( ClassNotFoundException exception ) {
|
||||
throw new HibernateException( "Enum class not found", exception );
|
||||
}
|
||||
|
||||
String type = (String) parameters.get( TYPE );
|
||||
if ( type != null ) {
|
||||
sqlType = Integer.decode( type );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,4 +256,30 @@ public class EnumType implements EnhancedUserType, ParameterizedType, Serializab
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private javax.persistence.EnumType getEnumType(ParameterType reader) {
|
||||
javax.persistence.EnumType enumType = null;
|
||||
if ( reader.isPrimaryKey() ) {
|
||||
MapKeyEnumerated enumAnn = getAnnotation( reader.getAnnotationsMethod(), MapKeyEnumerated.class );
|
||||
if ( enumAnn != null ) {
|
||||
enumType = enumAnn.value();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Enumerated enumAnn = getAnnotation( reader.getAnnotationsMethod(), Enumerated.class );
|
||||
if ( enumAnn != null ) {
|
||||
enumType = enumAnn.value();
|
||||
}
|
||||
}
|
||||
return enumType;
|
||||
}
|
||||
|
||||
private <T extends Annotation> T getAnnotation(Annotation[] annotations, Class<T> anClass) {
|
||||
for ( Annotation annotation : annotations ) {
|
||||
if ( anClass.isInstance( annotation ) ) {
|
||||
return (T) annotation;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
package org.hibernate.usertype;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* Types who implements this interface will have in the setParameterValues an
|
||||
* instance of the class DynamicParameterizedType$ParameterType instead of
|
||||
* the key PARAMETER_TYPE = "org.hibernate.type.ParameterType"
|
||||
*
|
||||
* The interface ParameterType provides some methods to read information
|
||||
* dynamically for build the type
|
||||
*
|
||||
* @author Janario Oliveira
|
||||
*/
|
||||
public interface DynamicParameterizedType extends ParameterizedType {
|
||||
public static final String PARAMETER_TYPE = "org.hibernate.type.ParameterType";
|
||||
|
||||
public static final String IS_DYNAMIC = "org.hibernate.type.ParameterType.dynamic";
|
||||
|
||||
public static final String RETURNED_CLASS = "org.hibernate.type.ParameterType.returnedClass";
|
||||
public static final String IS_PRIMARY_KEY = "org.hibernate.type.ParameterType.primaryKey";
|
||||
public static final String ENTITY = "org.hibernate.type.ParameterType.entityClass";
|
||||
public static final String PROPERTY = "org.hibernate.type.ParameterType.propertyName";
|
||||
public static final String ACCESS_TYPE = "org.hibernate.type.ParameterType.accessType";
|
||||
|
||||
public static interface ParameterType {
|
||||
|
||||
public Class getReturnedClass();
|
||||
|
||||
public Annotation[] getAnnotationsMethod();
|
||||
|
||||
public String getCatalog();
|
||||
|
||||
public String getSchema();
|
||||
|
||||
public String getTable();
|
||||
|
||||
public boolean isPrimaryKey();
|
||||
|
||||
public String[] getColumns();
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package org.hibernate.test.annotations.enumerated;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import org.hibernate.annotations.Type;
|
||||
import org.hibernate.annotations.TypeDef;
|
||||
import org.hibernate.annotations.TypeDefs;
|
||||
|
||||
/**
|
||||
* @author Janario Oliveira
|
||||
*/
|
||||
@Entity
|
||||
@TypeDefs({ @TypeDef(typeClass = LastNumberType.class, defaultForType = EntityEnum.LastNumber.class) })
|
||||
public class EntityEnum {
|
||||
|
||||
enum Common {
|
||||
|
||||
A1, A2, B1, B2
|
||||
}
|
||||
|
||||
enum FirstLetter {
|
||||
|
||||
A_LETTER, B_LETTER, C_LETTER
|
||||
}
|
||||
|
||||
enum LastNumber {
|
||||
|
||||
NUMBER_1, NUMBER_2, NUMBER_3
|
||||
}
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private long id;
|
||||
private Common ordinal;
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Common string;
|
||||
@Type(type = "org.hibernate.test.annotations.enumerated.FirstLetterType")
|
||||
private FirstLetter firstLetter;
|
||||
private LastNumber lastNumber;
|
||||
@Enumerated(EnumType.STRING)
|
||||
private LastNumber explicitOverridingImplicit;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Common getOrdinal() {
|
||||
return ordinal;
|
||||
}
|
||||
|
||||
public void setOrdinal(Common ordinal) {
|
||||
this.ordinal = ordinal;
|
||||
}
|
||||
|
||||
public Common getString() {
|
||||
return string;
|
||||
}
|
||||
|
||||
public void setString(Common string) {
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public FirstLetter getFirstLetter() {
|
||||
return firstLetter;
|
||||
}
|
||||
|
||||
public void setFirstLetter(FirstLetter firstLetter) {
|
||||
this.firstLetter = firstLetter;
|
||||
}
|
||||
|
||||
public LastNumber getLastNumber() {
|
||||
return lastNumber;
|
||||
}
|
||||
|
||||
public void setLastNumber(LastNumber lastNumber) {
|
||||
this.lastNumber = lastNumber;
|
||||
}
|
||||
|
||||
public LastNumber getExplicitOverridingImplicit() {
|
||||
return explicitOverridingImplicit;
|
||||
}
|
||||
|
||||
public void setExplicitOverridingImplicit(LastNumber explicitOverridingImplicit) {
|
||||
this.explicitOverridingImplicit = explicitOverridingImplicit;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,335 @@
|
|||
package org.hibernate.test.annotations.enumerated;
|
||||
|
||||
import java.io.Serializable;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.hibernate.type.EnumType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.hibernate.test.annotations.enumerated.EntityEnum.*;
|
||||
|
||||
/**
|
||||
* Test type definition for enum
|
||||
*
|
||||
* @author Janario Oliveira
|
||||
*/
|
||||
public class EnumeratedTypeTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Test
|
||||
public void testTypeDefinition() {
|
||||
Configuration cfg = configuration();
|
||||
PersistentClass pc = cfg.getClassMapping( EntityEnum.class.getName() );
|
||||
|
||||
// ordinal default of EnumType
|
||||
Type ordinalEnum = pc.getProperty( "ordinal" ).getType();
|
||||
assertEquals( Common.class, ordinalEnum.getReturnedClass() );
|
||||
assertEquals( EnumType.class.getName(), ordinalEnum.getName() );
|
||||
|
||||
// string defined by Enumerated(STRING)
|
||||
Type stringEnum = pc.getProperty( "string" ).getType();
|
||||
assertEquals( Common.class, stringEnum.getReturnedClass() );
|
||||
assertEquals( EnumType.class.getName(), stringEnum.getName() );
|
||||
|
||||
// explicit defined by @Type
|
||||
Type first = pc.getProperty( "firstLetter" ).getType();
|
||||
assertEquals( FirstLetter.class, first.getReturnedClass() );
|
||||
assertEquals( FirstLetterType.class.getName(), first.getName() );
|
||||
|
||||
// implicit defined by @TypeDef in somewhere
|
||||
Type last = pc.getProperty( "lastNumber" ).getType();
|
||||
assertEquals( LastNumber.class, last.getReturnedClass() );
|
||||
assertEquals( LastNumberType.class.getName(), last.getName() );
|
||||
|
||||
// implicit defined by @TypeDef in anywhere, but overrided by Enumerated(STRING)
|
||||
Type implicitOverrideExplicit = pc.getProperty( "explicitOverridingImplicit" ).getType();
|
||||
assertEquals( LastNumber.class, implicitOverrideExplicit.getReturnedClass() );
|
||||
assertEquals( EnumType.class.getName(), implicitOverrideExplicit.getName() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTypeQuery() {
|
||||
Session session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// persist
|
||||
EntityEnum entityEnum = new EntityEnum();
|
||||
entityEnum.setOrdinal( Common.A2 );
|
||||
Serializable id = session.save( entityEnum );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// find
|
||||
entityEnum = (EntityEnum) session.createQuery( "from EntityEnum ee where ee.ordinal=1" ).uniqueResult();
|
||||
assertEquals( id, entityEnum.getId() );
|
||||
assertEquals( Common.A2, entityEnum.getOrdinal() );
|
||||
// find parameter
|
||||
entityEnum = (EntityEnum) session.createQuery( "from EntityEnum ee where ee.ordinal=:ordinal" )
|
||||
.setParameter( "ordinal", Common.A2 ).uniqueResult();
|
||||
assertEquals( id, entityEnum.getId() );
|
||||
assertEquals( Common.A2, entityEnum.getOrdinal() );
|
||||
// delete
|
||||
assertEquals( 1, session.createSQLQuery( "DELETE FROM EntityEnum where ordinal=1" ).executeUpdate() );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
// **************
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// persist
|
||||
entityEnum = new EntityEnum();
|
||||
entityEnum.setString( Common.B1 );
|
||||
id = session.save( entityEnum );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// find
|
||||
entityEnum = (EntityEnum) session.createQuery( "from EntityEnum ee where ee.string='B1'" ).uniqueResult();
|
||||
assertEquals( id, entityEnum.getId() );
|
||||
assertEquals( Common.B1, entityEnum.getString() );
|
||||
// find parameter
|
||||
entityEnum = (EntityEnum) session.createQuery( "from EntityEnum ee where ee.string=:string" )
|
||||
.setParameter( "string", Common.B1 ).uniqueResult();
|
||||
assertEquals( id, entityEnum.getId() );
|
||||
assertEquals( Common.B1, entityEnum.getString() );
|
||||
// delete
|
||||
assertEquals( 1, session.createSQLQuery( "DELETE FROM EntityEnum where string='B1'" ).executeUpdate() );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
// **************
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// persist
|
||||
entityEnum = new EntityEnum();
|
||||
entityEnum.setFirstLetter( FirstLetter.C_LETTER );
|
||||
id = session.save( entityEnum );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// find
|
||||
entityEnum = (EntityEnum) session.createQuery( "from EntityEnum ee where ee.firstLetter='C'" ).uniqueResult();
|
||||
assertEquals( id, entityEnum.getId() );
|
||||
assertEquals( FirstLetter.C_LETTER, entityEnum.getFirstLetter() );
|
||||
// find parameter
|
||||
entityEnum = (EntityEnum) session.createQuery( "from EntityEnum ee where ee.firstLetter=:firstLetter" )
|
||||
.setParameter( "firstLetter", FirstLetter.C_LETTER ).uniqueResult();
|
||||
assertEquals( id, entityEnum.getId() );
|
||||
assertEquals( FirstLetter.C_LETTER, entityEnum.getFirstLetter() );
|
||||
// delete
|
||||
assertEquals( 1, session.createSQLQuery( "DELETE FROM EntityEnum where firstLetter='C'" ).executeUpdate() );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
// **************
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// persist
|
||||
entityEnum = new EntityEnum();
|
||||
entityEnum.setLastNumber( LastNumber.NUMBER_1 );
|
||||
id = session.save( entityEnum );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// find
|
||||
entityEnum = (EntityEnum) session.createQuery( "from EntityEnum ee where ee.lastNumber='1'" ).uniqueResult();
|
||||
assertEquals( id, entityEnum.getId() );
|
||||
assertEquals( LastNumber.NUMBER_1, entityEnum.getLastNumber() );
|
||||
// find parameter
|
||||
entityEnum = (EntityEnum) session.createQuery( "from EntityEnum ee where ee.lastNumber=:lastNumber" )
|
||||
.setParameter( "lastNumber", LastNumber.NUMBER_1 ).uniqueResult();
|
||||
assertEquals( id, entityEnum.getId() );
|
||||
assertEquals( LastNumber.NUMBER_1, entityEnum.getLastNumber() );
|
||||
// delete
|
||||
assertEquals( 1, session.createSQLQuery( "DELETE FROM EntityEnum where lastNumber='1'" ).executeUpdate() );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
// **************
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// persist
|
||||
entityEnum = new EntityEnum();
|
||||
entityEnum.setExplicitOverridingImplicit( LastNumber.NUMBER_2 );
|
||||
id = session.save( entityEnum );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// find
|
||||
entityEnum = (EntityEnum) session.createQuery(
|
||||
"from EntityEnum ee where ee.explicitOverridingImplicit='NUMBER_2'" ).uniqueResult();
|
||||
assertEquals( id, entityEnum.getId() );
|
||||
assertEquals( LastNumber.NUMBER_2, entityEnum.getExplicitOverridingImplicit() );
|
||||
// find parameter
|
||||
entityEnum = (EntityEnum) session
|
||||
.createQuery( "from EntityEnum ee where ee.explicitOverridingImplicit=:override" )
|
||||
.setParameter( "override", LastNumber.NUMBER_2 ).uniqueResult();
|
||||
assertEquals( id, entityEnum.getId() );
|
||||
assertEquals( LastNumber.NUMBER_2, entityEnum.getExplicitOverridingImplicit() );
|
||||
// delete
|
||||
assertEquals( 1, session.createSQLQuery( "DELETE FROM EntityEnum where explicitOverridingImplicit='NUMBER_2'" )
|
||||
.executeUpdate() );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTypeCriteria() {
|
||||
Session session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// persist
|
||||
EntityEnum entityEnum = new EntityEnum();
|
||||
entityEnum.setOrdinal( Common.A1 );
|
||||
Serializable id = session.save( entityEnum );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// find
|
||||
entityEnum = (EntityEnum) session.createCriteria( EntityEnum.class )
|
||||
.add( Restrictions.eq( "ordinal", Common.A1 ) ).uniqueResult();
|
||||
assertEquals( id, entityEnum.getId() );
|
||||
assertEquals( Common.A1, entityEnum.getOrdinal() );
|
||||
// delete
|
||||
assertEquals( 1, session.createSQLQuery( "DELETE FROM EntityEnum where ordinal=0" ).executeUpdate() );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
// **************
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// persist
|
||||
entityEnum = new EntityEnum();
|
||||
entityEnum.setString( Common.B2 );
|
||||
id = session.save( entityEnum );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// find
|
||||
entityEnum = (EntityEnum) session.createCriteria( EntityEnum.class )
|
||||
.add( Restrictions.eq( "string", Common.B2 ) ).uniqueResult();
|
||||
assertEquals( id, entityEnum.getId() );
|
||||
assertEquals( Common.B2, entityEnum.getString() );
|
||||
// delete
|
||||
assertEquals( 1, session.createSQLQuery( "DELETE FROM EntityEnum where string='B2'" ).executeUpdate() );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
// **************
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// persist
|
||||
entityEnum = new EntityEnum();
|
||||
entityEnum.setFirstLetter( FirstLetter.A_LETTER );
|
||||
id = session.save( entityEnum );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// find
|
||||
entityEnum = (EntityEnum) session.createCriteria( EntityEnum.class )
|
||||
.add( Restrictions.eq( "firstLetter", FirstLetter.A_LETTER ) ).uniqueResult();
|
||||
assertEquals( id, entityEnum.getId() );
|
||||
assertEquals( FirstLetter.A_LETTER, entityEnum.getFirstLetter() );
|
||||
// delete
|
||||
assertEquals( 1, session.createSQLQuery( "DELETE FROM EntityEnum where firstLetter='A'" ).executeUpdate() );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
// **************
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// persist
|
||||
entityEnum = new EntityEnum();
|
||||
entityEnum.setLastNumber( LastNumber.NUMBER_3 );
|
||||
id = session.save( entityEnum );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// find
|
||||
entityEnum = (EntityEnum) session.createCriteria( EntityEnum.class )
|
||||
.add( Restrictions.eq( "lastNumber", LastNumber.NUMBER_3 ) ).uniqueResult();
|
||||
assertEquals( id, entityEnum.getId() );
|
||||
assertEquals( LastNumber.NUMBER_3, entityEnum.getLastNumber() );
|
||||
// delete
|
||||
assertEquals( 1, session.createSQLQuery( "DELETE FROM EntityEnum where lastNumber='3'" ).executeUpdate() );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
// **************
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// persist
|
||||
entityEnum = new EntityEnum();
|
||||
entityEnum.setExplicitOverridingImplicit( LastNumber.NUMBER_2 );
|
||||
id = session.save( entityEnum );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
// find
|
||||
entityEnum = (EntityEnum) session.createCriteria( EntityEnum.class )
|
||||
.add( Restrictions.eq( "explicitOverridingImplicit", LastNumber.NUMBER_2 ) ).uniqueResult();
|
||||
assertEquals( id, entityEnum.getId() );
|
||||
assertEquals( LastNumber.NUMBER_2, entityEnum.getExplicitOverridingImplicit() );
|
||||
// delete
|
||||
assertEquals( 1, session.createSQLQuery( "DELETE FROM EntityEnum where explicitOverridingImplicit='NUMBER_2'" )
|
||||
.executeUpdate() );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[] { EntityEnum.class };
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package org.hibernate.test.annotations.enumerated;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
|
||||
/**
|
||||
* @author Janario Oliveira
|
||||
*/
|
||||
public class FirstLetterType extends org.hibernate.type.EnumType {
|
||||
|
||||
@Override
|
||||
public int[] sqlTypes() {
|
||||
return new int[] { Types.VARCHAR };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
|
||||
throws HibernateException, SQLException {
|
||||
String persistValue = (String) rs.getObject( names[0] );
|
||||
if ( rs.wasNull() ) {
|
||||
return null;
|
||||
}
|
||||
return Enum.valueOf( returnedClass(), persistValue + "_LETTER" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session)
|
||||
throws HibernateException, SQLException {
|
||||
if ( value == null ) {
|
||||
st.setNull( index, sqlTypes()[0] );
|
||||
}
|
||||
else {
|
||||
String enumString = ( (Enum<?>) value ).name();
|
||||
st.setObject( index, enumString.charAt( 0 ), sqlTypes()[0] );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package org.hibernate.test.annotations.enumerated;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
|
||||
/**
|
||||
* @author Janario Oliveira
|
||||
*/
|
||||
public class LastNumberType extends org.hibernate.type.EnumType {
|
||||
|
||||
@Override
|
||||
public int[] sqlTypes() {
|
||||
return new int[] { Types.VARCHAR };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
|
||||
throws HibernateException, SQLException {
|
||||
String persistValue = (String) rs.getObject( names[0] );
|
||||
if ( rs.wasNull() ) {
|
||||
return null;
|
||||
}
|
||||
return Enum.valueOf( returnedClass(), "NUMBER_" + persistValue );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session)
|
||||
throws HibernateException, SQLException {
|
||||
if ( value == null ) {
|
||||
st.setNull( index, sqlTypes()[0] );
|
||||
}
|
||||
else {
|
||||
|
||||
String enumString = ( (Enum<?>) value ).name();
|
||||
st.setObject( index, enumString.charAt( enumString.length() - 1 ), sqlTypes()[0] );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package org.hibernate.test.annotations.referencedcolumnname;
|
||||
|
||||
import javax.persistence.AssociationOverride;
|
||||
import javax.persistence.AssociationOverrides;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
|
||||
/**
|
||||
* @author Janario Oliveira
|
||||
*/
|
||||
@Entity
|
||||
public class HousePlaces {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
int id;
|
||||
@Embedded
|
||||
Places places;
|
||||
@Embedded
|
||||
@AssociationOverrides({
|
||||
@AssociationOverride(name = "livingRoom", joinColumns = {
|
||||
@JoinColumn(name = "NEIGHBOUR_LIVINGROOM", referencedColumnName = "NAME"),
|
||||
@JoinColumn(name = "NEIGHBOUR_LIVINGROOM_OWNER", referencedColumnName = "OWNER") }),
|
||||
@AssociationOverride(name = "kitchen", joinColumns = @JoinColumn(name = "NEIGHBOUR_KITCHEN", referencedColumnName = "NAME")) })
|
||||
Places neighbourPlaces;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package org.hibernate.test.annotations.referencedcolumnname;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* @author Janario Oliveira
|
||||
*/
|
||||
@Entity
|
||||
public class Place {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
int id;
|
||||
@Column(name = "NAME")
|
||||
String name;
|
||||
@Column(name = "OWNER")
|
||||
String owner;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package org.hibernate.test.annotations.referencedcolumnname;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinColumns;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
/**
|
||||
* @author Janario Oliveira
|
||||
*/
|
||||
@Embeddable
|
||||
public class Places {
|
||||
|
||||
@ManyToOne(cascade = CascadeType.ALL)
|
||||
@JoinColumns({ @JoinColumn(name = "LIVING_ROOM", referencedColumnName = "NAME"),
|
||||
@JoinColumn(name = "LIVING_ROOM_OWNER", referencedColumnName = "OWNER") })
|
||||
Place livingRoom;
|
||||
@ManyToOne(cascade = CascadeType.ALL)
|
||||
@JoinColumn(name = "KITCHEN", referencedColumnName = "NAME")
|
||||
Place kitchen;
|
||||
}
|
|
@ -30,6 +30,7 @@ import org.junit.Test;
|
|||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
@ -206,6 +207,68 @@ public class ReferencedColumnNameTest extends BaseCoreFunctionalTestCase {
|
|||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManyToOneInsideComponentReferencedColumn() {
|
||||
HousePlaces house = new HousePlaces();
|
||||
house.places = new Places();
|
||||
|
||||
house.places.livingRoom = new Place();
|
||||
house.places.livingRoom.name = "First";
|
||||
house.places.livingRoom.owner = "mine";
|
||||
|
||||
house.places.kitchen = new Place();
|
||||
house.places.kitchen.name = "Kitchen 1";
|
||||
|
||||
house.neighbourPlaces = new Places();
|
||||
house.neighbourPlaces.livingRoom = new Place();
|
||||
house.neighbourPlaces.livingRoom.name = "Neighbour";
|
||||
house.neighbourPlaces.livingRoom.owner = "his";
|
||||
|
||||
house.neighbourPlaces.kitchen = new Place();
|
||||
house.neighbourPlaces.kitchen.name = "His Kitchen";
|
||||
|
||||
Session s = openSession();
|
||||
Transaction tx = s.beginTransaction();
|
||||
s.save( house );
|
||||
s.flush();
|
||||
|
||||
HousePlaces get = (HousePlaces) s.get( HousePlaces.class, house.id );
|
||||
assertEquals( house.id, get.id );
|
||||
|
||||
HousePlaces uniqueResult = (HousePlaces) s.createQuery( "from HousePlaces h where h.places.livingRoom.name='First'" )
|
||||
.uniqueResult();
|
||||
assertNotNull( uniqueResult );
|
||||
assertEquals( uniqueResult.places.livingRoom.name, "First" );
|
||||
assertEquals( uniqueResult.places.livingRoom.owner, "mine" );
|
||||
|
||||
uniqueResult = (HousePlaces) s.createQuery( "from HousePlaces h where h.places.livingRoom.owner=:owner" )
|
||||
.setParameter( "owner", "mine" ).uniqueResult();
|
||||
assertNotNull( uniqueResult );
|
||||
assertEquals( uniqueResult.places.livingRoom.name, "First" );
|
||||
assertEquals( uniqueResult.places.livingRoom.owner, "mine" );
|
||||
|
||||
assertNotNull( s.createCriteria( HousePlaces.class ).add( Restrictions.eq( "places.livingRoom.owner", "mine" ) )
|
||||
.uniqueResult() );
|
||||
|
||||
// override
|
||||
uniqueResult = (HousePlaces) s.createQuery( "from HousePlaces h where h.neighbourPlaces.livingRoom.owner='his'" )
|
||||
.uniqueResult();
|
||||
assertNotNull( uniqueResult );
|
||||
assertEquals( uniqueResult.neighbourPlaces.livingRoom.name, "Neighbour" );
|
||||
assertEquals( uniqueResult.neighbourPlaces.livingRoom.owner, "his" );
|
||||
|
||||
uniqueResult = (HousePlaces) s.createQuery( "from HousePlaces h where h.neighbourPlaces.livingRoom.name=:name" )
|
||||
.setParameter( "name", "Neighbour" ).uniqueResult();
|
||||
assertNotNull( uniqueResult );
|
||||
assertEquals( uniqueResult.neighbourPlaces.livingRoom.name, "Neighbour" );
|
||||
assertEquals( uniqueResult.neighbourPlaces.livingRoom.owner, "his" );
|
||||
|
||||
assertNotNull( s.createCriteria( HousePlaces.class )
|
||||
.add( Restrictions.eq( "neighbourPlaces.livingRoom.owner", "his" ) ).uniqueResult() );
|
||||
|
||||
tx.rollback();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[]{
|
||||
|
@ -219,7 +282,9 @@ public class ReferencedColumnNameTest extends BaseCoreFunctionalTestCase {
|
|||
Item.class,
|
||||
ItemCost.class,
|
||||
Vendor.class,
|
||||
WarehouseItem.class
|
||||
WarehouseItem.class,
|
||||
Place.class,
|
||||
HousePlaces.class
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,10 +64,16 @@ public final class BasicMetadataGenerator {
|
|||
Element type_mapping = prop_mapping.addElement("type");
|
||||
type_mapping.addAttribute("name", typeName);
|
||||
|
||||
for (java.util.Map.Entry paramKeyValue : typeParameters.entrySet()) {
|
||||
Element type_param = type_mapping.addElement("param");
|
||||
type_param.addAttribute("name", (String) paramKeyValue.getKey());
|
||||
type_param.setText((String) paramKeyValue.getValue());
|
||||
|
||||
for (Object object : typeParameters.keySet()) {
|
||||
String keyType = (String) object;
|
||||
String property = typeParameters.getProperty(keyType);
|
||||
|
||||
if (property != null) {
|
||||
Element type_param = type_mapping.addElement("param");
|
||||
type_param.addAttribute("name", keyType);
|
||||
type_param.setText(property);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue