HHH-15800 make Generator free of GenerationTiming

This commit is contained in:
Gavin 2022-12-03 12:02:17 +01:00 committed by Gavin King
parent 1104d01d33
commit 216fe0f615
23 changed files with 226 additions and 161 deletions

View File

@ -574,22 +574,27 @@ public class PropertyBinder {
private static void checkVersionGenerationAlways(XProperty property, Generator generator) { private static void checkVersionGenerationAlways(XProperty property, Generator generator) {
if ( property.isAnnotationPresent(Version.class) ) { if ( property.isAnnotationPresent(Version.class) ) {
final GenerationTiming timing = generator.getGenerationTiming(); if ( !generator.generatedOnInsert() ) {
if ( !timing.isAlways() ) {
throw new AnnotationException("Property '" + property.getName() throw new AnnotationException("Property '" + property.getName()
+ "' is annotated '@Version' but has a value generator with timing " + timing.name() + "' is annotated '@Version' but has a 'Generator' which does not generate on inserts"
+ " (the value generation timing must be ALWAYS)" );
}
if ( !generator.generatedOnUpdate() ) {
throw new AnnotationException("Property '" + property.getName()
+ "' is annotated '@Version' but has a 'Generator' which does not generate on updates"
); );
} }
} }
} }
private static void checkIdGeneratorTiming(Class<? extends Annotation> annotationType, Generator generator) { private static void checkIdGeneratorTiming(Class<? extends Annotation> annotationType, Generator generator) {
GenerationTiming timing = generator.getGenerationTiming(); if ( !generator.generatedOnInsert() ) {
if ( timing != INSERT ) {
throw new MappingException( "Annotation '" + annotationType throw new MappingException( "Annotation '" + annotationType
+ "' is annotated 'IdGeneratorType' but the given 'InMemoryGenerator' has timing " + timing + "' is annotated 'IdGeneratorType' but the given 'Generator' does not generate on inserts");
+ " (an id generator must having timing INSERT)"); }
if ( generator.generatedOnUpdate() ) {
throw new MappingException( "Annotation '" + annotationType
+ "' is annotated 'IdGeneratorType' but the given 'Generator' generates on updates (it must generate only on inserts)");
} }
} }
} }

View File

@ -129,7 +129,7 @@ public final class Nullability {
} }
private static boolean generated(Generator generator) { private static boolean generated(Generator generator) {
return generator != null && generator.getGenerationTiming().isNotNever(); return generator != null && generator.isNotNever();
} }
/** /**

View File

@ -19,8 +19,6 @@ import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.InMemoryGenerator; import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import static org.hibernate.tuple.GenerationTiming.INSERT;
/** /**
* A classic extension point from the very earliest days of Hibernate, * A classic extension point from the very earliest days of Hibernate,
* this interface is no longer the only way to generate identifiers. Any * this interface is no longer the only way to generate identifiers. Any
@ -145,11 +143,19 @@ public interface IdentifierGenerator extends InMemoryGenerator, ExportableProduc
} }
/** /**
* @return {@link GenerationTiming#INSERT} * @return {@code true}
*/ */
@Override @Override
default GenerationTiming getGenerationTiming() { default boolean generatedOnInsert() {
return INSERT; return true;
}
/**
* @return {@code false}
*/
@Override
default boolean generatedOnUpdate() {
return false;
} }
/** /**

View File

@ -13,8 +13,6 @@ import org.hibernate.type.Type;
import java.util.Properties; import java.util.Properties;
import static org.hibernate.tuple.GenerationTiming.INSERT;
/** /**
* The counterpart of {@link IdentifierGenerator} for values generated by the database. * The counterpart of {@link IdentifierGenerator} for values generated by the database.
* This interface is no longer the only way to handle database-generate identifiers. * This interface is no longer the only way to handle database-generate identifiers.
@ -28,11 +26,19 @@ import static org.hibernate.tuple.GenerationTiming.INSERT;
public interface PostInsertIdentifierGenerator extends InDatabaseGenerator, Configurable { public interface PostInsertIdentifierGenerator extends InDatabaseGenerator, Configurable {
/** /**
* @return {@link GenerationTiming#INSERT} * @return {@code true}
*/ */
@Override @Override
default GenerationTiming getGenerationTiming() { default boolean generatedOnInsert() {
return INSERT; return true;
}
/**
* @return {@code false}
*/
@Override
default boolean generatedOnUpdate() {
return false;
} }
/** /**

View File

@ -12,7 +12,6 @@ import java.util.UUID;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.factory.spi.CustomIdGeneratorCreationContext; import org.hibernate.id.factory.spi.CustomIdGeneratorCreationContext;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.InMemoryGenerator; import org.hibernate.tuple.InMemoryGenerator;
import org.hibernate.type.descriptor.java.UUIDJavaType; import org.hibernate.type.descriptor.java.UUIDJavaType;
import org.hibernate.type.descriptor.java.UUIDJavaType.ValueTransformer; import org.hibernate.type.descriptor.java.UUIDJavaType.ValueTransformer;
@ -60,9 +59,20 @@ public class UuidGenerator implements InMemoryGenerator {
} }
} }
/**
* @return {@code true}
*/
@Override @Override
public GenerationTiming getGenerationTiming() { public boolean generatedOnInsert() {
return GenerationTiming.INSERT; return true;
}
/**
* @return {@code false}
*/
@Override
public boolean generatedOnUpdate() {
return false;
} }
@Override @Override

