HHH-15074 Handle composite nested value generation for java records
This commit is contained in:
parent
c558fb7a5c
commit
19d9d95a9e
|
@ -17,6 +17,8 @@ import org.hibernate.boot.model.relational.ExportableProducer;
|
|||
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.id.factory.spi.StandardGenerator;
|
||||
import org.hibernate.property.access.spi.Setter;
|
||||
import org.hibernate.type.CompositeType;
|
||||
|
||||
/**
|
||||
* For composite identifiers, defines a number of "nested" generations that
|
||||
|
@ -87,16 +89,35 @@ public class CompositeNestedGeneratedValueGenerator
|
|||
*
|
||||
* @param session The current session
|
||||
* @param incomingObject The entity for which we are generating id
|
||||
* @param injectionContext The context into which the generated value can be injected
|
||||
*/
|
||||
void execute(SharedSessionContractImplementor session, Object incomingObject, Object injectionContext);
|
||||
Object execute(SharedSessionContractImplementor session, Object incomingObject);
|
||||
|
||||
/**
|
||||
* Returns the {@link Setter injector} for the generated property.
|
||||
* Used when the {@link CompositeType} is {@linkplain CompositeType#isMutable() mutable}.
|
||||
*
|
||||
* @see #getPropertyIndex()
|
||||
*/
|
||||
Setter getInjector();
|
||||
|
||||
/**
|
||||
* Returns the index of the generated property.
|
||||
* Used when the {@link CompositeType} is not {@linkplain CompositeType#isMutable() mutable}.
|
||||
*
|
||||
* @see #getInjector()
|
||||
*/
|
||||
int getPropertyIndex();
|
||||
}
|
||||
|
||||
private final GenerationContextLocator generationContextLocator;
|
||||
private final CompositeType compositeType;
|
||||
private final List<GenerationPlan> generationPlans = new ArrayList<>();
|
||||
|
||||
public CompositeNestedGeneratedValueGenerator(GenerationContextLocator generationContextLocator) {
|
||||
public CompositeNestedGeneratedValueGenerator(
|
||||
GenerationContextLocator generationContextLocator,
|
||||
CompositeType compositeType) {
|
||||
this.generationContextLocator = generationContextLocator;
|
||||
this.compositeType = compositeType;
|
||||
}
|
||||
|
||||
public void addGeneratedValuePlan(GenerationPlan plan) {
|
||||
|
@ -107,11 +128,29 @@ public class CompositeNestedGeneratedValueGenerator
|
|||
public Object generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
|
||||
final Object context = generationContextLocator.locateGenerationContext( session, object );
|
||||
|
||||
final List<Object> generatedValues = compositeType.isMutable() ?
|
||||
null :
|
||||
new ArrayList<>( generationPlans.size() );
|
||||
for ( GenerationPlan generationPlan : generationPlans ) {
|
||||
generationPlan.execute( session, object, context );
|
||||
final Object generated = generationPlan.execute( session, object );
|
||||
if ( generatedValues != null ) {
|
||||
generatedValues.add( generated );
|
||||
}
|
||||
else {
|
||||
generationPlan.getInjector().set( context, generated );
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
if ( generatedValues != null) {
|
||||
final Object[] values = compositeType.getPropertyValues( context );
|
||||
for ( int i = 0; i < generatedValues.size(); i++ ) {
|
||||
values[generationPlans.get( i ).getPropertyIndex()] = generatedValues.get( i );
|
||||
}
|
||||
return compositeType.replacePropertyValues( context, values, session );
|
||||
}
|
||||
else {
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -578,20 +578,25 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
|
|||
|
||||
final CompositeNestedGeneratedValueGenerator.GenerationContextLocator locator =
|
||||
new StandardGenerationContextLocator( rootClass.getEntityName() );
|
||||
final CompositeNestedGeneratedValueGenerator generator = new CompositeNestedGeneratedValueGenerator( locator );
|
||||
final CompositeNestedGeneratedValueGenerator generator = new CompositeNestedGeneratedValueGenerator(
|
||||
locator,
|
||||
getType()
|
||||
);
|
||||
|
||||
for ( Property property : getProperties() ) {
|
||||
final List<Property> properties = getProperties();
|
||||
for ( int i = 0; i < properties.size(); i++ ) {
|
||||
final Property property = properties.get( i );
|
||||
if ( property.getValue().isSimpleValue() ) {
|
||||
final SimpleValue value = (SimpleValue) property.getValue();
|
||||
|
||||
if ( !DEFAULT_ID_GEN_STRATEGY.equals( value.getIdentifierGeneratorStrategy() ) ) {
|
||||
// skip any 'assigned' generators, they would have been handled by
|
||||
// the StandardGenerationContextLocator
|
||||
Generator subgenerator = value.createGenerator( identifierGeneratorFactory, dialect, rootClass );
|
||||
generator.addGeneratedValuePlan( new ValueGenerationPlan(
|
||||
subgenerator,
|
||||
injector( property, attributeDeclarer ) )
|
||||
);
|
||||
value.createGenerator( identifierGeneratorFactory, dialect, rootClass ),
|
||||
getType().isMutable() ? injector( property, attributeDeclarer ) : null,
|
||||
i
|
||||
) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -639,18 +644,29 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
|
|||
public static class ValueGenerationPlan implements CompositeNestedGeneratedValueGenerator.GenerationPlan {
|
||||
private final Generator subgenerator;
|
||||
private final Setter injector;
|
||||
private final int propertyIndex;
|
||||
|
||||
public ValueGenerationPlan(Generator subgenerator, Setter injector) {
|
||||
public ValueGenerationPlan(Generator subgenerator, Setter injector, int propertyIndex) {
|
||||
this.subgenerator = subgenerator;
|
||||
this.injector = injector;
|
||||
this.propertyIndex = propertyIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(SharedSessionContractImplementor session, Object incomingObject, Object injectionContext) {
|
||||
public Setter getInjector() {
|
||||
return injector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPropertyIndex() {
|
||||
return propertyIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(SharedSessionContractImplementor session, Object incomingObject) {
|
||||
if ( !subgenerator.generatedOnExecution( incomingObject, session ) ) {
|
||||
final Object generatedId = ( (BeforeExecutionGenerator) subgenerator)
|
||||
return ( (BeforeExecutionGenerator) subgenerator)
|
||||
.generate( session, incomingObject, null, INSERT );
|
||||
injector.set( injectionContext, generatedId );
|
||||
}
|
||||
else {
|
||||
throw new IdentifierGenerationException( "Identity generation isn't supported for composite ids" );
|
||||
|
|
Loading…
Reference in New Issue