HHH-7108 TypeDef with Enum, included inside of EnumType its own properties to create itself

This commit is contained in:
Janario Oliveira 2012-08-06 23:37:20 -03:00
parent 1fe4baecb9
commit edeecef3cf
13 changed files with 853 additions and 94 deletions

View File

@ -2495,6 +2495,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 );

View File

@ -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 ) {

View File

@ -210,26 +210,25 @@ public class MapBinder extends CollectionBinder {
}
}
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;
AccessType accessType;
// FIXME support @Access for collection of elements
// String accessType = access != null ? access.value() : null;
if ( owner.getIdentifierProperty() != null ) {
isPropertyAnnotated = owner.getIdentifierProperty()
.getPropertyAccessorName()
.equals( "property" );
accessType = owner.getIdentifierProperty().getPropertyAccessorName().equals( "property" ) ? AccessType.PROPERTY
: AccessType.FIELD;
}
else
if ( owner.getIdentifierMapper() != null && owner.getIdentifierMapper().getPropertySpan() > 0 ) {
else if ( owner.getIdentifierMapper() != null && owner.getIdentifierMapper().getPropertySpan() > 0 ) {
Property prop = (Property) owner.getIdentifierMapper().getPropertyIterator().next();
isPropertyAnnotated = prop.getPropertyAccessorName().equals( "property" );
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();
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() );
}
}

View File

@ -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();

View File

@ -24,10 +24,10 @@
package org.hibernate.cfg.annotations;
import java.io.Serializable;
import java.sql.Types;
import java.util.Calendar;
import java.util.Date;
import java.util.Properties;
import javax.persistence.Enumerated;
import javax.persistence.Lob;
import javax.persistence.MapKeyEnumerated;
@ -35,14 +35,14 @@ 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.cfg.AccessType;
import org.hibernate.cfg.BinderHelper;
import org.hibernate.cfg.Ejb3Column;
import org.hibernate.cfg.Ejb3JoinColumn;
@ -51,6 +51,7 @@ import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.cfg.PkDrivenByDefaultMapsIdSecondPass;
import org.hibernate.cfg.SetSimpleValueTypeSecondPass;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.Table;
@ -60,6 +61,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
@ -72,6 +75,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;
@ -81,6 +85,8 @@ public class SimpleValueBinder {
//is a Map key
private boolean key;
private String referencedEntityName;
private XProperty xproperty;
private AccessType accessType;
public void setReferencedEntityName(String referencedEntityName) {
this.referencedEntityName = referencedEntityName;
@ -104,6 +110,10 @@ public class SimpleValueBinder {
public void setReturnedClassName(String returnedClassName) {
this.returnedClassName = returnedClassName;
if ( defaultType.length() == 0 ) {
defaultType = returnedClassName;
}
}
public void setTable(Table table) {
@ -131,10 +141,17 @@ public class SimpleValueBinder {
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;
@ -170,6 +187,7 @@ public class SimpleValueBinder {
default:
throw new AssertionFailure( "Unknown temporal type: " + temporalType );
}
explicitType = type;
}
else if ( property.isAnnotationPresent( Lob.class ) ) {
@ -207,59 +225,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;
this.typeParameters = typeParameters;
Type annType = property.getAnnotation( Type.class );
setExplicitType( annType );
}
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;
defaultType = BinderHelper.isEmptyAnnotationValue( type ) ? returnedClassName : type;
this.typeParameters = typeParameters;
}
private TemporalType getTemporalType(XProperty property) {
@ -341,17 +327,37 @@ public class SimpleValueBinder {
LOG.debugf( "Setting SimpleValue typeName for %s", propertyName );
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() );
}
if ( typeParameters != null && typeParameters.size() != 0 ) {
//explicit type params takes precedence over type def params
simpleValue.setTypeParameters( typeParameters );
}
simpleValue.setTypeName( type );
if ( persistentClassName != null ) {
simpleValue.setTypeUsingReflection( persistentClassName, propertyName );
}
@ -364,9 +370,42 @@ 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;
}
}

View File

@ -22,6 +22,8 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.mapping;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@ -29,6 +31,7 @@ import java.util.Properties;
import org.hibernate.FetchMode;
import org.hibernate.MappingException;
import org.hibernate.cfg.AccessType;
import org.hibernate.cfg.Environment;
import org.hibernate.cfg.Mappings;
import org.hibernate.dialect.Dialect;
@ -38,7 +41,9 @@ 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.Type;
import org.hibernate.usertype.DynamicParameterizedType;
/**
* Any value that maps to columns.
@ -290,19 +295,25 @@ public class SimpleValue implements KeyValue {
}
public Type getType() throws MappingException {
if (typeName==null) {
throw new MappingException("No type name");
if ( typeName == null ) {
throw new MappingException( "No type name" );
}
Type result = mappings.getTypeResolver().heuristicType(typeName, typeParameters);
if (result==null) {
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 ) {
String msg = "Could not determine type for: " + typeName;
if(table != null){
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);
throw new MappingException( msg );
}
return result;
}
@ -351,4 +362,97 @@ public class SimpleValue implements KeyValue {
public boolean[] getColumnUpdateability() {
return getColumnInsertability();
}
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;
}
}
}

View File

@ -24,20 +24,24 @@
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 +53,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,7 +172,26 @@ public class EnumType implements EnhancedUserType, ParameterizedType, Serializab
}
public void setParameterValues(Properties parameters) {
String enumClassName = parameters.getProperty( ENUM );
ParameterType reader = (ParameterType) parameters.get( PARAMETER_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 );
}
@ -176,11 +199,12 @@ public class EnumType implements EnhancedUserType, ParameterizedType, Serializab
throw new HibernateException( "Enum class not found", exception );
}
String type = parameters.getProperty( TYPE );
String type = (String) parameters.get( TYPE );
if ( type != null ) {
sqlType = Integer.decode( type );
}
}
}
/**
* Lazy init of {@link #enumValues}.
@ -234,4 +258,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;
}
}

View File

@ -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 with
* 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();
}
}

View File

@ -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;
}
}

View File

@ -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 };
}
}

View File

@ -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] );
}
}
}

View File

@ -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] );
}
}
}

View File

@ -64,10 +64,15 @@ 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 );
}
}
}
}