View File

@ -20,22 +20,22 @@ import org.hibernate.tuple.InMemoryGenerator;
*/ */
@Incubating @Incubating
public interface GeneratedValueResolver { public interface GeneratedValueResolver {
static GeneratedValueResolver from( // static GeneratedValueResolver from(
Generator generator, // Generator generator,
GenerationTiming requestedTiming, // GenerationTiming requestedTiming,
int dbSelectionPosition) { // int dbSelectionPosition) {
assert requestedTiming.isNotNever(); // assert requestedTiming.isNotNever();
//
// if ( generator == null || !generator.getGenerationTiming().includes( requestedTiming ) ) {
// return NoGeneratedValueResolver.INSTANCE;
// }
// else {
// return generator.generatedByDatabase()
// ? new InDatabaseGeneratedValueResolver( requestedTiming, dbSelectionPosition ) // in-db generation (column-default, function, etc)
// : new InMemoryGeneratedValueResolver( (InMemoryGenerator) generator, requestedTiming );
// }
// }
if ( generator == null || !generator.getGenerationTiming().includes( requestedTiming ) ) { // GenerationTiming getGenerationTiming();
return NoGeneratedValueResolver.INSTANCE;
}
else {
return generator.generatedByDatabase()
? new InDatabaseGeneratedValueResolver( requestedTiming, dbSelectionPosition ) // in-db generation (column-default, function, etc)
: new InMemoryGeneratedValueResolver( (InMemoryGenerator) generator, requestedTiming );
}
}
GenerationTiming getGenerationTiming();
Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue); Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue);
} }

View File

