Skip to content

Commit ab7adaa

Browse files
committed
HHH-18815 introduce Generator.generatedBeforeExecution()
so that GeneratedGeneration does not need to implement BeforeExecutionGenerator Signed-off-by: Gavin King <[email protected]>
1 parent 685fda0 commit ab7adaa

File tree

7 files changed

+78
-49
lines changed

7 files changed

+78
-49
lines changed

hibernate-core/src/main/java/org/hibernate/generator/Generator.java

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,10 @@
3232
* SQL {@code select}, though in certain cases this additional round trip may be avoided.
3333
* An important example is id generation using an identity column.
3434
* </ul>
35-
* A Generator may implement both interfaces and determine the timing of ID generation at runtime.
36-
* Furthermore, this condition can be based on the state of the owner entity, see
37-
* {@link #generatedOnExecution(Object, SharedSessionContractImplementor) generatedOnExecution}.
35+
* A {@code Generator} may implement both interfaces and determine the timing of identifier
36+
* generation at runtime. Furthermore, this condition can be based on the state of the owner entity,
37+
* see {@link #generatedOnExecution(Object, SharedSessionContractImplementor) generatedOnExecution} and
38+
* {@link #generatedBeforeExecution(Object, SharedSessionContractImplementor) generatedBeforeExecution}.
3839
* <p>
3940
* Generically, a generator may be integrated with the program using the meta-annotation
4041
* {@link org.hibernate.annotations.ValueGenerationType}, which associates the generator with
@@ -95,20 +96,16 @@ public interface Generator extends Serializable {
9596
boolean generatedOnExecution();
9697

9798
/**
98-
* Determines if the property value is generated when a row is written to the database,
99-
* or in Java code that executes before the row is written.
99+
* Determines if the property value is generated when a row is written to the database.
100100
* <p>
101-
* Defaults to {@link #generatedOnExecution()}, but can be overloaded allowing conditional
102-
* value generation timing (on/before execution) based on the current state of the owner entity.
103-
* Note that a generator <b>must</b> implement both {@link BeforeExecutionGenerator} and
104-
* {@link OnExecutionGenerator} to achieve this behavior.
101+
* Defaults to {@link #generatedOnExecution()}, but may be overridden to allow conditional
102+
* on-execution value generation based on the current state of the owner entity.
105103
*
106104
* @param entity The instance of the entity owning the attribute for which we are generating a value.
107105
* @param session The session from which the request originates.
108106
*
109107
* @return {@code true} if the value is generated by the database as a side effect of
110-
* the execution of an {@code insert} or {@code update} statement, or false if
111-
* it is generated in Java code before the statement is executed via JDBC.
108+
* the execution of an {@code insert} or {@code update} statement.
112109
*
113110
* @see #generatedOnExecution()
114111
* @see BeforeExecutionGenerator
@@ -120,6 +117,30 @@ default boolean generatedOnExecution(Object entity, SharedSessionContractImpleme
120117
return generatedOnExecution();
121118
}
122119

120+
/**
121+
* Determines if the property value is generated before in Java code that executes before
122+
* the row is written.
123+
* <p>
124+
* Defaults to {@link #generatedOnExecution() !generatedOnExecution()}, but may be overridden
125+
* to allow conditional before-execution value generation based on the current state of the
126+
* owner entity.
127+
*
128+
* @param entity The instance of the entity owning the attribute for which we are generating a value.
129+
* @param session The session from which the request originates.
130+
*
131+
* @return {@code true} if the value is generated in Java code before the statement is
132+
* executed via JDBC.
133+
*
134+
* @see #generatedOnExecution()
135+
* @see BeforeExecutionGenerator
136+
* @see OnExecutionGenerator
137+
*
138+
* @since 7.0
139+
*/
140+
default boolean generatedBeforeExecution(Object entity, SharedSessionContractImplementor session) {
141+
return !generatedOnExecution();
142+
}
143+
123144
/**
124145
* The {@linkplain EventType event types} for which this generator should be called
125146
* to produce a new value.

hibernate-core/src/main/java/org/hibernate/generator/internal/GeneratedGeneration.java

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import org.hibernate.annotations.Generated;
99
import org.hibernate.dialect.Dialect;
1010
import org.hibernate.engine.spi.SharedSessionContractImplementor;
11-
import org.hibernate.generator.BeforeExecutionGenerator;
1211
import org.hibernate.generator.EventType;
1312
import org.hibernate.generator.OnExecutionGenerator;
1413
import org.hibernate.persister.entity.EntityPersister;
@@ -27,7 +26,7 @@
2726
* @author Steve Ebersole
2827
* @author Gunnar Morling
2928
*/
30-
public class GeneratedGeneration implements OnExecutionGenerator, BeforeExecutionGenerator {
29+
public class GeneratedGeneration implements OnExecutionGenerator {
3130

3231
private final EnumSet<EventType> eventTypes;
3332
private final boolean writable;
@@ -72,11 +71,6 @@ public boolean writePropertyValue() {
7271
return writable;
7372
}
7473

75-
@Override
76-
public boolean generatedOnExecution() {
77-
return true;
78-
}
79-
8074
@Override
8175
public boolean generatedOnExecution(Object entity, SharedSessionContractImplementor session) {
8276
if ( writable ) {
@@ -90,13 +84,6 @@ public boolean generatedOnExecution(Object entity, SharedSessionContractImplemen
9084
}
9185
}
9286

93-
@Override
94-
public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue, EventType eventType) {
95-
final EntityPersister entityPersister = session.getEntityPersister( null, owner );
96-
assert entityPersister.getGenerator() == this;
97-
return entityPersister.getIdentifier( owner, session );
98-
}
99-
10087
@Override
10188
public boolean allowAssignedIdentifiers() {
10289
return writable;

hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -146,32 +146,47 @@ public Object insert(String entityName, Object entity) {
146146
}
147147
}
148148
final Generator generator = persister.getGenerator();
149-
if ( !generator.generatedOnExecution( entity, this ) ) {
150-
if ( generator.generatesOnInsert() ) {
151-
id = ( (BeforeExecutionGenerator) generator).generate( this, entity, null, INSERT );
152-
}
153-
else {
154-
id = persister.getIdentifier( entity, this );
155-
if ( id == null ) {
156-
throw new IdentifierGenerationException( "Identifier of entity '" + persister.getEntityName() + "' must be manually assigned before calling 'insert()'" );
157-
}
149+
if ( generator.generatedBeforeExecution( entity, this ) ) {
150+
if ( !generator.generatesOnInsert() ) {
151+
throw new IdentifierGenerationException( "Identifier generator must generate on insert" );
158152
}
153+
id = ( (BeforeExecutionGenerator) generator).generate( this, entity, null, INSERT );
159154
if ( firePreInsert(entity, id, state, persister) ) {
160155
return id;
161156
}
162-
getInterceptor().onInsert( entity, id, state, persister.getPropertyNames(), persister.getPropertyTypes() );
163-
persister.getInsertCoordinator().insert( entity, id, state, this );
157+
else {
158+
getInterceptor().onInsert( entity, id, state, persister.getPropertyNames(), persister.getPropertyTypes() );
159+
persister.getInsertCoordinator().insert( entity, id, state, this );
160+
persister.setIdentifier( entity, id, this );
161+
}
164162
}
165-
else {
163+
else if ( generator.generatedOnExecution( entity, this ) ) {
164+
if ( !generator.generatesOnInsert() ) {
165+
throw new IdentifierGenerationException( "Identifier generator must generate on insert" );
166+
}
166167
if ( firePreInsert(entity, null, state, persister) ) {
167168
return null;
168169
}
169-
getInterceptor()
170-
.onInsert( entity, null, state, persister.getPropertyNames(), persister.getPropertyTypes() );
171-
final GeneratedValues generatedValues = persister.getInsertCoordinator().insert( entity, state, this );
172-
id = castNonNull( generatedValues ).getGeneratedValue( persister.getIdentifierMapping() );
170+
else {
171+
getInterceptor().onInsert( entity, null, state, persister.getPropertyNames(), persister.getPropertyTypes() );
172+
final GeneratedValues generatedValues = persister.getInsertCoordinator().insert( entity, state, this );
173+
id = castNonNull( generatedValues ).getGeneratedValue( persister.getIdentifierMapping() );
174+
persister.setIdentifier( entity, id, this );
175+
}
176+
}
177+
else { // assigned identifier
178+
id = persister.getIdentifier( entity, this );
179+
if ( id == null ) {
180+
throw new IdentifierGenerationException( "Identifier of entity '" + persister.getEntityName() + "' must be manually assigned before calling 'insert()'" );
181+
}
182+
if ( firePreInsert(entity, id, state, persister) ) {
183+
return id;
184+
}
185+
else {
186+
getInterceptor().onInsert( entity, id, state, persister.getPropertyNames(), persister.getPropertyTypes() );
187+
persister.getInsertCoordinator().insert( entity, id, state, this );
188+
}
173189
}
174-
persister.setIdentifier( entity, id, this );
175190
forEachOwnedCollection( entity, id, persister,
176191
(descriptor, collection) -> {
177192
descriptor.recreate( collection, id, this);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,7 @@ public int getPropertyIndex() {
776776

777777
@Override
778778
public Object execute(SharedSessionContractImplementor session, Object incomingObject) {
779-
if ( !generator.generatedOnExecution( incomingObject, session ) ) {
779+
if ( generator.generatedBeforeExecution( incomingObject, session ) ) {
780780
return generator.generate( session, incomingObject, null, INSERT );
781781
}
782782
else {

hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/InsertCoordinatorStandard.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ protected boolean preInsertInMemoryValueGeneration(Object[] values, Object entit
140140
final Generator generator = generators[i];
141141
if ( generator != null
142142
&& generator.generatesOnInsert()
143-
&& !generator.generatedOnExecution( entity, session ) ) {
143+
&& generator.generatedBeforeExecution( entity, session ) ) {
144144
values[i] = ( (BeforeExecutionGenerator) generator ).generate( session, entity, values[i], INSERT );
145145
persister.setPropertyValue( entity, i, values[i] );
146146
foundStateDependentGenerator = foundStateDependentGenerator || generator.generatedOnExecution();
@@ -407,7 +407,7 @@ private void applyTableInsertDetails(
407407
else {
408408
final Generator generator = attributeMapping.getGenerator();
409409
if ( isValueGenerated( generator ) ) {
410-
if ( session != null && !generator.generatedOnExecution( object, session ) ) {
410+
if ( session != null && generator.generatedBeforeExecution( object, session ) ) {
411411
attributeInclusions[attributeIndex] = true;
412412
attributeMapping.forEachInsertable( insertGroupBuilder );
413413
}

hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateCoordinatorStandard.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ private int[] preUpdateInMemoryValueGeneration(
540540
final Generator generator = generators[i];
541541
if ( generator != null
542542
&& generator.generatesOnUpdate()
543-
&& !generator.generatedOnExecution( object, session ) ) {
543+
&& generator.generatedBeforeExecution( object, session ) ) {
544544
newValues[i] = ( (BeforeExecutionGenerator) generator ).generate( session, object, newValues[i], UPDATE );
545545
entityPersister().setPropertyValue( object, i, newValues[i] );
546546
fieldsPreUpdateNeeded[count++] = i;
@@ -667,7 +667,8 @@ private void processAttribute(
667667

668668
final Generator generator = attributeMapping.getGenerator();
669669
final boolean generated = isValueGenerated( generator );
670-
final boolean needsDynamicUpdate = generated && session != null && !generator.generatedOnExecution( entity, session );
670+
final boolean needsDynamicUpdate =
671+
generated && session != null && generator.generatedBeforeExecution( entity, session );
671672
final boolean generatedInSql = generated && isValueGenerationInSql( generator, dialect );
672673
if ( generatedInSql && !needsDynamicUpdate && !( (OnExecutionGenerator) generator ).writePropertyValue() ) {
673674
analysis.registerValueGeneratedInSqlNoWrite();

hibernate-core/src/test/java/org/hibernate/orm/test/idgen/userdefined/MixedTimingGeneratorsTest.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,8 +333,13 @@ public boolean generatedOnExecution() {
333333
}
334334

335335
@Override
336-
public boolean generatedOnExecution(Object owner, SharedSessionContractImplementor session) {
337-
return !( (StringGeneratedEntity) owner ).getName().contains( "generated" );
336+
public boolean generatedOnExecution(Object entity, SharedSessionContractImplementor session) {
337+
return !generatedBeforeExecution( entity, session );
338+
}
339+
340+
@Override
341+
public boolean generatedBeforeExecution(Object entity, SharedSessionContractImplementor session) {
342+
return ( (StringGeneratedEntity) entity ).getName().contains( "generated" );
338343
}
339344

340345
@Override

0 commit comments

Comments
 (0)