Skip to content

Commit 19d9d95

Browse files
committed
HHH-15074 Handle composite nested value generation for java records
1 parent c558fb7 commit 19d9d95

File tree

2 files changed

+70
-15
lines changed

2 files changed

+70
-15
lines changed

hibernate-core/src/main/java/org/hibernate/id/CompositeNestedGeneratedValueGenerator.java

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
1818
import org.hibernate.engine.spi.SharedSessionContractImplementor;
1919
import org.hibernate.id.factory.spi.StandardGenerator;
20+
import org.hibernate.property.access.spi.Setter;
21+
import org.hibernate.type.CompositeType;
2022

2123
/**
2224
* For composite identifiers, defines a number of "nested" generations that
@@ -87,16 +89,35 @@ public interface GenerationPlan extends ExportableProducer {
8789
*
8890
* @param session The current session
8991
* @param incomingObject The entity for which we are generating id
90-
* @param injectionContext The context into which the generated value can be injected
9192
*/
92-
void execute(SharedSessionContractImplementor session, Object incomingObject, Object injectionContext);
93+
Object execute(SharedSessionContractImplementor session, Object incomingObject);
94+
95+
/**
96+
* Returns the {@link Setter injector} for the generated property.
97+
* Used when the {@link CompositeType} is {@linkplain CompositeType#isMutable() mutable}.
98+
*
99+
* @see #getPropertyIndex()
100+
*/
101+
Setter getInjector();
102+
103+
/**
104+
* Returns the index of the generated property.
105+
* Used when the {@link CompositeType} is not {@linkplain CompositeType#isMutable() mutable}.
106+
*
107+
* @see #getInjector()
108+
*/
109+
int getPropertyIndex();
93110
}
94111

95112
private final GenerationContextLocator generationContextLocator;
113+
private final CompositeType compositeType;
96114
private final List<GenerationPlan> generationPlans = new ArrayList<>();
97115

98-
public CompositeNestedGeneratedValueGenerator(GenerationContextLocator generationContextLocator) {
116+
public CompositeNestedGeneratedValueGenerator(
117+
GenerationContextLocator generationContextLocator,
118+
CompositeType compositeType) {
99119
this.generationContextLocator = generationContextLocator;
120+
this.compositeType = compositeType;
100121
}
101122

102123
public void addGeneratedValuePlan(GenerationPlan plan) {
@@ -107,11 +128,29 @@ public void addGeneratedValuePlan(GenerationPlan plan) {
107128
public Object generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
108129
final Object context = generationContextLocator.locateGenerationContext( session, object );
109130

131+
final List<Object> generatedValues = compositeType.isMutable() ?
132+
null :
133+
new ArrayList<>( generationPlans.size() );
110134
for ( GenerationPlan generationPlan : generationPlans ) {
111-
generationPlan.execute( session, object, context );
135+
final Object generated = generationPlan.execute( session, object );
136+
if ( generatedValues != null ) {
137+
generatedValues.add( generated );
138+
}
139+
else {
140+
generationPlan.getInjector().set( context, generated );
141+
}
112142
}
113143

114-
return context;
144+
if ( generatedValues != null) {
145+
final Object[] values = compositeType.getPropertyValues( context );
146+
for ( int i = 0; i < generatedValues.size(); i++ ) {
147+
values[generationPlans.get( i ).getPropertyIndex()] = generatedValues.get( i );
148+
}
149+
return compositeType.replacePropertyValues( context, values, session );
150+
}
151+
else {
152+
return context;
153+
}
115154
}
116155

117156
@Override

hibernate-core/src/main/java/org/hibernate/mapping/Component.java

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -578,20 +578,25 @@ else if ( rootClass.getIdentifierProperty() != null ) {
578578

579579
final CompositeNestedGeneratedValueGenerator.GenerationContextLocator locator =
580580
new StandardGenerationContextLocator( rootClass.getEntityName() );
581-
final CompositeNestedGeneratedValueGenerator generator = new CompositeNestedGeneratedValueGenerator( locator );
581+
final CompositeNestedGeneratedValueGenerator generator = new CompositeNestedGeneratedValueGenerator(
582+
locator,
583+
getType()
584+
);
582585

583-
for ( Property property : getProperties() ) {
586+
final List<Property> properties = getProperties();
587+
for ( int i = 0; i < properties.size(); i++ ) {
588+
final Property property = properties.get( i );
584589
if ( property.getValue().isSimpleValue() ) {
585590
final SimpleValue value = (SimpleValue) property.getValue();
586591

587592
if ( !DEFAULT_ID_GEN_STRATEGY.equals( value.getIdentifierGeneratorStrategy() ) ) {
588593
// skip any 'assigned' generators, they would have been handled by
589594
// the StandardGenerationContextLocator
590-
Generator subgenerator = value.createGenerator( identifierGeneratorFactory, dialect, rootClass );
591595
generator.addGeneratedValuePlan( new ValueGenerationPlan(
592-
subgenerator,
593-
injector( property, attributeDeclarer ) )
594-
);
596+
value.createGenerator( identifierGeneratorFactory, dialect, rootClass ),
597+
getType().isMutable() ? injector( property, attributeDeclarer ) : null,
598+
i
599+
) );
595600
}
596601
}
597602
}
@@ -639,18 +644,29 @@ public Object locateGenerationContext(SharedSessionContractImplementor session,
639644
public static class ValueGenerationPlan implements CompositeNestedGeneratedValueGenerator.GenerationPlan {
640645
private final Generator subgenerator;
641646
private final Setter injector;
647+
private final int propertyIndex;
642648

643-
public ValueGenerationPlan(Generator subgenerator, Setter injector) {
649+
public ValueGenerationPlan(Generator subgenerator, Setter injector, int propertyIndex) {
644650
this.subgenerator = subgenerator;
645651
this.injector = injector;
652+
this.propertyIndex = propertyIndex;
653+
}
654+
655+
@Override
656+
public Setter getInjector() {
657+
return injector;
658+
}
659+
660+
@Override
661+
public int getPropertyIndex() {
662+
return propertyIndex;
646663
}
647664

648665
@Override
649-
public void execute(SharedSessionContractImplementor session, Object incomingObject, Object injectionContext) {
666+
public Object execute(SharedSessionContractImplementor session, Object incomingObject) {
650667
if ( !subgenerator.generatedOnExecution( incomingObject, session ) ) {
651-
final Object generatedId = ( (BeforeExecutionGenerator) subgenerator)
668+
return ( (BeforeExecutionGenerator) subgenerator)
652669
.generate( session, incomingObject, null, INSERT );
653-
injector.set( injectionContext, generatedId );
654670
}
655671
else {
656672
throw new IdentifierGenerationException( "Identity generation isn't supported for composite ids" );

0 commit comments

Comments
 (0)