@ -18,18 +18,18 @@ import org.hibernate.tuple.GenerationTiming;
*/ */
@Internal @Internal
public class InDatabaseGeneratedValueResolver implements GeneratedValueResolver { public class InDatabaseGeneratedValueResolver implements GeneratedValueResolver {
private final GenerationTiming timing; // private final GenerationTiming timing;
private final int resultPosition; private final int resultPosition;
public InDatabaseGeneratedValueResolver(GenerationTiming timing, int resultPosition) { public InDatabaseGeneratedValueResolver(GenerationTiming timing, int resultPosition) {
this.timing = timing; // this.timing = timing;
this.resultPosition = resultPosition; this.resultPosition = resultPosition;
} }
@Override // @Override
public GenerationTiming getGenerationTiming() { // public GenerationTiming getGenerationTiming() {
return timing; // return timing;
} // }
@Override @Override
public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue) { public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue) {

View File

@ -18,18 +18,18 @@ import org.hibernate.tuple.InMemoryGenerator;
*/ */
@Internal @Internal
public class InMemoryGeneratedValueResolver implements GeneratedValueResolver { public class InMemoryGeneratedValueResolver implements GeneratedValueResolver {
private final GenerationTiming generationTiming; // private final GenerationTiming generationTiming;
private final InMemoryGenerator valueGenerator; private final InMemoryGenerator valueGenerator;
public InMemoryGeneratedValueResolver(InMemoryGenerator valueGenerator, GenerationTiming generationTiming) { public InMemoryGeneratedValueResolver(InMemoryGenerator valueGenerator, GenerationTiming generationTiming) {
this.valueGenerator = valueGenerator; this.valueGenerator = valueGenerator;
this.generationTiming = generationTiming; // this.generationTiming = generationTiming;
} }
@Override // @Override
public GenerationTiming getGenerationTiming() { // public GenerationTiming getGenerationTiming() {
return generationTiming; // return generationTiming;
} // }
@Override @Override
public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue) { public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue) {

View File

@ -11,8 +11,6 @@ import java.util.List;
import org.hibernate.Incubating; import org.hibernate.Incubating;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
@ -25,7 +23,6 @@ import org.hibernate.metamodel.mapping.InDatabaseGeneratedValueResolver;
import org.hibernate.query.spi.QueryOptions; import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.select.SelectStatement; import org.hibernate.sql.ast.tree.select.SelectStatement;
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl; import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
@ -33,7 +30,6 @@ import org.hibernate.sql.exec.spi.Callback;
import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcOperationQuerySelect; import org.hibernate.sql.exec.spi.JdbcOperationQuerySelect;
import org.hibernate.sql.exec.spi.JdbcParameterBindings; import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.hibernate.tuple.GenerationTiming; import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.Generator; import org.hibernate.tuple.Generator;
@ -100,7 +96,7 @@ public class GeneratedValuesProcessor {
final Generator generator = generators[ mapping.getStateArrayPosition() ]; final Generator generator = generators[ mapping.getStateArrayPosition() ];
if ( generator != null if ( generator != null
&& generator.generatedByDatabase() && generator.generatedByDatabase()
&& generator.getGenerationTiming().isNotNever() ) { && generator.isNotNever() ) {
// this attribute is generated for the timing we are processing... // this attribute is generated for the timing we are processing...
valueDescriptors.add( new GeneratedValueDescriptor( valueDescriptors.add( new GeneratedValueDescriptor(
new InDatabaseGeneratedValueResolver( timing, generatedValuesToSelect.size() ), new InDatabaseGeneratedValueResolver( timing, generatedValuesToSelect.size() ),

View File

@ -20,10 +20,10 @@ public class NoGeneratedValueResolver implements GeneratedValueResolver {
*/ */
public static final NoGeneratedValueResolver INSTANCE = new NoGeneratedValueResolver(); public static final NoGeneratedValueResolver INSTANCE = new NoGeneratedValueResolver();
@Override // @Override
public GenerationTiming getGenerationTiming() { // public GenerationTiming getGenerationTiming() {
return GenerationTiming.NEVER; // return GenerationTiming.NEVER;
} // }
@Override @Override
public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue) { public Object resolveGeneratedValue(Object[] row, Object entity, SharedSessionContractImplementor session, Object currentValue) {

View File

@ -2773,7 +2773,7 @@ public abstract class AbstractEntityPersister
else { else {
final Generator generator = attributeMapping.getGenerator(); final Generator generator = attributeMapping.getGenerator();
if ( generator!=null if ( generator!=null
&& generator.getGenerationTiming().includesUpdate() && generator.generatedOnUpdate()
&& generator.generatedByDatabase() ) { && generator.generatedByDatabase() ) {
final InDatabaseGenerator databaseGenerator = (InDatabaseGenerator) generator; final InDatabaseGenerator databaseGenerator = (InDatabaseGenerator) generator;
final Dialect dialect = getFactory().getJdbcServices().getDialect(); final Dialect dialect = getFactory().getJdbcServices().getDialect();

View File

@ -106,7 +106,7 @@ public class InsertCoordinator extends AbstractMutationCoordinator {
Generator generator = generators[i]; Generator generator = generators[i];
if ( generator != null if ( generator != null
&& !generator.generatedByDatabase() && !generator.generatedByDatabase()
&& generator.getGenerationTiming().includesInsert() ) { && generator.generatedOnInsert() ) {
values[i] = ( (InMemoryGenerator) generator ).generate( session, entity, values[i] ); values[i] = ( (InMemoryGenerator) generator ).generate( session, entity, values[i] );
entityPersister().setPropertyValue( entity, i, values[i] ); entityPersister().setPropertyValue( entity, i, values[i] );
} }
@ -438,7 +438,7 @@ public class InsertCoordinator extends AbstractMutationCoordinator {
private static boolean isValueGenerationInSql(Generator generator, Dialect dialect) { private static boolean isValueGenerationInSql(Generator generator, Dialect dialect) {
return generator != null return generator != null
&& generator.getGenerationTiming().includesInsert() && generator.generatedOnInsert()
&& generator.generatedByDatabase() && generator.generatedByDatabase()
&& ( (InDatabaseGenerator) generator ).referenceColumnsInSql(dialect); && ( (InDatabaseGenerator) generator ).referenceColumnsInSql(dialect);
} }

View File

@ -337,14 +337,14 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
private boolean isValueGenerationInSql(Generator generator, Dialect dialect) { private boolean isValueGenerationInSql(Generator generator, Dialect dialect) {
return generator != null return generator != null
&& generator.getGenerationTiming().includesUpdate() && generator.generatedOnUpdate()
&& generator.generatedByDatabase() && generator.generatedByDatabase()
&& ((InDatabaseGenerator) generator).referenceColumnsInSql(dialect); && ((InDatabaseGenerator) generator).referenceColumnsInSql(dialect);
} }
private boolean isValueGenerationInSqlNoWrite(Generator generator, Dialect dialect) { private boolean isValueGenerationInSqlNoWrite(Generator generator, Dialect dialect) {
return generator != null return generator != null
&& generator.getGenerationTiming().includesUpdate() && generator.generatedOnUpdate()
&& generator.generatedByDatabase() && generator.generatedByDatabase()
&& ((InDatabaseGenerator) generator).referenceColumnsInSql(dialect) && ((InDatabaseGenerator) generator).referenceColumnsInSql(dialect)
&& !((InDatabaseGenerator) generator).writePropertyValue(); && !((InDatabaseGenerator) generator).writePropertyValue();
@ -451,7 +451,7 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple
Generator generator = generators[i]; Generator generator = generators[i];
if ( generator != null if ( generator != null
&& !generator.generatedByDatabase() && !generator.generatedByDatabase()
&& generator.getGenerationTiming().includesUpdate() ) { && generator.generatedOnUpdate() ) {
newValues[i] = ( (InMemoryGenerator) generator ).generate( session, object, newValues[i] ); newValues[i] = ( (InMemoryGenerator) generator ).generate( session, object, newValues[i] );
entityPersister().setPropertyValue( object, i, newValues[i] ); entityPersister().setPropertyValue( object, i, newValues[i] );
fieldsPreUpdateNeeded[count++] = i; fieldsPreUpdateNeeded[count++] = i;

View File

@ -20,8 +20,13 @@ public class GeneratedAlwaysValueGeneration
public GeneratedAlwaysValueGeneration() {} public GeneratedAlwaysValueGeneration() {}
@Override @Override
public GenerationTiming getGenerationTiming() { public boolean generatedOnUpdate() {
return GenerationTiming.ALWAYS; return true;
}
@Override
public boolean generatedOnInsert() {
return true;
} }
@Override @Override

View File

@ -9,8 +9,6 @@ package org.hibernate.tuple;
import org.hibernate.annotations.Generated; import org.hibernate.annotations.Generated;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import java.lang.reflect.Member;
import static org.hibernate.internal.util.StringHelper.isEmpty; import static org.hibernate.internal.util.StringHelper.isEmpty;
/** /**
@ -41,8 +39,13 @@ public class GeneratedValueGeneration implements InDatabaseGenerator {
} }
@Override @Override
public GenerationTiming getGenerationTiming() { public boolean generatedOnInsert() {
return timing; return timing.includesInsert();
}
@Override
public boolean generatedOnUpdate() {
return timing.includesUpdate();
} }
@Override @Override

View File

@ -48,19 +48,6 @@ import java.io.Serializable;
* @since 6.2 * @since 6.2
*/ */
public interface Generator extends Serializable { public interface Generator extends Serializable {
/**
* Specifies that the property value is generated:
* <ul>
* <li>{@linkplain GenerationTiming#INSERT when the entity is inserted},
* <li>{@linkplain GenerationTiming#UPDATE when the entity is updated},
* <li>{@linkplain GenerationTiming#ALWAYS whenever the entity is inserted or updated}, or
* <li>{@linkplain GenerationTiming#NEVER never}.
* </ul>
*
* @return The {@link GenerationTiming} specifying when the value is generated.
*/
GenerationTiming getGenerationTiming();
/** /**
* Determines if the property value is generated in Java, or by the database. * Determines if the property value is generated in Java, or by the database.
* *
@ -68,4 +55,12 @@ public interface Generator extends Serializable {
* generated in Java using a {@link ValueGenerator}. * generated in Java using a {@link ValueGenerator}.
*/ */
boolean generatedByDatabase(); boolean generatedByDatabase();
boolean generatedOnInsert();
boolean generatedOnUpdate();
default boolean isNotNever() {
return generatedOnInsert() || generatedOnUpdate();
}
} }

View File

@ -24,7 +24,6 @@ import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
import static java.sql.Types.TIMESTAMP; import static java.sql.Types.TIMESTAMP;
import static org.hibernate.tuple.GenerationTiming.ALWAYS;
/** /**
* Value generation strategy using the query {@link Dialect#getCurrentTimestampSelectString()}. * Value generation strategy using the query {@link Dialect#getCurrentTimestampSelectString()}.
@ -68,9 +67,20 @@ public class SourceGeneration implements InMemoryGenerator, ValueGenerator<Objec
} }
} }
/**
* @return {@code true}
*/
@Override @Override
public GenerationTiming getGenerationTiming() { public boolean generatedOnInsert() {
return ALWAYS; return true;
}
/**
* @return {@code false}
*/
@Override
public boolean generatedOnUpdate() {
return false;
} }
@Override @Override

View File

@ -35,9 +35,20 @@ public class TenantIdGeneration implements InMemoryGenerator {
propertyType = getPropertyType( member ); propertyType = getPropertyType( member );
} }
/**
* @return {@code true}
*/
@Override @Override
public GenerationTiming getGenerationTiming() { public boolean generatedOnInsert() {
return GenerationTiming.INSERT; return true;
}
/**
* @return {@code false}
*/
@Override
public boolean generatedOnUpdate() {
return false;
} }
@Override @Override

View File

@ -22,6 +22,29 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
* @see AnnotationValueGeneration * @see AnnotationValueGeneration
*/ */
public interface ValueGeneration extends InMemoryGenerator, InDatabaseGenerator { public interface ValueGeneration extends InMemoryGenerator, InDatabaseGenerator {
/**
* Specifies that the property value is generated:
* <ul>
* <li>{@linkplain GenerationTiming#INSERT when the entity is inserted},
* <li>{@linkplain GenerationTiming#UPDATE when the entity is updated},
* <li>{@linkplain GenerationTiming#ALWAYS whenever the entity is inserted or updated}, or
* <li>{@linkplain GenerationTiming#NEVER never}.
* </ul>
*
* @return The {@link GenerationTiming} specifying when the value is generated.
*/
GenerationTiming getGenerationTiming();
@Override
default boolean generatedOnInsert() {
return getGenerationTiming().includesInsert();
}
@Override
default boolean generatedOnUpdate() {
return getGenerationTiming().includesUpdate();
}
/** /**
* Obtain the {@linkplain ValueGenerator Java value generator}, if the value is generated in * Obtain the {@linkplain ValueGenerator Java value generator}, if the value is generated in
* Java, or return {@code null} if the value is generated by the database. * Java, or return {@code null} if the value is generated by the database.

View File

@ -44,11 +44,23 @@ public class VmValueGeneration implements InMemoryGenerator {
: annotation.timing(); : annotation.timing();
} }
/**
* @return {@code true}
*/
@Override @Override
public GenerationTiming getGenerationTiming() { public boolean generatedOnInsert() {
return generationTiming; return generationTiming.includesInsert();
} }
/**
* @return {@code false}
*/
@Override
public boolean generatedOnUpdate() {
return generationTiming.includesUpdate();
}
@Override @Override
public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue) { public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue) {
return generator.generateValue( (Session) session, owner, currentValue ); return generator.generateValue( (Session) session, owner, currentValue );

View File

@ -42,7 +42,6 @@ import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.spi.PersisterCreationContext; import org.hibernate.persister.spi.PersisterCreationContext;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.Generator; import org.hibernate.tuple.Generator;
import org.hibernate.tuple.IdentifierProperty; import org.hibernate.tuple.IdentifierProperty;
import org.hibernate.tuple.InDatabaseGenerator; import org.hibernate.tuple.InDatabaseGenerator;
@ -310,34 +309,21 @@ public class EntityMetamodel implements Serializable {
propertyInsertability[i] = false; propertyInsertability[i] = false;
propertyUpdateability[i] = false; propertyUpdateability[i] = false;
} }
// we have some level of generation indicated if ( generator.generatedOnInsert() ) {
switch ( generator.getGenerationTiming() ) {
case INSERT:
if ( generator.generatedByDatabase() ) { if ( generator.generatedByDatabase() ) {
foundPostInsertGeneratedValues = true; foundPostInsertGeneratedValues = true;
} }
else { else {
foundPreInsertGeneratedValues = true; foundPreInsertGeneratedValues = true;
} }
break; }
case UPDATE: if ( generator.generatedOnUpdate() ) {
if ( generator.generatedByDatabase() ) { if ( generator.generatedByDatabase() ) {
foundPostUpdateGeneratedValues = true; foundPostUpdateGeneratedValues = true;
} }
else { else {
foundPreUpdateGeneratedValues = true; foundPreUpdateGeneratedValues = true;
} }
break;
case ALWAYS:
if ( generator.generatedByDatabase() ) {
foundPostInsertGeneratedValues = true;
foundPostUpdateGeneratedValues = true;
}
else {
foundPreInsertGeneratedValues = true;
foundPreUpdateGeneratedValues = true;
}
break;
} }
} }
@ -468,7 +454,7 @@ public class EntityMetamodel implements Serializable {
final GeneratorCreator generatorCreator = mappingProperty.getValueGeneratorCreator(); final GeneratorCreator generatorCreator = mappingProperty.getValueGeneratorCreator();
if ( generatorCreator != null ) { if ( generatorCreator != null ) {
final Generator generator = mappingProperty.createGenerator( context ); final Generator generator = mappingProperty.createGenerator( context );
if ( generator.getGenerationTiming().isNotNever() ) { if ( generator.isNotNever() ) {
return generator; return generator;
} }
} }
@ -524,7 +510,7 @@ public class EntityMetamodel implements Serializable {
} }
private void add(InMemoryGenerator inMemoryStrategy) { private void add(InMemoryGenerator inMemoryStrategy) {
if ( inMemoryStrategy.getGenerationTiming().isNotNever() ) { if ( inMemoryStrategy.isNotNever() ) {
hadInMemoryGeneration = true; hadInMemoryGeneration = true;
} }
} }
@ -535,7 +521,7 @@ public class EntityMetamodel implements Serializable {
} }
inDatabaseStrategies.add( inDatabaseStrategy ); inDatabaseStrategies.add( inDatabaseStrategy );
if ( inDatabaseStrategy.getGenerationTiming().isNotNever() ) { if ( inDatabaseStrategy.isNotNever() ) {
hadInDatabaseGeneration = true; hadInDatabaseGeneration = true;
} }
} }
@ -563,7 +549,8 @@ public class EntityMetamodel implements Serializable {
} }
// the base-line values for the aggregated InDatabaseValueGenerationStrategy we will build here. // the base-line values for the aggregated InDatabaseValueGenerationStrategy we will build here.
GenerationTiming timing = GenerationTiming.NEVER; boolean generatedOnInsert = false;
boolean generatedOnUpdate = false;
boolean referenceColumns = false; boolean referenceColumns = false;
String[] columnValues = new String[ composite.getColumnSpan() ]; String[] columnValues = new String[ composite.getColumnSpan() ];
@ -573,29 +560,8 @@ public class EntityMetamodel implements Serializable {
for ( Property property : composite.getProperties() ) { for ( Property property : composite.getProperties() ) {
propertyIndex++; propertyIndex++;
final InDatabaseGenerator subStrategy = inDatabaseStrategies.get( propertyIndex ); final InDatabaseGenerator subStrategy = inDatabaseStrategies.get( propertyIndex );
switch ( subStrategy.getGenerationTiming() ) { generatedOnUpdate = generatedOnUpdate || subStrategy.generatedOnUpdate();
case INSERT: generatedOnInsert = generatedOnInsert || subStrategy.generatedOnInsert();
switch ( timing ) {
case UPDATE:
timing = GenerationTiming.ALWAYS;
break;
case NEVER:
timing = GenerationTiming.INSERT;
break;
}
break;
case UPDATE:
switch ( timing ) {
case INSERT:
timing = GenerationTiming.ALWAYS;
break;
case NEVER:
timing = GenerationTiming.UPDATE;
}
break;
case ALWAYS:
timing = GenerationTiming.ALWAYS;
}
if ( subStrategy.referenceColumnsInSql(dialect) ) { if ( subStrategy.referenceColumnsInSql(dialect) ) {
// override base-line value // override base-line value
referenceColumns = true; referenceColumns = true;
@ -619,13 +585,17 @@ public class EntityMetamodel implements Serializable {
} }
// then use the aggregated values to build the InDatabaseValueGenerationStrategy // then use the aggregated values to build the InDatabaseValueGenerationStrategy
return new InDatabaseGeneratorImpl( timing, referenceColumns, columnValues ); return new InDatabaseGeneratorImpl( generatedOnUpdate, generatedOnInsert, referenceColumns, columnValues );
} }
else { else {
return new Generator() { return new Generator() {
@Override @Override
public GenerationTiming getGenerationTiming() { public boolean generatedOnInsert() {
return GenerationTiming.NEVER; return false;
}
@Override
public boolean generatedOnUpdate() {
return false;
} }
@Override @Override
public boolean generatedByDatabase() { public boolean generatedByDatabase() {
@ -637,22 +607,30 @@ public class EntityMetamodel implements Serializable {
} }
private static class InDatabaseGeneratorImpl implements InDatabaseGenerator { private static class InDatabaseGeneratorImpl implements InDatabaseGenerator {
private final GenerationTiming timing; private final boolean generatedOnUpdate;
private final boolean generatedOnInsert;
private final boolean referenceColumnInSql; private final boolean referenceColumnInSql;
private final String[] referencedColumnValues; private final String[] referencedColumnValues;
private InDatabaseGeneratorImpl( private InDatabaseGeneratorImpl(
GenerationTiming timing, boolean generatedOnUpdate,
boolean generatedOnInsert,
boolean referenceColumnInSql, boolean referenceColumnInSql,
String[] referencedColumnValues) { String[] referencedColumnValues) {
this.timing = timing; this.generatedOnUpdate = generatedOnUpdate;
this.generatedOnInsert = generatedOnInsert;
this.referenceColumnInSql = referenceColumnInSql; this.referenceColumnInSql = referenceColumnInSql;
this.referencedColumnValues = referencedColumnValues; this.referencedColumnValues = referencedColumnValues;
} }
@Override @Override
public GenerationTiming getGenerationTiming() { public boolean generatedOnInsert() {
return timing; return generatedOnInsert;
}
@Override
public boolean generatedOnUpdate() {
return generatedOnUpdate;
} }
@Override @Override
@ -694,17 +672,17 @@ public class EntityMetamodel implements Serializable {
// * That code checks that there is a natural identifier before making this call, so we assume the same here // * That code checks that there is a natural identifier before making this call, so we assume the same here
// * That code assumes a non-composite natural-id, so we assume the same here // * That code assumes a non-composite natural-id, so we assume the same here
final Generator strategy = generators[ naturalIdPropertyNumbers[0] ]; final Generator strategy = generators[ naturalIdPropertyNumbers[0] ];
return strategy != null && strategy.getGenerationTiming().isNotNever(); return strategy != null && strategy.isNotNever();
} }
public boolean isVersionGeneratedByDatabase() { public boolean isVersionGeneratedByDatabase() {
final Generator strategy = generators[ versionPropertyIndex ]; final Generator strategy = generators[ versionPropertyIndex ];
return strategy != null && strategy.getGenerationTiming().isNotNever() && strategy.generatedByDatabase(); return strategy != null && strategy.isNotNever() && strategy.generatedByDatabase();
} }
public boolean isVersionGeneratedInMemory() { public boolean isVersionGeneratedInMemory() {
final Generator strategy = generators[ versionPropertyIndex ]; final Generator strategy = generators[ versionPropertyIndex ];
return strategy != null && strategy.getGenerationTiming().isNotNever() && !strategy.generatedByDatabase(); return strategy != null && strategy.isNotNever() && !strategy.generatedByDatabase();
} }
public int[] getNaturalIdentifierProperties() { public int[] getNaturalIdentifierProperties() {

View File

@ -91,8 +91,13 @@ public class GeneratedUuidTests {
} }
@Override @Override
public GenerationTiming getGenerationTiming() { public boolean generatedOnInsert() {
return timing; return timing.includesInsert();
}
@Override
public boolean generatedOnUpdate() {
return timing.includesUpdate();
} }
@Override @Override

View File

@ -123,7 +123,7 @@ public final class AuditMetadataGenerator extends AbstractMetadataGenerator {
final GeneratorCreator generation = property.getValueGeneratorCreator(); final GeneratorCreator generation = property.getValueGeneratorCreator();
if ( generation instanceof GeneratedValueGeneration ) { if ( generation instanceof GeneratedValueGeneration ) {
final GeneratedValueGeneration valueGeneration = (GeneratedValueGeneration) generation; final GeneratedValueGeneration valueGeneration = (GeneratedValueGeneration) generation;
if ( valueGeneration.getGenerationTiming().includesInsert() ) { if ( valueGeneration.generatedOnInsert() ) {
return true; return true;
} }
} }