HHH-15847 run AttributeBinders in a SecondPass

so that they can do stuff like register converters and not
have the results hammered by the SecondPass registered by
BasicValueBinder.
This commit is contained in:
Gavin 2022-12-11 14:15:45 +01:00 committed by Gavin King
parent 2b7eb6fc1c
commit 33faa5b060
3 changed files with 24 additions and 36 deletions

View File

@ -1766,6 +1766,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
* Ugh! But we need this done before we ask Envers to produce its entities.
*/
public void processSecondPasses(MetadataBuildingContext buildingContext) {
assert !inSecondPass;
inSecondPass = true;
try {

View File

@ -41,7 +41,6 @@ import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.MappedSuperclass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.RootClass;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.ToOne;
import org.hibernate.mapping.Value;
import org.hibernate.metamodel.spi.EmbeddableInstantiator;
@ -232,8 +231,8 @@ public class PropertyBinder {
basicValueBinder.setAccessType( accessType );
final SimpleValue propertyValue = basicValueBinder.make();
setValue( propertyValue );
value = basicValueBinder.make();
return makeProperty();
}
@ -266,7 +265,7 @@ public class PropertyBinder {
this.isXToMany = xToMany;
}
private Property bind(Property prop) {
private Property bind(Property property) {
if ( isId ) {
final RootClass rootClass = (RootClass) holder.getPersistentClass();
//if an xToMany, it has to be wrapped today.
@ -280,7 +279,7 @@ public class PropertyBinder {
new PropertyPreloadedData(null, null, null),
true,
false,
resolveCustomInstantiator( property, returnedClass ),
resolveCustomInstantiator(this.property, returnedClass ),
buildingContext
);
rootClass.setIdentifier( identifier );
@ -289,7 +288,7 @@ public class PropertyBinder {
rootClass.setIdentifierMapper( identifier );
}
//FIXME is it good enough?
identifier.addProperty( prop );
identifier.addProperty( property );
}
else {
rootClass.setIdentifier( (KeyValue) getValue() );
@ -297,29 +296,34 @@ public class PropertyBinder {
rootClass.setEmbeddedIdentifier( true );
}
else {
rootClass.setIdentifierProperty( prop );
rootClass.setIdentifierProperty( property );
final MappedSuperclass superclass = getMappedSuperclassOrNull(
declaringClass,
inheritanceStatePerClass,
buildingContext
);
if ( superclass != null ) {
superclass.setDeclaredIdentifierProperty(prop);
superclass.setDeclaredIdentifierProperty(property);
}
else {
//we know the property is on the actual entity
rootClass.setDeclaredIdentifierProperty( prop );
rootClass.setDeclaredIdentifierProperty( property );
}
}
}
}
else {
holder.addProperty( prop, columns, declaringClass );
holder.addProperty( property, columns, declaringClass );
}
callAttributeBinders( prop );
if ( buildingContext.getMetadataCollector().isInSecondPass() ) {
callAttributeBinders( property );
}
else {
buildingContext.getMetadataCollector().addSecondPass( persistentClasses -> callAttributeBinders( property ) );
}
return prop;
return property;
}
private Class<? extends EmbeddableInstantiator> resolveCustomInstantiator(XProperty property, XClass embeddableClass) {
@ -370,6 +374,7 @@ public class PropertyBinder {
property.setUpdateable( updatable );
LOG.tracev( "Cascading {0} with {1}", name, cascade );
return property;
}

View File

@ -6,17 +6,13 @@
*/
package org.hibernate.orm.test.mapping.attributebinder;
import java.sql.Types;
import org.hibernate.boot.model.convert.internal.InstanceBasedConverterDescriptor;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.mapping.BasicValue;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.binder.AttributeBinder;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.type.YesNoConverter;
import org.hibernate.type.descriptor.java.BasicJavaType;
import org.hibernate.type.descriptor.jdbc.JdbcType;
//tag::attribute-binder-example[]
/**
@ -29,26 +25,12 @@ public class YesNoBinder implements AttributeBinder<YesNo> {
MetadataBuildingContext buildingContext,
PersistentClass persistentClass,
Property property) {
final BasicValue booleanValueMapping = (BasicValue) property.getValue();
final BasicJavaType<?> javaType = (BasicJavaType<?>) buildingContext.getBootstrapContext()
.getTypeConfiguration()
.getJavaTypeRegistry()
.getDescriptor( Boolean.class );
final JdbcType jdbcType = buildingContext.getBootstrapContext()
.getTypeConfiguration()
.getJdbcTypeRegistry()
.getDescriptor( Types.CHAR );
final InstanceBasedConverterDescriptor converter = new InstanceBasedConverterDescriptor(
YesNoConverter.INSTANCE,
buildingContext.getBootstrapContext().getClassmateContext()
( (SimpleValue) property.getValue() ).setJpaAttributeConverterDescriptor(
new InstanceBasedConverterDescriptor(
YesNoConverter.INSTANCE,
buildingContext.getBootstrapContext().getClassmateContext()
)
);
booleanValueMapping.setExplicitJavaTypeAccess( (typeConfiguration) -> javaType );
booleanValueMapping.setExplicitJdbcTypeAccess( (typeConfiguration) -> jdbcType );
booleanValueMapping.setJpaAttributeConverterDescriptor( converter );
}
}
//end::attribute-binder-example[]