very minor cleanups, and more Javadoc in BinderHelper
This commit is contained in:
parent
e2f42cd0bc
commit
38b4e8e01b
|
@ -7,13 +7,15 @@
|
|||
package org.hibernate.boot.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.unmodifiableMap;
|
||||
|
||||
/**
|
||||
* Identifier generator definition, should be immutable.
|
||||
*
|
||||
|
@ -32,12 +34,7 @@ public class IdentifierGeneratorDefinition implements Serializable {
|
|||
final Map<String, String> parameters) {
|
||||
this.name = name;
|
||||
this.strategy = strategy;
|
||||
if ( CollectionHelper.isEmpty( parameters ) ) {
|
||||
this.parameters = Collections.emptyMap();
|
||||
}
|
||||
else {
|
||||
this.parameters = Collections.unmodifiableMap( parameters );
|
||||
}
|
||||
this.parameters = CollectionHelper.isEmpty( parameters ) ? emptyMap() : unmodifiableMap( parameters );
|
||||
}
|
||||
|
||||
public IdentifierGeneratorDefinition(
|
||||
|
@ -53,7 +50,7 @@ public class IdentifierGeneratorDefinition implements Serializable {
|
|||
public IdentifierGeneratorDefinition(String name, String strategy) {
|
||||
this.name = name;
|
||||
this.strategy = strategy;
|
||||
this.parameters = Collections.emptyMap();
|
||||
this.parameters = emptyMap();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -107,26 +107,6 @@ public class BinderHelper {
|
|||
boolean.class.getName()
|
||||
);
|
||||
|
||||
/**
|
||||
* create a property copy reusing the same value
|
||||
*/
|
||||
public static Property shallowCopy(Property property) {
|
||||
Property clone = new SyntheticProperty();
|
||||
clone.setCascade( property.getCascade() );
|
||||
clone.setInsertable( property.isInsertable() );
|
||||
clone.setLazy( property.isLazy() );
|
||||
clone.setName( property.getName() );
|
||||
clone.setNaturalIdentifier( property.isNaturalIdentifier() );
|
||||
clone.setOptimisticLocked( property.isOptimisticLocked() );
|
||||
clone.setOptional( property.isOptional() );
|
||||
clone.setPersistentClass( property.getPersistentClass() );
|
||||
clone.setPropertyAccessorName( property.getPropertyAccessorName() );
|
||||
clone.setSelectable( property.isSelectable() );
|
||||
clone.setUpdateable( property.isUpdateable() );
|
||||
clone.setValue( property.getValue() );
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Here we address a fundamental problem: the {@code @JoinColumn}
|
||||
* annotation specifies the referenced column in the target table
|
||||
|
@ -320,87 +300,86 @@ public class BinderHelper {
|
|||
String propertyName,
|
||||
boolean inverse,
|
||||
PersistentClass associatedClass) {
|
||||
String syntheticPropertyName =
|
||||
"_" + associatedClass.getEntityName().replace('.', '_') +
|
||||
"_" + propertyName.replace('.', '_');
|
||||
if ( inverse ) {
|
||||
// Use a different name for inverse synthetic properties to avoid duplicate properties for self-referencing models
|
||||
syntheticPropertyName += "_inverse";
|
||||
}
|
||||
return syntheticPropertyName;
|
||||
final String syntheticPropertyName =
|
||||
( "_" + associatedClass.getEntityName() + "_" + propertyName )
|
||||
.replace('.', '_');
|
||||
// Use a different name for inverse synthetic properties to
|
||||
// avoid duplicate properties for self-referencing models
|
||||
return inverse ? syntheticPropertyName + "_inverse" : syntheticPropertyName;
|
||||
}
|
||||
|
||||
private static String associationMessage(PersistentClass associatedEntity, AnnotatedJoinColumns joinColumns) {
|
||||
StringBuilder message = new StringBuilder();
|
||||
if ( associatedEntity != null ) {
|
||||
message.append( "'" )
|
||||
.append( associatedEntity.getEntityName() )
|
||||
.append( "." )
|
||||
.append( joinColumns.getPropertyName() )
|
||||
.append( "'" );
|
||||
return "'" + associatedEntity.getEntityName() + "." + joinColumns.getPropertyName() + "'";
|
||||
}
|
||||
else if ( joinColumns.getPropertyHolder() != null ) {
|
||||
return "'" + joinColumns.getPropertyHolder().getEntityName() + "." + joinColumns.getPropertyName() + "'";
|
||||
}
|
||||
else {
|
||||
if ( joinColumns.getPropertyHolder() != null ) {
|
||||
message.append( "'" )
|
||||
.append( joinColumns.getPropertyHolder().getEntityName() )
|
||||
.append( "." )
|
||||
.append( joinColumns.getPropertyName() )
|
||||
.append( "'" );
|
||||
}
|
||||
return "";
|
||||
}
|
||||
return message.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the "synthetic" {@link Component} that holds all the
|
||||
* properties referenced by a foreign key mapping specified as
|
||||
* a list of {@link jakarta.persistence.JoinColumn} annotations
|
||||
* with explicit {@code referencedColumnName()}s.
|
||||
*/
|
||||
private static Property makeSyntheticComponentProperty(
|
||||
PersistentClass ownerEntity,
|
||||
Object persistentClassOrJoin,
|
||||
MetadataBuildingContext context,
|
||||
String syntheticPropertyName,
|
||||
List<Property> properties) {
|
||||
Component embeddedComp = persistentClassOrJoin instanceof PersistentClass
|
||||
final Component embeddedComponent = persistentClassOrJoin instanceof PersistentClass
|
||||
? new Component( context, (PersistentClass) persistentClassOrJoin )
|
||||
: new Component( context, (Join) persistentClassOrJoin );
|
||||
embeddedComp.setComponentClassName( embeddedComp.getOwner().getClassName() );
|
||||
embeddedComp.setEmbedded( true );
|
||||
Property property = makeComponent( ownerEntity, context, syntheticPropertyName, embeddedComp, properties );
|
||||
property.setPropertyAccessorName( "embedded" );
|
||||
ownerEntity.addProperty( property );
|
||||
embeddedComp.createUniqueKey(); //make it unique
|
||||
return property;
|
||||
}
|
||||
|
||||
private static Property makeComponent(
|
||||
PersistentClass ownerEntity,
|
||||
MetadataBuildingContext context,
|
||||
String name,
|
||||
Component embeddedComp,
|
||||
List<Property> properties) {
|
||||
embeddedComponent.setComponentClassName( embeddedComponent.getOwner().getClassName() );
|
||||
embeddedComponent.setEmbedded( true );
|
||||
for ( Property property : properties ) {
|
||||
Property clone = cloneProperty( ownerEntity, context, property );
|
||||
embeddedComp.addProperty( clone );
|
||||
embeddedComponent.addProperty( cloneProperty( ownerEntity, context, property ) );
|
||||
}
|
||||
embeddedComp.sortProperties();
|
||||
Property synthProp = new SyntheticProperty();
|
||||
synthProp.setName( name );
|
||||
synthProp.setPersistentClass( ownerEntity );
|
||||
synthProp.setUpdateable( false );
|
||||
synthProp.setInsertable( false );
|
||||
synthProp.setValue( embeddedComp );
|
||||
return synthProp;
|
||||
embeddedComponent.sortProperties();
|
||||
final Property result = new SyntheticProperty();
|
||||
result.setName(syntheticPropertyName);
|
||||
result.setPersistentClass(ownerEntity);
|
||||
result.setUpdateable( false );
|
||||
result.setInsertable( false );
|
||||
result.setValue(embeddedComponent);
|
||||
result.setPropertyAccessorName( "embedded" );
|
||||
ownerEntity.addProperty( result );
|
||||
embeddedComponent.createUniqueKey(); //make it unique
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a (deep) copy of the {@link Property}, by also recursively
|
||||
* cloning any child {@link Component} instances, but reusing other
|
||||
* kinds of {@link Value} and other attributes.
|
||||
*/
|
||||
private static Property cloneProperty(PersistentClass ownerEntity, MetadataBuildingContext context, Property property) {
|
||||
if ( property.isComposite() ) {
|
||||
Component component = (Component) property.getValue();
|
||||
Component copy = new Component( context, component );
|
||||
final Component component = (Component) property.getValue();
|
||||
final Component copy = new Component( context, component );
|
||||
copy.setComponentClassName( component.getComponentClassName() );
|
||||
copy.setEmbedded( component.isEmbedded() );
|
||||
Property clone = makeComponent( ownerEntity, context, property.getName(), copy, component.getProperties() );
|
||||
for ( Property property1 : component.getProperties()) {
|
||||
copy.addProperty( cloneProperty(ownerEntity, context, property1) );
|
||||
}
|
||||
copy.sortProperties();
|
||||
final Property result = new SyntheticProperty();
|
||||
result.setName(property.getName());
|
||||
result.setPersistentClass(ownerEntity);
|
||||
result.setUpdateable( false );
|
||||
result.setInsertable( false );
|
||||
result.setValue(copy);
|
||||
final Property clone = result;
|
||||
clone.setPropertyAccessorName( property.getPropertyAccessorName() );
|
||||
return clone;
|
||||
}
|
||||
else {
|
||||
Property clone = shallowCopy( property );
|
||||
final Property clone = shallowCopy( property );
|
||||
clone.setInsertable( false );
|
||||
clone.setUpdateable( false );
|
||||
clone.setNaturalIdentifier( false );
|
||||
|
@ -409,6 +388,27 @@ public class BinderHelper {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a copy of the {@link Property}, reusing the same {@link Value}
|
||||
* and other attributes.
|
||||
*/
|
||||
public static Property shallowCopy(Property property) {
|
||||
Property clone = new SyntheticProperty();
|
||||
clone.setCascade( property.getCascade() );
|
||||
clone.setInsertable( property.isInsertable() );
|
||||
clone.setLazy( property.isLazy() );
|
||||
clone.setName( property.getName() );
|
||||
clone.setNaturalIdentifier( property.isNaturalIdentifier() );
|
||||
clone.setOptimisticLocked( property.isOptimisticLocked() );
|
||||
clone.setOptional( property.isOptional() );
|
||||
clone.setPersistentClass( property.getPersistentClass() );
|
||||
clone.setPropertyAccessorName( property.getPropertyAccessorName() );
|
||||
clone.setSelectable( property.isSelectable() );
|
||||
clone.setUpdateable( property.isUpdateable() );
|
||||
clone.setValue( property.getValue() );
|
||||
return clone;
|
||||
}
|
||||
|
||||
private static List<Property> findPropertiesByColumns(
|
||||
Object columnOwner,
|
||||
AnnotatedJoinColumns columns,
|
||||
|
@ -741,66 +741,63 @@ public class BinderHelper {
|
|||
}
|
||||
|
||||
/**
|
||||
* apply an id generator to a SimpleValue
|
||||
* Apply an id generation strategy and parameters to the
|
||||
* given {@link SimpleValue} which represents an identifier.
|
||||
*/
|
||||
public static void makeIdGenerator(
|
||||
SimpleValue id,
|
||||
XProperty idXProperty,
|
||||
XProperty property,
|
||||
String generatorType,
|
||||
String generatorName,
|
||||
MetadataBuildingContext buildingContext,
|
||||
Map<String, IdentifierGeneratorDefinition> localGenerators) {
|
||||
log.debugf( "#makeIdGenerator(%s, %s, %s, %s, ...)", id, idXProperty, generatorType, generatorName );
|
||||
log.debugf( "#makeIdGenerator(%s, %s, %s, %s, ...)", id, property, generatorType, generatorName );
|
||||
|
||||
Table table = id.getTable();
|
||||
final Table table = id.getTable();
|
||||
table.setIdentifierValue( id );
|
||||
//generator settings
|
||||
id.setIdentifierGeneratorStrategy( generatorType );
|
||||
|
||||
final Map<String,Object> params = new HashMap<>();
|
||||
final Map<String,Object> parameters = new HashMap<>();
|
||||
|
||||
//always settable
|
||||
params.put( PersistentIdentifierGenerator.TABLE, table.getName() );
|
||||
parameters.put( PersistentIdentifierGenerator.TABLE, table.getName() );
|
||||
|
||||
if ( id.getColumnSpan() == 1 ) {
|
||||
params.put( PersistentIdentifierGenerator.PK, id.getColumns().get(0).getName() );
|
||||
parameters.put( PersistentIdentifierGenerator.PK, id.getColumns().get(0).getName() );
|
||||
}
|
||||
// YUCK! but cannot think of a clean way to do this given the string-config based scheme
|
||||
params.put( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, buildingContext.getObjectNameNormalizer() );
|
||||
params.put( IdentifierGenerator.GENERATOR_NAME, generatorName );
|
||||
parameters.put( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, buildingContext.getObjectNameNormalizer() );
|
||||
parameters.put( IdentifierGenerator.GENERATOR_NAME, generatorName );
|
||||
|
||||
if ( !isEmptyAnnotationValue( generatorName ) ) {
|
||||
//we have a named generator
|
||||
IdentifierGeneratorDefinition gen = getIdentifierGenerator(
|
||||
final IdentifierGeneratorDefinition definition = getIdentifierGenerator(
|
||||
generatorName,
|
||||
idXProperty,
|
||||
property,
|
||||
localGenerators,
|
||||
buildingContext
|
||||
);
|
||||
if ( gen == null ) {
|
||||
if ( definition == null ) {
|
||||
throw new AnnotationException( "No id generator was declared with the name '" + generatorName
|
||||
+ "' specified by '@GeneratedValue'"
|
||||
+ " (define a named generator using '@SequenceGenerator', '@TableGenerator', or '@GenericGenerator')" );
|
||||
}
|
||||
//This is quite vague in the spec but a generator could override the generator choice
|
||||
String identifierGeneratorStrategy = gen.getStrategy();
|
||||
final String identifierGeneratorStrategy = definition.getStrategy();
|
||||
//yuk! this is a hack not to override 'AUTO' even if generator is set
|
||||
final boolean avoidOverriding = identifierGeneratorStrategy.equals( "identity" )
|
||||
|| identifierGeneratorStrategy.equals( "seqhilo" );
|
||||
if ( generatorType == null || !avoidOverriding ) {
|
||||
id.setIdentifierGeneratorStrategy( identifierGeneratorStrategy );
|
||||
}
|
||||
//checkIfMatchingGenerator(gen, generatorType, generatorName);
|
||||
for ( Map.Entry<String,String> elt : gen.getParameters().entrySet() ) {
|
||||
if ( elt.getKey() != null ) {
|
||||
params.put( elt.getKey(), elt.getValue() );
|
||||
}
|
||||
}
|
||||
//checkIfMatchingGenerator(definition, generatorType, generatorName);
|
||||
parameters.putAll( definition.getParameters() );
|
||||
}
|
||||
if ( "assigned".equals( generatorType ) ) {
|
||||
id.setNullValue( "undefined" );
|
||||
}
|
||||
id.setIdentifierGeneratorParameters( params );
|
||||
id.setIdentifierGeneratorParameters( parameters );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue