HHH-7950 bind custom tuplizer on composite attribute

This commit is contained in:
Strong Liu 2013-01-28 22:36:59 +08:00
parent 2922922133
commit 34c3cec657
33 changed files with 341 additions and 236 deletions

View File

@ -89,7 +89,7 @@ public class BeanValidationEventListener
init( factory, properties );
}
}
@Override
public boolean onPreInsert(PreInsertEvent event) {
validate(
event.getEntity(), event.getPersister().getEntityMode(), event.getPersister(),
@ -97,7 +97,7 @@ public class BeanValidationEventListener
);
return false;
}
@Override
public boolean onPreUpdate(PreUpdateEvent event) {
validate(
event.getEntity(), event.getPersister().getEntityMode(), event.getPersister(),
@ -105,7 +105,7 @@ public class BeanValidationEventListener
);
return false;
}
@Override
public boolean onPreDelete(PreDeleteEvent event) {
validate(
event.getEntity(), event.getPersister().getEntityMode(), event.getPersister(),

View File

@ -31,6 +31,7 @@ import java.util.Properties;
import javax.validation.groups.Default;
import org.hibernate.HibernateException;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.internal.util.ReflectHelper;
/**
@ -44,12 +45,18 @@ public class GroupsPerOperation {
private static final Class<?>[] EMPTY_GROUPS = new Class<?>[] { };
private Map<Operation, Class<?>[]> groupsPerOperation = new HashMap<Operation, Class<?>[]>(4);
private ClassLoaderService classLoaderService;
public GroupsPerOperation(Properties properties) {
this(properties, null);
}
public GroupsPerOperation(Properties properties, ClassLoaderService classLoaderService){
setGroupsForOperation( Operation.INSERT, properties );
setGroupsForOperation( Operation.UPDATE, properties );
setGroupsForOperation( Operation.DELETE, properties );
setGroupsForOperation( Operation.DDL, properties );
this.classLoaderService = classLoaderService;
}
private void setGroupsForOperation(Operation operation, Properties properties) {
@ -71,11 +78,16 @@ public class GroupsPerOperation {
for (String groupName : groupNames) {
String cleanedGroupName = groupName.trim();
if ( cleanedGroupName.length() > 0) {
try {
groupsList.add( ReflectHelper.classForName( cleanedGroupName ) );
if ( classLoaderService != null ) {
groupsList.add( classLoaderService.classForName( cleanedGroupName ) );
}
catch ( ClassNotFoundException e ) {
throw new HibernateException( "Unable to load class " + cleanedGroupName, e );
else {
try {
groupsList.add( ReflectHelper.classForName( cleanedGroupName ) );
}
catch ( ClassNotFoundException e ) {
throw new HibernateException( "Unable to load class " + cleanedGroupName, e );
}
}
}
}

View File

@ -143,7 +143,7 @@ class TypeSafeActivator {
for ( PersistentClass persistentClass : persistentClasses ) {
final String className = persistentClass.getClassName();
if ( className == null || className.length() == 0 ) {
if ( StringHelper.isEmpty( className ) ) {
continue;
}
Class<?> clazz;
@ -251,7 +251,7 @@ class TypeSafeActivator {
ClassLoaderService classLoaderService,
Dialect dialect) {
final ValidatorFactory factory = getValidatorFactory( properties );
final Class<?>[] groupsArray = new GroupsPerOperation( properties ).get( GroupsPerOperation.Operation.DDL );
final Class<?>[] groupsArray = new GroupsPerOperation( properties, classLoaderService ).get( GroupsPerOperation.Operation.DDL );
final Set<Class<?>> groups = new HashSet<Class<?>>( Arrays.asList( groupsArray ) );
for ( EntityBinding binding : bindings ) {

View File

@ -76,8 +76,8 @@ public class DerbyDialect extends DB2Dialect {
final Class sysinfoClass = ReflectHelper.classForName( "org.apache.derby.tools.sysinfo", this.getClass() );
final Method majorVersionGetter = sysinfoClass.getMethod( "getMajorVersion", ReflectHelper.NO_PARAM_SIGNATURE );
final Method minorVersionGetter = sysinfoClass.getMethod( "getMinorVersion", ReflectHelper.NO_PARAM_SIGNATURE );
driverVersionMajor = ( (Integer) majorVersionGetter.invoke( null, ReflectHelper.NO_PARAMS ) ).intValue();
driverVersionMinor = ( (Integer) minorVersionGetter.invoke( null, ReflectHelper.NO_PARAMS ) ).intValue();
driverVersionMajor = (Integer) majorVersionGetter.invoke( null, ReflectHelper.NO_PARAMS );
driverVersionMinor = (Integer) minorVersionGetter.invoke( null, ReflectHelper.NO_PARAMS );
}
catch ( Exception e ) {
LOG.unableToLoadDerbyDriver( e.getMessage() );
@ -229,11 +229,7 @@ public String getForUpdateString() {
}
private int getWithIndex(String querySelect) {
int i = querySelect.lastIndexOf( "with " );
if ( i < 0 ) {
i = querySelect.lastIndexOf( "WITH " );
}
return i;
return querySelect.toLowerCase().lastIndexOf( "with " );
}
@Override

View File

@ -28,6 +28,7 @@ import java.util.TreeMap;
import org.hibernate.MappingException;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
/**
* This class maps a type to names. Associations
@ -63,8 +64,8 @@ import org.hibernate.internal.util.StringHelper;
*/
public class TypeNames {
private Map<Integer, Map<Long, String>> weighted = new HashMap<Integer, Map<Long, String>>();
private Map<Integer, String> defaults = new HashMap<Integer, String>();
private final Map<Integer, Map<Long, String>> weighted = new HashMap<Integer, Map<Long, String>>();
private final Map<Integer, String> defaults = new HashMap<Integer, String>();
/**
* get default type name for specified type
@ -88,11 +89,11 @@ public class TypeNames {
*/
public String get(int typeCode, long size, int precision, int scale) throws MappingException {
Map<Long, String> map = weighted.get( typeCode );
if ( map!=null && map.size()>0 ) {
if ( CollectionHelper.isNotEmpty( map ) ) {
// iterate entries ordered by capacity to find first fit
for (Map.Entry<Long, String> entry: map.entrySet()) {
if ( size <= entry.getKey() ) {
return replace( entry.getValue(), size, precision, scale );
for ( final Long key : map.keySet() ) {
if ( size <= key ) {
return replace( map.get( key ), size, precision, scale );
}
}
}

View File

@ -61,6 +61,9 @@ import org.hibernate.service.spi.Stoppable;
public class DriverManagerConnectionProviderImpl
implements ConnectionProvider, Configurable, Stoppable, ServiceRegistryAwareService {
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, DriverManagerConnectionProviderImpl.class.getName() );
private static final boolean traceEnabled = LOG.isTraceEnabled();
private static final boolean debugEnabled = LOG.isDebugEnabled();
private String url;
private Properties connectionProps;
@ -92,7 +95,7 @@ public class DriverManagerConnectionProviderImpl
throw new UnknownUnwrapTypeException( unwrapType );
}
}
@Override
public void configure(Map configurationValues) {
LOG.usingHibernateBuiltInConnectionPool();
@ -148,12 +151,12 @@ public class DriverManagerConnectionProviderImpl
LOG.usingDriver( driverClassName, url );
// if debug level is enabled, then log the password, otherwise mask it
if ( LOG.isDebugEnabled() )
if ( debugEnabled )
LOG.connectionProperties( connectionProps );
else
LOG.connectionProperties( ConfigurationHelper.maskOut( connectionProps, "password" ) );
}
@Override
public void stop() {
LOG.cleaningUpConnectionPool( url );
@ -168,9 +171,8 @@ public class DriverManagerConnectionProviderImpl
pool.clear();
stopped = true;
}
@Override
public Connection getConnection() throws SQLException {
final boolean traceEnabled = LOG.isTraceEnabled();
if ( traceEnabled ) LOG.tracev( "Total checked-out connections: {0}", checkedOut.intValue() );
// essentially, if we have available connections in the pool, use one...
@ -191,8 +193,6 @@ public class DriverManagerConnectionProviderImpl
}
// otherwise we open a new connection...
final boolean debugEnabled = LOG.isDebugEnabled();
if ( debugEnabled ) LOG.debug( "Opening new JDBC connection" );
Connection conn = DriverManager.getConnection( url, connectionProps );
@ -210,11 +210,9 @@ public class DriverManagerConnectionProviderImpl
checkedOut.incrementAndGet();
return conn;
}
@Override
public void closeConnection(Connection conn) throws SQLException {
checkedOut.decrementAndGet();
final boolean traceEnabled = LOG.isTraceEnabled();
// add to the pool if the max size is not yet reached.
synchronized ( pool ) {
int currentSize = pool.size();
@ -224,7 +222,6 @@ public class DriverManagerConnectionProviderImpl
return;
}
}
LOG.debug( "Closing JDBC connection" );
conn.close();
}
@ -236,7 +233,7 @@ public class DriverManagerConnectionProviderImpl
}
super.finalize();
}
@Override
public boolean supportsAggressiveRelease() {
return false;
}

View File

@ -29,6 +29,8 @@ import java.util.List;
import java.util.Set;
import org.hibernate.QueryException;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.hql.internal.QuerySplitter;
import org.hibernate.internal.util.ReflectHelper;
@ -44,7 +46,7 @@ public class SelectParser implements Parser {
//TODO: arithmetic expressions, multiple new Foo(...)
private static final Set COUNT_MODIFIERS = new HashSet();
private static final Set<String> COUNT_MODIFIERS = new HashSet<String>();
static {
COUNT_MODIFIERS.add( "distinct" );
@ -52,7 +54,7 @@ public class SelectParser implements Parser {
COUNT_MODIFIERS.add( "*" );
}
private LinkedList aggregateFuncTokenList = new LinkedList();
private LinkedList<String> aggregateFuncTokenList = new LinkedList<String>();
private boolean ready;
private boolean aggregate;
@ -72,7 +74,7 @@ public class SelectParser implements Parser {
pathExpressionParser.setUseThetaStyleJoin( true );
aggregatePathExpressionParser.setUseThetaStyleJoin( true );
}
@Override
public void token(String token, QueryTranslatorImpl q) throws QueryException {
String lctoken = token.toLowerCase();
@ -92,9 +94,12 @@ public class SelectParser implements Parser {
if ( afterNew ) {
afterNew = false;
try {
holderClass = ReflectHelper.classForName( QuerySplitter.getImportedClass( token, q.getFactory() ) );
final ClassLoaderService classLoaderService = q.getFactory()
.getServiceRegistry()
.getService( ClassLoaderService.class );
holderClass = classLoaderService.classForName( QuerySplitter.getImportedClass( token, q.getFactory() ) );
}
catch ( ClassNotFoundException cnfe ) {
catch ( ClassLoadingException cnfe ) {
throw new QueryException( cnfe );
}
if ( holderClass == null ) throw new QueryException( "class not found: " + token );
@ -238,7 +243,7 @@ public class SelectParser implements Parser {
private SQLFunction getFunction(String name, QueryTranslatorImpl q) {
return q.getFactory().getSqlFunctionRegistry().findSQLFunction( name );
}
@Override
public void start(QueryTranslatorImpl q) {
ready = true;
first = true;
@ -248,7 +253,7 @@ public class SelectParser implements Parser {
holderClass = null;
aggregateFuncTokenList.clear();
}
@Override
public void end(QueryTranslatorImpl q) {
}

View File

@ -30,6 +30,8 @@ import java.util.concurrent.ConcurrentHashMap;
import org.jboss.logging.Logger;
import org.hibernate.MappingException;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.id.Assigned;
@ -66,6 +68,7 @@ public class DefaultIdentifierGeneratorFactory implements MutableIdentifierGener
DefaultIdentifierGeneratorFactory.class.getName());
private transient Dialect dialect;
private transient ClassLoaderService classLoaderService;
private ConcurrentHashMap<String, Class> generatorStrategyToClassNameMap = new ConcurrentHashMap<String, Class>();
/**
@ -133,9 +136,18 @@ public class DefaultIdentifierGeneratorFactory implements MutableIdentifierGener
Class generatorClass = generatorStrategyToClassNameMap.get( strategy );
try {
if ( generatorClass == null ) {
generatorClass = ReflectHelper.classForName( strategy );
if ( classLoaderService != null ) {
generatorClass = classLoaderService.classForName( strategy );
}
else {
generatorClass = ReflectHelper.classForName( strategy );
}
register( strategy, generatorClass );
}
}
catch ( ClassLoadingException e ) {
throw new MappingException( String.format( "Could not interpret id generator strategy [%s]", strategy ) );
}
catch ( ClassNotFoundException e ) {
throw new MappingException( String.format( "Could not interpret id generator strategy [%s]", strategy ) );
}
@ -145,5 +157,6 @@ public class DefaultIdentifierGeneratorFactory implements MutableIdentifierGener
@Override
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
this.dialect = serviceRegistry.getService( JdbcServices.class ).getDialect();
this.classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
}
}

View File

@ -92,7 +92,7 @@ public final class ReflectHelper {
* @return The equals method reference
* @throws NoSuchMethodException Should indicate an attempt to extract equals method from interface.
*/
public static Method extractEqualsMethod(Class clazz) throws NoSuchMethodException {
public static Method extractEqualsMethod(Class<?> clazz) throws NoSuchMethodException {
return clazz.getMethod( "equals", SINGLE_OBJECT_PARAM_SIGNATURE );
}
@ -103,7 +103,7 @@ public final class ReflectHelper {
* @return The hashCode method reference
* @throws NoSuchMethodException Should indicate an attempt to extract hashCode method from interface.
*/
public static Method extractHashCodeMethod(Class clazz) throws NoSuchMethodException {
public static Method extractHashCodeMethod(Class<?> clazz) throws NoSuchMethodException {
return clazz.getMethod( "hashCode", NO_PARAM_SIGNATURE );
}
@ -148,7 +148,7 @@ public final class ReflectHelper {
* @param intf The interface to check it against.
* @return True if the class does implement the interface, false otherwise.
*/
public static boolean implementsInterface(Class clazz, Class intf) {
public static boolean implementsInterface(Class clazz, Class<?> intf) {
assert intf.isInterface() : "Interface to check was not an interface";
return intf.isAssignableFrom( clazz );
}
@ -173,7 +173,12 @@ public final class ReflectHelper {
}
catch ( Throwable ignore ) {
}
return Class.forName( name, true, caller.getClassLoader() );
if ( caller != null ) {
return Class.forName( name, true, caller.getClassLoader() );
}
else {
return Class.forName( name );
}
}
/**
@ -187,15 +192,7 @@ public final class ReflectHelper {
* @throws ClassNotFoundException From {@link Class#forName(String)}.
*/
public static Class classForName(String name) throws ClassNotFoundException {
try {
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
if ( contextClassLoader != null ) {
return contextClassLoader.loadClass(name);
}
}
catch ( Throwable ignore ) {
}
return Class.forName( name );
return classForName( name, null );
}
/**
@ -231,7 +228,7 @@ public final class ReflectHelper {
*/
public static Class reflectedPropertyClass(String className, String name) throws MappingException {
try {
Class clazz = ReflectHelper.classForName( className );
Class clazz = classForName( className );
return getter( clazz, name ).getReturnType();
}
catch ( ClassNotFoundException cnfe ) {
@ -301,7 +298,7 @@ public final class ReflectHelper {
* @return The default constructor.
* @throws PropertyNotFoundException Indicates there was not publicly accessible, no-arg constructor (todo : why PropertyNotFoundException???)
*/
public static Constructor getDefaultConstructor(Class clazz) throws PropertyNotFoundException {
public static Constructor getDefaultConstructor(Class<?> clazz) throws PropertyNotFoundException {
if ( isAbstractClass( clazz ) ) {
return null;
}
@ -378,7 +375,7 @@ public final class ReflectHelper {
throw new PropertyNotFoundException( "no appropriate constructor in class: " + clazz.getName() );
}
public static Method getMethod(Class clazz, Method method) {
public static Method getMethod(Class<?> clazz, Method method) {
try {
return clazz.getMethod( method.getName(), method.getParameterTypes() );
}

View File

@ -40,6 +40,7 @@ import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.MultiTenancyStrategy;
import org.hibernate.TruthValue;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.cfg.ObjectNameNormalizer;
@ -1046,6 +1047,12 @@ public class Binder {
naturalIdMutability,
createMetaAttributeContext( attributeBindingContainer, attributeSource )
);
if ( attributeSource.getExplicitTuplizerClassName() != null ) {
Class tuplizerClass = bindingContext().getServiceRegistry()
.getService( ClassLoaderService.class )
.classForName( attributeSource.getExplicitTuplizerClassName() );
attributeBinding.setCustomComponentTuplizerClass( tuplizerClass );
}
bindAttributes( attributeBinding, attributeSource );
typeHelper.bindAggregatedCompositeAttributeType(
isAttributeIdentifier,

View File

@ -104,7 +104,8 @@ public class ComponentAttributeSourceImpl implements ComponentAttributeSource {
@Override
public String getExplicitTuplizerClassName() {
return embeddableClass.getCustomTuplizer();
return StringHelper.isEmpty( embeddableClass.getCustomTuplizerClass() ) ? embeddableClass.getCustomTuplizer() : embeddableClass
.getCustomTuplizerClass();
}
@Override

View File

@ -99,12 +99,13 @@ public class BasicAttribute extends MappedAttribute {
private final String customReadFragment;
private AttributeTypeResolver resolver;
public static BasicAttribute createSimpleAttribute(String name,
Class<?> attributeType,
Nature attributeNature,
Map<DotName, List<AnnotationInstance>> annotations,
String accessType,
EntityBindingContext context) {
public static BasicAttribute createSimpleAttribute(
String name,
Class<?> attributeType,
Nature attributeNature,
Map<DotName, List<AnnotationInstance>> annotations,
String accessType,
EntityBindingContext context) {
return new BasicAttribute( name, attributeType, attributeNature, accessType, annotations, context );
}
@ -124,7 +125,8 @@ public class BasicAttribute extends MappedAttribute {
annotations,
HibernateDotNames.SOURCE
);
this.versionSourceType = sourceAnnotation !=null ? JandexHelper.getEnumValue( sourceAnnotation, "value", SourceType.class ) : null;
this.versionSourceType = sourceAnnotation !=null ?
JandexHelper.getEnumValue( sourceAnnotation, "value", SourceType.class ) : null;
}
else {
versionSourceType = null;
@ -133,7 +135,7 @@ public class BasicAttribute extends MappedAttribute {
if ( isId() ) {
// an id must be unique and cannot be nullable
for(Column columnValue : getColumnValues()) {
for ( Column columnValue : getColumnValues() ) {
columnValue.setUnique( true );
columnValue.setNullable( false );
}

View File

@ -247,8 +247,8 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
if ( naturalIdAnnotation == null ) {
return SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID;
}
final boolean mutable = naturalIdAnnotation.value( "mutable" ) == null ? false :
naturalIdAnnotation.value( "mutable" ).asBoolean();
final boolean mutable = naturalIdAnnotation.value( "mutable" ) != null && naturalIdAnnotation.value( "mutable" )
.asBoolean();
return mutable ? SingularAttributeBinding.NaturalIdMutability.MUTABLE : SingularAttributeBinding.NaturalIdMutability.IMMUTABLE;
}

View File

@ -54,6 +54,7 @@ import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOv
import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute;
import org.hibernate.metamodel.internal.source.annotations.attribute.MappedAttribute;
import org.hibernate.metamodel.internal.source.annotations.attribute.PluralAssociationAttribute;
import org.hibernate.metamodel.internal.source.annotations.util.AnnotationParserHelper;
import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames;
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
@ -574,11 +575,26 @@ public class ConfiguredClass {
else {
naturalIdMutability = SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID;
}
//tuplizer on field
final AnnotationInstance tuplizersAnnotation = JandexHelper.getSingleAnnotation(
annotations, HibernateDotNames.TUPLIZERS
);
final AnnotationInstance tuplizerAnnotation = JandexHelper.getSingleAnnotation(
annotations,
HibernateDotNames.TUPLIZER
);
final String customTuplizerClass = AnnotationParserHelper.determineCustomTuplizer(
tuplizersAnnotation,
tuplizerAnnotation
);
final EmbeddableHierarchy hierarchy = EmbeddableHierarchy.createEmbeddableHierarchy(
localBindingContext.<Object>locateClassByName( embeddableClassInfo.toString() ),
attributeName,
classAccessType,
naturalIdMutability,
customTuplizerClass,
localBindingContext
);
return hierarchy.getLeaf();
@ -593,10 +609,10 @@ public class ConfiguredClass {
*
* @return an instance of the {@code AttributeType} enum
*/
private MappedAttribute.Nature determineAttributeNature( Map<DotName,
List<AnnotationInstance>> annotations,
Class<?> attributeType,
Class<?> referencedCollectionType ) {
private MappedAttribute.Nature determineAttributeNature(
final Map<DotName,List<AnnotationInstance>> annotations,
final Class<?> attributeType,
final Class<?> referencedCollectionType ) {
EnumSet<MappedAttribute.Nature> discoveredAttributeTypes = EnumSet.noneOf( MappedAttribute.Nature.class );
AnnotationInstance oneToOne = JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_ONE );
if ( oneToOne != null ) {
@ -633,12 +649,10 @@ public class ConfiguredClass {
// annotations. (see HHH-7678)
// However, it's important to ignore this if the field is
// annotated with @EmbeddedId.
ClassInfo typeClassInfo = localBindingContext.getIndex()
.getClassByName( DotName.createSimple( attributeType.getName() ) );
if ( typeClassInfo != null
&& JandexHelper.getSingleAnnotation(
typeClassInfo.annotations(),
JPADotNames.EMBEDDABLE ) != null ) {
if ( isEmbeddableType( attributeType ) ) {
LOG.warn( attributeType.getName() + " has @Embeddable on it, but the attribute of this type in entity["
+ getName()
+ "] doesn't have @Embedded, which may cause compatibility issue" );
discoveredAttributeTypes.add( MappedAttribute.Nature.EMBEDDED );
}
}
@ -771,48 +785,15 @@ public class ConfiguredClass {
return prefix;
}
private String determineCustomTuplizer() {
protected String determineCustomTuplizer() {
final AnnotationInstance tuplizersAnnotation = JandexHelper.getSingleAnnotation(
classInfo, HibernateDotNames.TUPLIZERS
classInfo, HibernateDotNames.TUPLIZERS, ClassInfo.class
);
final AnnotationInstance tuplizerAnnotation = JandexHelper.getSingleAnnotation(
classInfo,
HibernateDotNames.TUPLIZER
HibernateDotNames.TUPLIZER,
ClassInfo.class
);
if ( tuplizersAnnotation != null ) {
AnnotationInstance[] annotations = JandexHelper.getValue(
tuplizersAnnotation,
"value",
AnnotationInstance[].class
);
for ( final AnnotationInstance annotationInstance : annotations ) {
final String impl = findTuplizerImpl( annotationInstance );
if ( StringHelper.isNotEmpty( impl ) ) {
return impl;
}
}
}
else if ( tuplizerAnnotation != null ) {
final String impl = findTuplizerImpl( tuplizerAnnotation );
if ( StringHelper.isNotEmpty( impl ) ) {
return impl;
}
}
return null;
}
private String findTuplizerImpl(final AnnotationInstance tuplizerAnnotation) {
EntityMode mode;
if ( tuplizerAnnotation.value( "entityModeType" ) != null ) {
mode = EntityMode.valueOf( tuplizerAnnotation.value( "entityModeType" ).asEnum() );
}
else if ( tuplizerAnnotation.value( "entityMode" ) != null ) {
mode = EntityMode.parse( tuplizerAnnotation.value( "entityMode" ).asString() );
}
else {
mode = EntityMode.POJO;
}
return mode == EntityMode.POJO ? tuplizerAnnotation.value( "impl" ).asString() : null;
return AnnotationParserHelper.determineCustomTuplizer( tuplizersAnnotation, tuplizerAnnotation );
}
}

View File

@ -41,6 +41,8 @@ import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
public class EmbeddableClass extends ConfiguredClass {
private final String embeddedAttributeName;
private final String parentReferencingAttributeName;
//custom tuplizer defined on the embedded field
private final String customTuplizerClass;
private SingularAttributeBinding.NaturalIdMutability naturalIdMutability;
public EmbeddableClass(
@ -49,11 +51,13 @@ public class EmbeddableClass extends ConfiguredClass {
ConfiguredClass parent,
AccessType defaultAccessType,
SingularAttributeBinding.NaturalIdMutability naturalIdMutability,
String customTuplizerClass,
AnnotationBindingContext context) {
super( classInfo, defaultAccessType, parent, context );
this.embeddedAttributeName = embeddedAttributeName;
this.naturalIdMutability = naturalIdMutability;
this.parentReferencingAttributeName = checkParentAnnotation();
this.customTuplizerClass = customTuplizerClass;
}
private String checkParentAnnotation() {
@ -79,6 +83,10 @@ public class EmbeddableClass extends ConfiguredClass {
public void setNaturalIdMutability(SingularAttributeBinding.NaturalIdMutability naturalIdMutability) {
this.naturalIdMutability = naturalIdMutability;
}
public String getCustomTuplizerClass() {
return customTuplizerClass;
}
}

View File

@ -35,7 +35,7 @@ import org.hibernate.AssertionFailure;
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import static org.hibernate.metamodel.spi.binding.SingularAttributeBinding.NaturalIdMutability;
/**
* Contains information about the access and inheritance type for all classes within a class hierarchy.
@ -45,7 +45,6 @@ import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
public class EmbeddableHierarchy implements Iterable<EmbeddableClass> {
private final AccessType defaultAccessType;
private final List<EmbeddableClass> embeddables;
/**
* Builds the configured class hierarchy for a an embeddable class.
*
@ -56,11 +55,15 @@ public class EmbeddableHierarchy implements Iterable<EmbeddableClass> {
*
* @return a set of {@code ConfiguredClassHierarchy}s. One for each "leaf" entity.
*/
public static EmbeddableHierarchy createEmbeddableHierarchy(Class<?> embeddableClass, String propertyName,
AccessType accessType,
SingularAttributeBinding.NaturalIdMutability naturalIdMutability, AnnotationBindingContext context) {
public static EmbeddableHierarchy createEmbeddableHierarchy(
final Class<?> embeddableClass,
final String propertyName,
final AccessType accessType,
final NaturalIdMutability naturalIdMutability,
final String customTuplizerClass,
final AnnotationBindingContext context) {
ClassInfo embeddableClassInfo = context.getClassInfo( embeddableClass.getName() );
final ClassInfo embeddableClassInfo = context.getClassInfo( embeddableClass.getName() );
if ( embeddableClassInfo == null ) {
throw new AssertionFailure(
String.format(
@ -85,11 +88,10 @@ public class EmbeddableHierarchy implements Iterable<EmbeddableClass> {
Class<?> clazz = embeddableClass;
while ( clazz != null && !clazz.equals( Object.class ) ) {
ClassInfo tmpClassInfo = context.getIndex().getClassByName( DotName.createSimple( clazz.getName() ) );
clazz = clazz.getSuperclass();
if ( tmpClassInfo == null ) {
continue;
}
clazz = clazz.getSuperclass();
classInfoList.add( 0, tmpClassInfo );
}
@ -97,6 +99,7 @@ public class EmbeddableHierarchy implements Iterable<EmbeddableClass> {
classInfoList,
propertyName,
naturalIdMutability,
customTuplizerClass,
context,
accessType
);
@ -104,13 +107,13 @@ public class EmbeddableHierarchy implements Iterable<EmbeddableClass> {
@SuppressWarnings("unchecked")
private EmbeddableHierarchy(
List<ClassInfo> classInfoList,
String propertyName,
SingularAttributeBinding.NaturalIdMutability naturalIdMutability,
AnnotationBindingContext context,
AccessType defaultAccessType) {
final List<ClassInfo> classInfoList,
final String propertyName,
final NaturalIdMutability naturalIdMutability,
final String customTuplizerClass,
final AnnotationBindingContext context,
final AccessType defaultAccessType) {
this.defaultAccessType = defaultAccessType;
// the resolved type for the top level class in the hierarchy
context.resolveAllTypes( classInfoList.get( classInfoList.size() - 1 ).name().toString() );
@ -118,7 +121,7 @@ public class EmbeddableHierarchy implements Iterable<EmbeddableClass> {
ConfiguredClass parent = null;
for ( ClassInfo info : classInfoList ) {
EmbeddableClass embeddable = new EmbeddableClass(
info, propertyName, parent, defaultAccessType,naturalIdMutability, context
info, propertyName, parent, defaultAccessType,naturalIdMutability,customTuplizerClass, context
);
embeddables.add( embeddable );
parent = embeddable;
@ -133,6 +136,7 @@ public class EmbeddableHierarchy implements Iterable<EmbeddableClass> {
/**
* @return An iterator iterating in top down manner over the configured classes in this hierarchy.
*/
@Override
public Iterator<EmbeddableClass> iterator() {
return embeddables.iterator();
}

View File

@ -27,9 +27,12 @@ import java.util.List;
import java.util.Map;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.hibernate.EntityMode;
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.spi.binding.CustomSQL;
/**
@ -69,6 +72,45 @@ public class AnnotationParserHelper {
return new CustomSQL( sql, isCallable, checkStyle );
}
public static String determineCustomTuplizer(
final AnnotationInstance tuplizersAnnotation,
final AnnotationInstance tuplizerAnnotation) {
if ( tuplizersAnnotation != null ) {
AnnotationInstance[] annotations = JandexHelper.getValue(
tuplizersAnnotation,
"value",
AnnotationInstance[].class
);
for ( final AnnotationInstance annotationInstance : annotations ) {
final String impl = findTuplizerImpl( annotationInstance );
if ( StringHelper.isNotEmpty( impl ) ) {
return impl;
}
}
}
else if ( tuplizerAnnotation != null ) {
final String impl = findTuplizerImpl( tuplizerAnnotation );
if ( StringHelper.isNotEmpty( impl ) ) {
return impl;
}
}
return null;
}
private static String findTuplizerImpl(final AnnotationInstance tuplizerAnnotation) {
final EntityMode mode;
if ( tuplizerAnnotation.value( "entityModeType" ) != null ) {
mode = EntityMode.valueOf( tuplizerAnnotation.value( "entityModeType" ).asEnum() );
}
else if ( tuplizerAnnotation.value( "entityMode" ) != null ) {
mode = EntityMode.parse( tuplizerAnnotation.value( "entityMode" ).asString() );
}
else {
mode = EntityMode.POJO;
}
return mode == EntityMode.POJO ? tuplizerAnnotation.value( "impl" ).asString() : null;
}
}

View File

@ -31,6 +31,8 @@ import org.hibernate.metamodel.spi.domain.PluralAttribute;
import org.hibernate.metamodel.spi.domain.SingularAttribute;
import org.hibernate.metamodel.spi.relational.TableSpecification;
import org.hibernate.metamodel.spi.source.MetaAttributeContext;
import org.hibernate.tuple.Tuplizer;
import org.hibernate.tuple.component.ComponentTuplizer;
/**
* A container for attribute bindings that make up composite grouping
@ -91,6 +93,11 @@ public abstract class AbstractCompositeAttributeBindingContainer
return primaryTable;
}
@Override
public Class<? extends ComponentTuplizer> getCustomTuplizerClass() {
return null;
}
protected abstract boolean isModifiable();
@Override

View File

@ -8,14 +8,14 @@
*
* 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.
* Lesser General 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
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* You should have received a copy of the GNU Lesser General License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
@ -32,6 +32,7 @@ import org.hibernate.metamodel.spi.domain.SingularAttribute;
import org.hibernate.metamodel.spi.relational.TableSpecification;
import org.hibernate.metamodel.spi.relational.Value;
import org.hibernate.metamodel.spi.source.MetaAttributeContext;
import org.hibernate.tuple.Tuplizer;
/**
* Common contract for {@link EntityBinding} and {@link CompositeAttributeBinding} in so far as they are both
@ -45,21 +46,21 @@ public interface AttributeBindingContainer {
*
* @return The path base for this container.
*/
public String getPathBase();
String getPathBase();
/**
* Obtain the underlying domain attribute container.
*
* @return The attribute container
*/
public AttributeContainer getAttributeContainer();
AttributeContainer getAttributeContainer();
/**
* Obtain all attribute bindings
*
* @return All attribute bindings
*/
public Iterable<AttributeBinding> attributeBindings();
Iterable<AttributeBinding> attributeBindings();
/**
* Return the number of attribute bindings returned by
@ -68,7 +69,13 @@ public interface AttributeBindingContainer {
* @return the number of attribute bindings returned by
* {@link #attributeBindings()}.
*/
public int attributeBindingSpan();
int attributeBindingSpan();
/**
* Return the custom tuplizer class.
* @return
*/
Class<? extends Tuplizer> getCustomTuplizerClass();
/**
* Locate a specific attribute binding, by its local name.
@ -77,7 +84,7 @@ public interface AttributeBindingContainer {
*
* @return The attribute binding or {@code null} if none could be found.
*/
public AttributeBinding locateAttributeBinding(String name);
AttributeBinding locateAttributeBinding(String name);
/**
* Locate a specific attribute binding, by its values.
@ -86,14 +93,14 @@ public interface AttributeBindingContainer {
*
* @return The attribute binding or {@code null} if none could be found.
*/
public AttributeBinding locateAttributeBinding(List<Value> values);
AttributeBinding locateAttributeBinding(List<Value> values);
/**
* Seeks out the entity binding that is the root of this component path.
*
* @return The entity binding
*/
public EntityBinding seekEntityBinding();
EntityBinding seekEntityBinding();
/**
* Obtain the {@link Class} reference for this attribute container. Generally this is used to perform reflection
@ -101,14 +108,14 @@ public interface AttributeBindingContainer {
*
* @return The {@link Class} reference
*/
public Class<?> getClassReference();
Class<?> getClassReference();
/**
* Obtain the meta-attribute context for this container.
*
* @return The meta-attribute context.
*/
public MetaAttributeContext getMetaAttributeContext();
MetaAttributeContext getMetaAttributeContext();
/**
@ -117,7 +124,7 @@ public interface AttributeBindingContainer {
*
* @return the table specification.
*/
public abstract TableSpecification getPrimaryTable();
TableSpecification getPrimaryTable();
/**
* Factory method for basic attribute bindings.
@ -132,7 +139,7 @@ public interface AttributeBindingContainer {
*
* @return The attribute binding instance.
*/
public BasicAttributeBinding makeBasicAttributeBinding(
BasicAttributeBinding makeBasicAttributeBinding(
SingularAttribute attribute,
List<RelationalValueBinding> relationalValueBindings,
String propertyAccessorName,
@ -154,7 +161,7 @@ public interface AttributeBindingContainer {
*
* @return The attribute binding instance.
*/
public CompositeAttributeBinding makeAggregatedCompositeAttributeBinding(
CompositeAttributeBinding makeAggregatedCompositeAttributeBinding(
SingularAttribute attribute,
SingularAttribute parentReferenceAttribute,
String propertyAccessorName,
@ -176,7 +183,7 @@ public interface AttributeBindingContainer {
* @param isConstrained
* @return The attribute binding instance.
*/
public OneToOneAttributeBinding makeOneToOneAttributeBinding(
OneToOneAttributeBinding makeOneToOneAttributeBinding(
SingularAttribute attribute,
String propertyAccessorName,
boolean includedInOptimisticLocking,
@ -204,7 +211,7 @@ public interface AttributeBindingContainer {
*
* @return The attribute binding instance.
*/
public ManyToOneAttributeBinding makeManyToOneAttributeBinding(
ManyToOneAttributeBinding makeManyToOneAttributeBinding(
SingularAttribute attribute,
String propertyAccessorName,
boolean includedInOptimisticLocking,
@ -229,7 +236,7 @@ public interface AttributeBindingContainer {
*
* @return The attribute binding instance.
*/
public BagBinding makeBagAttributeBinding(
BagBinding makeBagAttributeBinding(
PluralAttribute attribute,
PluralAttributeElementBinding.Nature nature,
SingularAttributeBinding referencedAttributeBinding,
@ -251,7 +258,7 @@ public interface AttributeBindingContainer {
*
* @return The attribute binding instance.
*/
public ListBinding makeListAttributeBinding(
ListBinding makeListAttributeBinding(
PluralAttribute attribute,
PluralAttributeElementBinding.Nature nature,
SingularAttributeBinding referencedAttributeBinding,
@ -274,7 +281,7 @@ public interface AttributeBindingContainer {
*
* @return The attribute binding instance.
*/
public ArrayBinding makeArrayAttributeBinding(
ArrayBinding makeArrayAttributeBinding(
PluralAttribute attribute,
PluralAttributeElementBinding.Nature nature,
SingularAttributeBinding referencedAttributeBinding,
@ -297,7 +304,7 @@ public interface AttributeBindingContainer {
*
* @return The attribute binding instance.
*/
public MapBinding makeMapAttributeBinding(
MapBinding makeMapAttributeBinding(
PluralAttribute attribute,
PluralAttributeElementBinding.Nature elementNature,
PluralAttributeIndexBinding.Nature indexNature,
@ -319,7 +326,7 @@ public interface AttributeBindingContainer {
*
* @return The attribute binding instance.
*/
public SetBinding makeSetAttributeBinding(
SetBinding makeSetAttributeBinding(
PluralAttribute attribute,
PluralAttributeElementBinding.Nature nature,
SingularAttributeBinding referencedAttributeBinding,

View File

@ -38,6 +38,7 @@ import org.hibernate.metamodel.spi.domain.SingularAttribute;
import org.hibernate.metamodel.spi.relational.TableSpecification;
import org.hibernate.metamodel.spi.relational.Value;
import org.hibernate.metamodel.spi.source.MetaAttributeContext;
import org.hibernate.tuple.component.ComponentTuplizer;
/**
* A specialized binding contract for a singular attribute binding that
@ -50,7 +51,7 @@ public class CompositeAttributeBinding
implements SingularNonAssociationAttributeBinding, CompositeAttributeBindingContainer, Cascadeable {
private final AbstractCompositeAttributeBindingContainer compositeAttributeBindingContainer;
private Class<? extends ComponentTuplizer> customComponentTuplizerClass = null;
private CompositeAttributeBinding(
AttributeBindingContainer container,
SingularAttribute attribute,
@ -204,6 +205,15 @@ public class CompositeAttributeBinding
return compositeAttributeBindingContainer.getParentReference();
}
@Override
public Class<? extends ComponentTuplizer> getCustomTuplizerClass() {
return customComponentTuplizerClass;
}
public void setCustomComponentTuplizerClass(Class<? extends ComponentTuplizer> customComponentTuplizerClass) {
this.customComponentTuplizerClass = customComponentTuplizerClass;
}
@Override
public List<RelationalValueBinding> getRelationalValueBindings() {
final List<RelationalValueBinding> bindings = new ArrayList<RelationalValueBinding>();
@ -359,6 +369,8 @@ public class CompositeAttributeBinding
return compositeAttributeBindingContainer.getPrimaryTable();
}
@Override
public BasicAttributeBinding makeBasicAttributeBinding(
SingularAttribute attribute,

View File

@ -24,6 +24,8 @@
package org.hibernate.metamodel.spi.binding;
import org.hibernate.metamodel.spi.domain.SingularAttribute;
import org.hibernate.tuple.Tuplizer;
import org.hibernate.tuple.component.ComponentTuplizer;
/**
* @author Gail Badner
@ -32,4 +34,7 @@ public interface CompositeAttributeBindingContainer
extends AttributeBindingContainer {
boolean isAggregated();
SingularAttribute getParentReference();
@Override
Class<? extends ComponentTuplizer> getCustomTuplizerClass();
}

View File

@ -428,13 +428,13 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
public void setCustomEntityPersisterClass(Class<? extends EntityPersister> customEntityPersisterClass) {
this.customEntityPersisterClass = customEntityPersisterClass;
}
public Class<? extends EntityTuplizer> getCustomEntityTuplizerClass() {
@Override
public Class<? extends EntityTuplizer> getCustomTuplizerClass() {
if ( customEntityTuplizerClass != null ) {
return customEntityTuplizerClass;
}
else if ( superEntityBinding != null ) {
return superEntityBinding.getCustomEntityTuplizerClass();
return superEntityBinding.getCustomTuplizerClass();
}
return null;
}

View File

@ -101,16 +101,15 @@ public class ComponentMetamodel implements Serializable {
// todo : move this to SF per HHH-3517; also see HHH-1907 and ComponentMetamodel
final ComponentTuplizerFactory componentTuplizerFactory = new ComponentTuplizerFactory();
// TODO: provide support for custom tuplizer
final String tuplizerClassName = null;
if ( tuplizerClassName == null ) {
final Class<? extends ComponentTuplizer> tuplizerClass = component.getCustomTuplizerClass();
if ( tuplizerClass == null ) {
componentTuplizer = componentTuplizerFactory.constructDefaultTuplizer(
entityMode, component, isIdentifierMapper
);
}
else {
componentTuplizer = componentTuplizerFactory.constructTuplizer(
tuplizerClassName, component, isIdentifierMapper
tuplizerClass, component, isIdentifierMapper
);
}
}

View File

@ -143,11 +143,11 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer {
}
instantiator = buildInstantiator( componentClass, !component.isAggregated(), optimizer );
}
@Override
public Class getMappedClass() {
return componentClass;
}
@Override
public Object[] getPropertyValues(Object component) throws HibernateException {
if ( component == BackrefPropertyAccessor.UNKNOWN ) {
return new Object[propertySpan];
@ -159,7 +159,7 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer {
return super.getPropertyValues( component );
}
}
@Override
public void setPropertyValues(Object component, Object[] values) throws HibernateException {
if ( optimizer != null && optimizer.getAccessOptimizer() != null ) {
optimizer.getAccessOptimizer().setPropertyValues( component, values );
@ -168,15 +168,15 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer {
super.setPropertyValues( component, values );
}
}
@Override
public Object getParent(Object component) {
return parentGetter.get( component );
}
@Override
public boolean hasParentProperty() {
return parentGetter != null;
}
@Override
public boolean isMethodOf(Method method) {
for ( int i = 0; i < propertySpan; i++ ) {
final Method getterMethod = getters[i].getMethod();
@ -186,15 +186,15 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer {
}
return false;
}
@Override
public void setParent(Object component, Object parent, SessionFactoryImplementor factory) {
parentSetter.set( component, parent, factory );
}
@Override
protected Getter buildGetter(Component component, Property prop) {
return prop.getGetter( component.getComponentClass() );
}
@Override
protected Setter buildSetter(Component component, Property prop) {
return prop.getSetter( component.getComponentClass() );
}
@ -205,43 +205,36 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer {
}
private static Instantiator buildInstantiator(Class<?> mappedClass, boolean isVirtual, ReflectionOptimizer optimizer) {
if (isVirtual && ReflectHelper.isAbstractClass( mappedClass ) ) {
if ( isVirtual && ReflectHelper.isAbstractClass( mappedClass ) ) {
return new ProxiedInstantiator( mappedClass );
}
if ( optimizer == null ) {
return new PojoInstantiator( mappedClass, null );
}
else {
return new PojoInstantiator( mappedClass, optimizer.getInstantiationOptimizer() );
}
final ReflectionOptimizer.InstantiationOptimizer instantiationOptimizer =
optimizer == null ? null : optimizer.getInstantiationOptimizer();
return new PojoInstantiator( mappedClass, instantiationOptimizer );
}
private static class ProxiedInstantiator implements Instantiator {
private final Class proxiedClass;
private final BasicProxyFactory factory;
public ProxiedInstantiator(Class<?> proxyClass) {
public ProxiedInstantiator(final Class<?> proxyClass) {
this.proxiedClass = proxyClass;
if ( proxiedClass.isInterface() ) {
factory = Environment.getBytecodeProvider()
.getProxyFactoryFactory()
.buildBasicProxyFactory( null, new Class[] { proxiedClass } );
}
else {
factory = Environment.getBytecodeProvider()
.getProxyFactoryFactory()
.buildBasicProxyFactory( proxiedClass, null );
}
final boolean isInterface = proxiedClass.isInterface();
final Class superClass = isInterface ? null : proxiedClass;
final Class[] interfaces = isInterface ? new Class[] { proxiedClass } : null;
factory = Environment.getBytecodeProvider()
.getProxyFactoryFactory()
.buildBasicProxyFactory( superClass, interfaces );
}
@Override
public Object instantiate(Serializable id) {
throw new AssertionFailure( "ProxiedInstantiator can only be used to instantiate component" );
}
@Override
public Object instantiate() {
return factory.getProxy();
}
@Override
public boolean isInstance(Object object) {
return proxiedClass.isInstance( object );
}

View File

@ -53,9 +53,7 @@ import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.spi.binding.AttributeBinding;
import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
import org.hibernate.metamodel.spi.binding.EntityBinding;
import org.hibernate.metamodel.spi.binding.EntityIdentifier;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.metamodel.spi.domain.Aggregate;
import org.hibernate.metamodel.spi.domain.Attribute;
@ -584,7 +582,7 @@ public class EntityMetamodel implements Serializable {
entityMode = hasPojoRepresentation ? EntityMode.POJO : EntityMode.MAP;
final EntityTuplizerFactory entityTuplizerFactory = sessionFactory.getSettings().getEntityTuplizerFactory();
Class<? extends EntityTuplizer> tuplizerClass = entityBinding.getCustomEntityTuplizerClass();
Class<? extends EntityTuplizer> tuplizerClass = entityBinding.getCustomTuplizerClass();
if ( tuplizerClass == null ) {
entityTuplizer = entityTuplizerFactory.constructDefaultTuplizer( entityMode, this, entityBinding );

View File

@ -72,7 +72,7 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
private final Class mappedClass;
private final Class proxyInterface;
private final boolean lifecycleImplementor;
private final Set lazyPropertyNames = new HashSet();
private final Set<String> lazyPropertyNames = new HashSet<String>();
private final ReflectionOptimizer optimizer;
private final boolean isInstrumented;
@ -117,6 +117,8 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
super( entityMetamodel, mappedEntity );
this.mappedClass = mappedEntity.getEntity().getClassReference();
this.proxyInterface = mappedEntity.getProxyInterfaceType().getValue();
//with Jandex, if this entity is mapped by annotation, then we already get this info from jandex.
//but i don't know if this mirror improvement worth it.
this.lifecycleImplementor = Lifecycle.class.isAssignableFrom( mappedClass );
this.isInstrumented = entityMetamodel.isInstrumented();

View File

@ -90,7 +90,7 @@ public class ByteArrayBlobType extends AbstractLobType {
int length = array.length;
Byte[] copy = new Byte[length];
for ( int index = 0; index < length ; index++ ) {
copy[index] = Byte.valueOf( array[index].byteValue() );
copy[index] = array[index];
}
return copy;
}
@ -174,7 +174,7 @@ public class ByteArrayBlobType extends AbstractLobType {
int length = bytes.length;
byte[] result = new byte[length];
for ( int i = 0; i < length ; i++ ) {
result[i] = bytes[i].byteValue();
result[i] = bytes[i];
}
return result;
}
@ -183,7 +183,7 @@ public class ByteArrayBlobType extends AbstractLobType {
int length = bytes.length;
Byte[] result = new Byte[length];
for ( int index = 0; index < length ; index++ ) {
result[index] = Byte.valueOf( bytes[index] );
result[index] = bytes[index];
}
return result;
}

View File

@ -32,9 +32,6 @@ import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import org.dom4j.Element;
import org.dom4j.Node;
import org.hibernate.EntityMode;
import org.hibernate.FetchMode;
import org.hibernate.HibernateException;
@ -158,7 +155,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
public final boolean isComponentType() {
return true;
}
@Override
public Class getReturnedClass() {
return componentTuplizer.getMappedClass();
}
@ -327,7 +324,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
return old != null;
}
if ( old == null ) {
return current != null;
return true;
}
Object[] currentValues = getPropertyValues( current, session );
Object[] oldValues = ( Object[] ) old;

View File

@ -33,6 +33,7 @@ import org.dom4j.Node;
import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.Filter;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.engine.internal.ForeignKeys;
@ -416,7 +417,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
return isEmbeddedInXML;
}
public String getOnCondition(String alias, SessionFactoryImplementor factory, Map enabledFilters)
public String getOnCondition(String alias, SessionFactoryImplementor factory, Map<String, Filter> enabledFilters)
throws MappingException {
if ( isReferenceToPrimaryKey() ) { //TODO: this is a bit arbitrary, expose a switch to the user?
return "";
@ -430,10 +431,6 @@ public abstract class EntityType extends AbstractType implements AssociationType
* Resolve an identifier or unique key value
*/
public Object resolve(Object value, SessionImplementor session, Object owner) throws HibernateException {
if ( isNotEmbedded( session ) ) {
return value;
}
if ( value == null ) {
return null;
}
@ -456,10 +453,6 @@ public abstract class EntityType extends AbstractType implements AssociationType
}
protected final Object getIdentifier(Object value, SessionImplementor session) throws HibernateException {
if ( isNotEmbedded(session) ) {
return value;
}
if ( isReferenceToPrimaryKey() ) {
return ForeignKeys.getEntityIdentifierIfNotUnsaved( getAssociatedEntityName(), value, session ); //tolerates nulls
}

View File

@ -73,7 +73,7 @@ public abstract class BaseAnnotationIndexTestCase extends BaseUnitTestCase {
);
AnnotationBindingContext context = new AnnotationBindingContextImpl( meta, index );
return EmbeddableHierarchy.createEmbeddableHierarchy( configuredClasses[0], "", accessType,
naturalIdMutability, context );
naturalIdMutability,null, context );
}
}

View File

@ -1,6 +1,7 @@
//$Id$
package org.hibernate.test.annotations.tuplizer;
import org.hibernate.mapping.Component;
import org.hibernate.metamodel.spi.binding.CompositeAttributeBindingContainer;
import org.hibernate.tuple.Instantiator;
import org.hibernate.tuple.component.PojoComponentTuplizer;
@ -8,12 +9,23 @@ import org.hibernate.tuple.component.PojoComponentTuplizer;
* @author Emmanuel Bernard
*/
public class DynamicComponentTuplizer extends PojoComponentTuplizer {
private final Instantiator instantiator;
public DynamicComponentTuplizer(Component component) {
super( component );
this.instantiator = new DynamicInstantiator(component.getComponentClassName() );
}
public DynamicComponentTuplizer(CompositeAttributeBindingContainer component, boolean isIdentifierMapper) {
super( component, isIdentifierMapper );
this.instantiator = new DynamicInstantiator(component.getClassReference().getName() );
}
protected Instantiator buildInstantiator(Component component) {
return new DynamicInstantiator( component.getComponentClassName() ); //To change body of overridden methods use File | Settings | File Templates.
return new DynamicInstantiator( component.getComponentClassName() );
}
@Override
protected Instantiator getInstantiator() {
return instantiator;
}
}

View File

@ -1,6 +1,8 @@
//$Id$
package org.hibernate.test.annotations.tuplizer;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.metamodel.spi.binding.EntityBinding;
import org.hibernate.property.Getter;
import org.hibernate.property.Setter;
import org.hibernate.proxy.ProxyFactory;
@ -13,19 +15,33 @@ import org.hibernate.tuple.entity.PojoEntityTuplizer;
*/
public class DynamicEntityTuplizer extends PojoEntityTuplizer {
public DynamicEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) {
super( entityMetamodel, mappedEntity );
}
protected Instantiator buildInstantiator(PersistentClass persistentClass) {
return new DynamicInstantiator( persistentClass.getEntityName() );
}
protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) {
// allows defining a custom proxy factory, which is responsible for
// generating lazy proxies for a given entity.
//
// Here we simply use the default...
return super.buildProxyFactory( persistentClass, idGetter, idSetter );
}
public DynamicEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) {
super( entityMetamodel, mappedEntity );
}
public DynamicEntityTuplizer(EntityMetamodel entityMetamodel, EntityBinding mappedEntity) {
super( entityMetamodel, mappedEntity );
}
protected Instantiator buildInstantiator(PersistentClass persistentClass) {
return new DynamicInstantiator( persistentClass.getEntityName() );
}
@Override
protected Instantiator buildInstantiator(EntityBinding entityBinding) {
return new DynamicInstantiator( entityBinding.getEntityName() );
}
@Override
protected ProxyFactory buildProxyFactoryInternal(EntityBinding entityBinding, Getter idGetter, Setter idSetter) {
return super.buildProxyFactoryInternal( entityBinding, idGetter, idSetter );
}
protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) {
// allows defining a custom proxy factory, which is responsible for
// generating lazy proxies for a given entity.
//
// Here we simply use the default...
return super.buildProxyFactory( persistentClass, idGetter, idSetter );
}
}

View File

@ -26,7 +26,6 @@ package org.hibernate.test.annotations.tuplizer;
import org.junit.Test;
import org.hibernate.Session;
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.Assert.assertEquals;
@ -35,7 +34,6 @@ import static org.junit.Assert.assertNotNull;
/**
* @author Emmanuel Bernard
*/
@FailureExpectedWithNewMetamodel
public class TuplizerTest extends BaseCoreFunctionalTestCase {
@Test
public void testEntityTuplizer() throws Exception {
@ -46,7 +44,7 @@ public class TuplizerTest extends BaseCoreFunctionalTestCase {
cuisine.setCountry( country );
Session s = openSession( new EntityNameInterceptor() );
s.getTransaction().begin();
s.persist( cuisine );
s.persist( cuisine );
s.flush();
s.clear();
cuisine = (Cuisine) s.get(Cuisine.class, cuisine.getId() );
@ -59,6 +57,6 @@ public class TuplizerTest extends BaseCoreFunctionalTestCase {
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] { Cuisine.class };
return new Class[] { Cuisine.class, Country.class };
}
}