HHH-15800 introduce EventType + EventTypeSets in place of the previous "two booleans" approach

I hope @sebersole likes this better.

re-deprecate GenerationTime since the way forward is EventType
This commit is contained in:
Gavin 2022-12-03 21:29:25 +01:00 committed by Gavin King
parent c09664711d
commit 0228c3d185
28 changed files with 272 additions and 229 deletions

View File

@ -10,6 +10,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.hibernate.Remove; import org.hibernate.Remove;
import org.hibernate.generator.EventType;
import org.hibernate.generator.internal.CurrentTimestampGeneration; import org.hibernate.generator.internal.CurrentTimestampGeneration;
import org.hibernate.tuple.GenerationTiming; import org.hibernate.tuple.GenerationTiming;
@ -17,6 +18,8 @@ import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static org.hibernate.generator.EventType.INSERT;
import static org.hibernate.generator.EventType.UPDATE;
/** /**
* Specifies that the annotated field of property is a generated timestamp, * Specifies that the annotated field of property is a generated timestamp,
@ -68,9 +71,9 @@ public @interface CurrentTimestamp {
* Determines when the timestamp is generated. But default, it is updated * Determines when the timestamp is generated. But default, it is updated
* when any SQL {@code insert} or {@code update} statement is executed. * when any SQL {@code insert} or {@code update} statement is executed.
* If it should be generated just once, on the initial SQL {@code insert}, * If it should be generated just once, on the initial SQL {@code insert},
* explicitly specify {@link GenerationTime#INSERT event = INSERT}. * explicitly specify {@link EventType#INSERT event = INSERT}.
*/ */
GenerationTime event() default GenerationTime.INSERT_OR_UPDATE; EventType[] event() default {INSERT, UPDATE};
/** /**
* Determines when the timestamp is generated. But default, it is updated * Determines when the timestamp is generated. But default, it is updated

View File

@ -11,8 +11,12 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.hibernate.generator.EventType;
import org.hibernate.generator.internal.GeneratedGeneration; import org.hibernate.generator.internal.GeneratedGeneration;
import static org.hibernate.generator.EventType.INSERT;
import static org.hibernate.generator.EventType.UPDATE;
/** /**
* Specifies that the value of the annotated property is generated by the * Specifies that the value of the annotated property is generated by the
* database. The generated value will be automatically retrieved using a * database. The generated value will be automatically retrieved using a
@ -59,16 +63,15 @@ public @interface Generated {
* Specifies the events that cause the value to be generated by the * Specifies the events that cause the value to be generated by the
* database. * database.
* <ul> * <ul>
* <li>If {@link GenerationTime#INSERT}, the generated value will be * <li>If {@link EventType#INSERT} is included, the generated value
* selected after each SQL {@code insert} statement is executed. * will be selected after each SQL {@code insert} statement is
* <li>If {@link GenerationTime#UPDATE}, the generated value will be * executed.
* selected after each SQL {@code update} statement is executed. * <li>If {@link EventType#UPDATE} is included, the generated value
* <li>If {@link GenerationTime#INSERT_OR_UPDATE}, the generated value * will be selected after each SQL {@code update} statement is
* will be selected after each SQL {@code insert} or {@code update} * executed.
* statement is executed.
* </ul> * </ul>
*/ */
GenerationTime event() default GenerationTime.INSERT_OR_UPDATE; EventType[] event() default {INSERT, UPDATE};
/** /**
* Specifies the events that cause the value to be generated by the * Specifies the events that cause the value to be generated by the

View File

@ -8,8 +8,12 @@ package org.hibernate.annotations;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.Internal; import org.hibernate.Internal;
import org.hibernate.generator.EventType;
import org.hibernate.generator.EventTypeSets;
import org.hibernate.tuple.GenerationTiming; import org.hibernate.tuple.GenerationTiming;
import java.util.EnumSet;
/** /**
* Represents a class of events involving interaction with the database * Represents a class of events involving interaction with the database
* that causes generation of a new value. Intended for use with the * that causes generation of a new value. Intended for use with the
@ -19,7 +23,10 @@ import org.hibernate.tuple.GenerationTiming;
* *
* @see Generated * @see Generated
* @see CurrentTimestamp * @see CurrentTimestamp
*
* @deprecated use {@link EventType} and {@link EventTypeSets} instead
*/ */
@Deprecated(since = "6.2")
public enum GenerationTime { public enum GenerationTime {
/** /**
* Indicates that a value is never generated. * Indicates that a value is never generated.
@ -37,30 +44,22 @@ public enum GenerationTime {
UPDATE, UPDATE,
/** /**
* Indicates that a new value is generated on insert and on update. * Indicates that a new value is generated on insert and on update.
*
* @since 6.2
*/ */
INSERT_OR_UPDATE,
/**
* Indicates that a new value is generated on insert and on update.
*
* @deprecated use {@link #INSERT_OR_UPDATE}
*/
@Deprecated(since = "6.2")
ALWAYS; ALWAYS;
/** public EnumSet<EventType> eventTypes() {
* @return {@code true} if a new value is generated when an insert is executed switch (this) {
*/ case NEVER:
public boolean includesInsert() { return EventTypeSets.NONE;
return getEquivalent().includesInsert(); case ALWAYS:
return EventTypeSets.ALL;
case INSERT:
return EventTypeSets.INSERT_ONLY;
case UPDATE:
return EventTypeSets.UPDATE_ONLY;
default:
throw new AssertionFailure("unknown event");
} }
/**
* @return {@code true} if a new value is generated when an update is executed
*/
public boolean includesUpdate() {
return getEquivalent().includesUpdate();
} }
/** /**
@ -70,7 +69,6 @@ public enum GenerationTime {
public GenerationTiming getEquivalent() { public GenerationTiming getEquivalent() {
switch (this) { switch (this) {
case ALWAYS: case ALWAYS:
case INSERT_OR_UPDATE:
return GenerationTiming.ALWAYS; return GenerationTiming.ALWAYS;
case INSERT: case INSERT:
return GenerationTiming.INSERT; return GenerationTiming.INSERT;

View File

@ -572,12 +572,12 @@ 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) ) {
if ( !generator.generatedOnInsert() ) { if ( !generator.generatesOnInsert() ) {
throw new AnnotationException("Property '" + property.getName() throw new AnnotationException("Property '" + property.getName()
+ "' is annotated '@Version' but has a 'Generator' which does not generate on inserts" + "' is annotated '@Version' but has a 'Generator' which does not generate on inserts"
); );
} }
if ( !generator.generatedOnUpdate() ) { if ( !generator.generatesOnUpdate() ) {
throw new AnnotationException("Property '" + property.getName() throw new AnnotationException("Property '" + property.getName()
+ "' is annotated '@Version' but has a 'Generator' which does not generate on updates" + "' is annotated '@Version' but has a 'Generator' which does not generate on updates"
); );
@ -586,11 +586,11 @@ public class PropertyBinder {
} }
private static void checkIdGeneratorTiming(Class<? extends Annotation> annotationType, Generator generator) { private static void checkIdGeneratorTiming(Class<? extends Annotation> annotationType, Generator generator) {
if ( !generator.generatedOnInsert() ) { if ( !generator.generatesOnInsert() ) {
throw new MappingException( "Annotation '" + annotationType throw new MappingException( "Annotation '" + annotationType
+ "' is annotated 'IdGeneratorType' but the given 'Generator' does not generate on inserts"); + "' is annotated 'IdGeneratorType' but the given 'Generator' does not generate on inserts");
} }
if ( generator.generatedOnUpdate() ) { if ( generator.generatesOnUpdate() ) {
throw new MappingException( "Annotation '" + annotationType throw new MappingException( "Annotation '" + annotationType
+ "' is annotated 'IdGeneratorType' but the given 'Generator' generates on updates (it must generate only on inserts)"); + "' 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.isNotNever(); return generator != null && generator.generatesSometimes();
} }
/** /**

View File

@ -0,0 +1,29 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.generator;
/**
* Enumerates event types that can result in generation of a new value.
* A {@link Generator} must specify which events it responds to, by
* implementing {@link Generator#getEventTypes()}.
* <p>
* We usually work with {@linkplain EventTypeSets sets} of event types,
* even though there are only two types.
*
* @author Gavin King
*
* @since 6.2
*
* @see Generator
* @see org.hibernate.annotations.Generated
* @see org.hibernate.annotations.CurrentTimestamp
* @see EventTypeSets
*/
public enum EventType {
INSERT,
UPDATE;
}

View File

@ -0,0 +1,35 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.generator;
import java.util.EnumSet;
import java.util.Set;
import static org.hibernate.generator.EventType.INSERT;
import static org.hibernate.generator.EventType.UPDATE;
/**
* For convenience, enumerates the possible combinations of {@link EventType}.
* <p>
* This list supersedes the enumerations {@link org.hibernate.annotations.GenerationTime}
* and {@link org.hibernate.tuple.GenerationTiming} from older versions of Hibernate.
*
* @author Gavin King
*
* @since 6.2
*/
public class EventTypeSets {
public static final EnumSet<EventType> NONE = EnumSet.noneOf(EventType.class);
public static final EnumSet<EventType> INSERT_ONLY = EnumSet.of(INSERT);
public static final EnumSet<EventType> UPDATE_ONLY = EnumSet.of(UPDATE);
public static final EnumSet<EventType> INSERT_AND_UPDATE = EnumSet.of(INSERT, UPDATE);
public static final EnumSet<EventType> ALL = EnumSet.allOf(EventType.class);
public static EnumSet<EventType> fromArray(EventType[] types) {
return EnumSet.copyOf( Set.of(types) );
}
}

View File

@ -10,6 +10,10 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.tuple.ValueGenerator; import org.hibernate.tuple.ValueGenerator;
import java.io.Serializable; import java.io.Serializable;
import java.util.EnumSet;
import static org.hibernate.generator.EventType.INSERT;
import static org.hibernate.generator.EventType.UPDATE;
/** /**
* Describes the generation of values of a certain field or property of an entity. A generated * Describes the generation of values of a certain field or property of an entity. A generated
@ -38,6 +42,14 @@ import java.io.Serializable;
* <li>declare a constructor which accepts just the annotation instance, or * <li>declare a constructor which accepts just the annotation instance, or
* <li>declare a only default constructor, in which case it will not receive parameters. * <li>declare a only default constructor, in which case it will not receive parameters.
* </ul> * </ul>
* A generator must implement {@link #getEventTypes()} to specify the events for which it should be
* called to produce a new value. {@link EventTypeSets} provides a convenient list of possibilities.
* <p>
* An {@linkplain jakarta.persistence.Id identifier} generator is a generator capable of producing
* surrogate primary key values. An identifier generator must respond to insert events only. That
* is, {@link #getEventTypes()} must return {@link EventTypeSets#INSERT_ONLY}. It may be integrated
* using the {@link org.hibernate.annotations.IdGeneratorType} meta-annotation or the older-style
* {@link org.hibernate.annotations.GenericGenerator} annotation.
* *
* @see org.hibernate.annotations.ValueGenerationType * @see org.hibernate.annotations.ValueGenerationType
* @see org.hibernate.annotations.IdGeneratorType * @see org.hibernate.annotations.IdGeneratorType
@ -57,11 +69,25 @@ public interface Generator extends Serializable {
*/ */
boolean generatedByDatabase(); boolean generatedByDatabase();
boolean generatedOnInsert(); /**
* The {@linkplain EventType event types} for which this generator should be called
* to produce a new value.
* <p>
* Identifier generators must return {@link EventTypeSets#INSERT_ONLY}.
*
* @return a set of {@link EventType}s.
*/
EnumSet<EventType> getEventTypes();
boolean generatedOnUpdate(); default boolean generatesSometimes() {
return !getEventTypes().isEmpty();
}
default boolean isNotNever() { default boolean generatesOnInsert() {
return generatedOnInsert() || generatedOnUpdate(); return getEventTypes().contains(INSERT);
}
default boolean generatesOnUpdate() {
return getEventTypes().contains(UPDATE);
} }
} }

View File

@ -7,7 +7,6 @@
package org.hibernate.generator; package org.hibernate.generator;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.tuple.GenerationTiming;
/** /**
* A generator that is called to produce a value just before a row is written to the database. * A generator that is called to produce a value just before a row is written to the database.
@ -16,8 +15,8 @@ import org.hibernate.tuple.GenerationTiming;
* database via a parameter of a JDBC prepared statement, just like any other field or property * database via a parameter of a JDBC prepared statement, just like any other field or property
* value. * value.
* <p> * <p>
* Any {@link InMemoryGenerator} with {@linkplain #getGenerationTiming() generation timing} * Any {@link InMemoryGenerator} with {@linkplain #getEventTypes() generation event types}
* {@link GenerationTiming#INSERT} may be used to produce {@linkplain jakarta.persistence.Id * {@link EventTypeSets#INSERT_ONLY} may be used to produce {@linkplain jakarta.persistence.Id
* identifiers}. The built-in identifier generators all implement the older extension point * identifiers}. The built-in identifier generators all implement the older extension point
* {@link org.hibernate.id.IdentifierGenerator}, which is a subtype of this interface, but that * {@link org.hibernate.id.IdentifierGenerator}, which is a subtype of this interface, but that
* is no longer a requirement for custom id generators. * is no longer a requirement for custom id generators.

View File

@ -10,22 +10,25 @@ import org.hibernate.AssertionFailure;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.CurrentTimestamp; import org.hibernate.annotations.CurrentTimestamp;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.annotations.SourceType; import org.hibernate.annotations.SourceType;
import org.hibernate.annotations.UpdateTimestamp; import org.hibernate.annotations.UpdateTimestamp;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.generator.EventType;
import org.hibernate.generator.InDatabaseGenerator; import org.hibernate.generator.InDatabaseGenerator;
import org.hibernate.generator.InMemoryGenerator; import org.hibernate.generator.InMemoryGenerator;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.generator.GeneratorCreationContext; import org.hibernate.generator.GeneratorCreationContext;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.TimestampGenerators; import org.hibernate.tuple.TimestampGenerators;
import org.hibernate.tuple.ValueGenerator; import org.hibernate.tuple.ValueGenerator;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.util.EnumSet;
import static org.hibernate.annotations.GenerationTime.INSERT; import static org.hibernate.generator.EventTypeSets.INSERT_AND_UPDATE;
import static org.hibernate.annotations.GenerationTime.INSERT_OR_UPDATE; import static org.hibernate.generator.EventTypeSets.INSERT_ONLY;
import static org.hibernate.generator.EventTypeSets.fromArray;
/** /**
* Value generation strategy which produces a timestamp using the database * Value generation strategy which produces a timestamp using the database
@ -45,22 +48,24 @@ import static org.hibernate.annotations.GenerationTime.INSERT_OR_UPDATE;
* @author Gavin King * @author Gavin King
*/ */
public class CurrentTimestampGeneration implements InMemoryGenerator, InDatabaseGenerator { public class CurrentTimestampGeneration implements InMemoryGenerator, InDatabaseGenerator {
private final GenerationTime timing; private final EnumSet<EventType> eventTypes;
private final ValueGenerator<?> generator; private final ValueGenerator<?> generator;
public CurrentTimestampGeneration(CurrentTimestamp annotation, Member member, GeneratorCreationContext context) { public CurrentTimestampGeneration(CurrentTimestamp annotation, Member member, GeneratorCreationContext context) {
generator = getGenerator( annotation.source(), member ); generator = getGenerator( annotation.source(), member );
timing = annotation.event() == INSERT_OR_UPDATE ? annotation.timing().getEquivalent() : annotation.event(); eventTypes = annotation.timing() == GenerationTiming.ALWAYS
? fromArray( annotation.event() )
: annotation.timing().getEquivalent().eventTypes();
} }
public CurrentTimestampGeneration(CreationTimestamp annotation, Member member, GeneratorCreationContext context) { public CurrentTimestampGeneration(CreationTimestamp annotation, Member member, GeneratorCreationContext context) {
generator = getGenerator( annotation.source(), member ); generator = getGenerator( annotation.source(), member );
timing = INSERT; eventTypes = INSERT_ONLY;
} }
public CurrentTimestampGeneration(UpdateTimestamp annotation, Member member, GeneratorCreationContext context) { public CurrentTimestampGeneration(UpdateTimestamp annotation, Member member, GeneratorCreationContext context) {
generator = getGenerator( annotation.source(), member ); generator = getGenerator( annotation.source(), member );
timing = INSERT_OR_UPDATE; eventTypes = INSERT_AND_UPDATE;
} }
private static ValueGenerator<?> getGenerator(SourceType source, Member member) { private static ValueGenerator<?> getGenerator(SourceType source, Member member) {
@ -81,13 +86,8 @@ public class CurrentTimestampGeneration implements InMemoryGenerator, InDatabase
} }
@Override @Override
public boolean generatedOnInsert() { public EnumSet<EventType> getEventTypes() {
return timing.includesInsert(); return eventTypes;
}
@Override
public boolean generatedOnUpdate() {
return timing.includesUpdate();
} }
@Override @Override

View File

@ -8,8 +8,13 @@ package org.hibernate.generator.internal;
import org.hibernate.annotations.GeneratedColumn; import org.hibernate.annotations.GeneratedColumn;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.generator.EventType;
import org.hibernate.generator.InDatabaseGenerator; import org.hibernate.generator.InDatabaseGenerator;
import java.util.EnumSet;
import static org.hibernate.generator.EventTypeSets.ALL;
/** /**
* For {@link GeneratedColumn}. * For {@link GeneratedColumn}.
* *
@ -20,13 +25,8 @@ public class GeneratedAlwaysGeneration implements InDatabaseGenerator {
public GeneratedAlwaysGeneration() {} public GeneratedAlwaysGeneration() {}
@Override @Override
public boolean generatedOnUpdate() { public EnumSet<EventType> getEventTypes() {
return true; return ALL;
}
@Override
public boolean generatedOnInsert() {
return true;
} }
@Override @Override

View File

@ -9,45 +9,46 @@ package org.hibernate.generator.internal;
import org.hibernate.annotations.Generated; import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime; import org.hibernate.annotations.GenerationTime;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.generator.EventType;
import org.hibernate.generator.InDatabaseGenerator; import org.hibernate.generator.InDatabaseGenerator;
import org.hibernate.tuple.AnnotationValueGeneration;
import static org.hibernate.annotations.GenerationTime.INSERT_OR_UPDATE; import java.util.EnumSet;
import static org.hibernate.generator.EventTypeSets.fromArray;
import static org.hibernate.internal.util.StringHelper.isEmpty; import static org.hibernate.internal.util.StringHelper.isEmpty;
/** /**
* A {@link AnnotationValueGeneration} which marks a property as generated in the database. * A fairly generic {@link InDatabaseGenerator} which marks a property as generated in the
* database with semantics given explicitly by a {@link Generated @Generated} annotation.
*
* @see Generated
* *
* @author Steve Ebersole * @author Steve Ebersole
* @author Gunnar Morling * @author Gunnar Morling
*/ */
public class GeneratedGeneration implements InDatabaseGenerator { public class GeneratedGeneration implements InDatabaseGenerator {
private GenerationTime timing; private final EnumSet<EventType> eventTypes;
private boolean writable; private final boolean writable;
private String[] sql; private final String[] sql;
public GeneratedGeneration() {
}
public GeneratedGeneration(GenerationTime event) { public GeneratedGeneration(GenerationTime event) {
this.timing = event; eventTypes = event.eventTypes();
writable = false;
sql = null;
} }
public GeneratedGeneration(Generated annotation) { public GeneratedGeneration(Generated annotation) {
timing = annotation.event() == INSERT_OR_UPDATE ? annotation.value() : annotation.event(); eventTypes = annotation.value() == GenerationTime.ALWAYS
? fromArray( annotation.event() )
: annotation.value().eventTypes();
sql = isEmpty( annotation.sql() ) ? null : new String[] { annotation.sql() }; sql = isEmpty( annotation.sql() ) ? null : new String[] { annotation.sql() };
writable = annotation.writable() || sql != null; writable = annotation.writable() || sql != null;
} }
@Override @Override
public boolean generatedOnInsert() { public EnumSet<EventType> getEventTypes() {
return timing.includesInsert(); return eventTypes;
}
@Override
public boolean generatedOnUpdate() {
return timing.includesUpdate();
} }
@Override @Override

View File

@ -14,6 +14,8 @@ import org.hibernate.annotations.SourceType;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator; import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.generator.EventType;
import org.hibernate.generator.EventTypeSets;
import org.hibernate.generator.GeneratorCreationContext; import org.hibernate.generator.GeneratorCreationContext;
import org.hibernate.generator.InMemoryGenerator; import org.hibernate.generator.InMemoryGenerator;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
@ -27,8 +29,10 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.EnumSet;
import static java.sql.Types.TIMESTAMP; import static java.sql.Types.TIMESTAMP;
import static org.hibernate.generator.EventTypeSets.INSERT_ONLY;
/** /**
* Value generation strategy using the query {@link Dialect#getCurrentTimestampSelectString()}. * Value generation strategy using the query {@link Dialect#getCurrentTimestampSelectString()}.
@ -77,19 +81,11 @@ public class SourceGeneration implements InMemoryGenerator {
} }
/** /**
* @return {@code true} * @return {@link EventTypeSets#INSERT_ONLY}
*/ */
@Override @Override
public boolean generatedOnInsert() { public EnumSet<EventType> getEventTypes() {
return true; return INSERT_ONLY;
}
/**
* @return {@code false}
*/
@Override
public boolean generatedOnUpdate() {
return false;
} }
@Override @Override

View File

@ -12,12 +12,16 @@ import org.hibernate.annotations.TenantId;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver; import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.generator.EventType;
import org.hibernate.generator.EventTypeSets;
import org.hibernate.generator.InMemoryGenerator; import org.hibernate.generator.InMemoryGenerator;
import org.hibernate.generator.GeneratorCreationContext; import org.hibernate.generator.GeneratorCreationContext;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.util.EnumSet;
import static org.hibernate.generator.EventTypeSets.INSERT_ONLY;
import static org.hibernate.internal.util.ReflectHelper.getPropertyType; import static org.hibernate.internal.util.ReflectHelper.getPropertyType;
/** /**
@ -39,19 +43,11 @@ public class TenantIdGeneration implements InMemoryGenerator {
} }
/** /**
* @return {@code true} * @return {@link EventTypeSets#INSERT_ONLY}
*/ */
@Override @Override
public boolean generatedOnInsert() { public EnumSet<EventType> getEventTypes() {
return true; return INSERT_ONLY;
}
/**
* @return {@code false}
*/
@Override
public boolean generatedOnUpdate() {
return false;
} }
@Override @Override

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.id; package org.hibernate.id;
import java.util.EnumSet;
import java.util.Properties; import java.util.Properties;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
@ -14,15 +15,18 @@ import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.model.relational.ExportableProducer; import org.hibernate.boot.model.relational.ExportableProducer;
import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.generator.EventType;
import org.hibernate.generator.EventTypeSets;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.generator.InMemoryGenerator; import org.hibernate.generator.InMemoryGenerator;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import static org.hibernate.generator.EventTypeSets.INSERT_ONLY;
/** /**
* 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
* {@link InMemoryGenerator} with timing {@link GenerationTiming#INSERT} * {@link InMemoryGenerator} with timing {@link EventTypeSets#INSERT_ONLY}
* may now be used. * may now be used.
* <p> * <p>
* This interface extends {@code InMemoryGenerator} with some additional * This interface extends {@code InMemoryGenerator} with some additional
@ -143,19 +147,11 @@ public interface IdentifierGenerator extends InMemoryGenerator, ExportableProduc
} }
/** /**
* @return {@code true} * @return {@link EventTypeSets#INSERT_ONLY}
*/ */
@Override @Override
default boolean generatedOnInsert() { default EnumSet<EventType> getEventTypes() {
return true; return INSERT_ONLY;
}
/**
* @return {@code false}
*/
@Override
default boolean generatedOnUpdate() {
return false;
} }
/** /**

View File

@ -6,17 +6,21 @@
*/ */
package org.hibernate.id; package org.hibernate.id;
import org.hibernate.generator.EventType;
import org.hibernate.generator.EventTypeSets;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.generator.InDatabaseGenerator; import org.hibernate.generator.InDatabaseGenerator;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import java.util.EnumSet;
import java.util.Properties; import java.util.Properties;
import static org.hibernate.generator.EventTypeSets.INSERT_ONLY;
/** /**
* 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.
* Any {@link InDatabaseGenerator} with timing {@link GenerationTiming#INSERT} may now * Any {@link InDatabaseGenerator} with timing {@link EventTypeSets#INSERT_ONLY} may now
* be used. * be used.
* *
* @see IdentifierGenerator * @see IdentifierGenerator
@ -26,19 +30,11 @@ import java.util.Properties;
public interface PostInsertIdentifierGenerator extends InDatabaseGenerator, Configurable { public interface PostInsertIdentifierGenerator extends InDatabaseGenerator, Configurable {
/** /**
* @return {@code true} * @return {@link EventTypeSets#INSERT_ONLY}
*/ */
@Override @Override
default boolean generatedOnInsert() { default EnumSet<EventType> getEventTypes() {
return true; return INSERT_ONLY;
}
/**
* @return {@code false}
*/
@Override
default boolean generatedOnUpdate() {
return false;
} }
/** /**

View File

@ -7,16 +7,20 @@
package org.hibernate.id.uuid; package org.hibernate.id.uuid;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.util.EnumSet;
import java.util.UUID; 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.generator.EventType;
import org.hibernate.generator.EventTypeSets;
import org.hibernate.id.factory.spi.CustomIdGeneratorCreationContext; import org.hibernate.id.factory.spi.CustomIdGeneratorCreationContext;
import org.hibernate.generator.InMemoryGenerator; import org.hibernate.generator.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;
import static org.hibernate.annotations.UuidGenerator.Style.TIME; import static org.hibernate.annotations.UuidGenerator.Style.TIME;
import static org.hibernate.generator.EventTypeSets.INSERT_ONLY;
import static org.hibernate.internal.util.ReflectHelper.getPropertyType; import static org.hibernate.internal.util.ReflectHelper.getPropertyType;
/** /**
@ -60,19 +64,11 @@ public class UuidGenerator implements InMemoryGenerator {
} }
/** /**
* @return {@code true} * @return {@link EventTypeSets#INSERT_ONLY}
*/ */
@Override @Override
public boolean generatedOnInsert() { public EnumSet<EventType> getEventTypes() {
return true; return INSERT_ONLY;
}
/**
* @return {@code false}
*/
@Override
public boolean generatedOnUpdate() {
return false;
} }
@Override @Override

View File

@ -97,7 +97,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.isNotNever() ) { && generator.generatesSometimes() ) {
// 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

@ -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.generatedOnUpdate() && generator.generatesOnUpdate()
&& 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.generatedOnInsert() ) { && generator.generatesOnInsert() ) {
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.generatedOnInsert() && generator.generatesOnInsert()
&& 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.generatedOnUpdate() && generator.generatesOnUpdate()
&& 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.generatedOnUpdate() && generator.generatesOnUpdate()
&& 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.generatedOnUpdate() ) { && generator.generatesOnUpdate() ) {
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

@ -84,7 +84,7 @@ public enum GenerationTiming {
public GenerationTime getEquivalent() { public GenerationTime getEquivalent() {
switch (this) { switch (this) {
case ALWAYS: case ALWAYS:
return GenerationTime.INSERT_OR_UPDATE; return GenerationTime.ALWAYS;
case INSERT: case INSERT:
return GenerationTime.INSERT; return GenerationTime.INSERT;
case UPDATE: case UPDATE:

View File

@ -9,10 +9,13 @@ package org.hibernate.tuple;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.generator.EventType;
import org.hibernate.generator.Generator; import org.hibernate.generator.Generator;
import org.hibernate.generator.InDatabaseGenerator; import org.hibernate.generator.InDatabaseGenerator;
import org.hibernate.generator.InMemoryGenerator; import org.hibernate.generator.InMemoryGenerator;
import java.util.EnumSet;
/** /**
* A value generator that can adapt to both Java value generation and database value generation. * A value generator that can adapt to both Java value generation and database value generation.
* <p> * <p>
@ -39,13 +42,8 @@ public interface ValueGeneration extends InMemoryGenerator, InDatabaseGenerator
GenerationTiming getGenerationTiming(); GenerationTiming getGenerationTiming();
@Override @Override
default boolean generatedOnInsert() { default EnumSet<EventType> getEventTypes() {
return getGenerationTiming().includesInsert(); return getGenerationTiming().getEquivalent().eventTypes();
}
@Override
default boolean generatedOnUpdate() {
return getGenerationTiming().includesUpdate();
} }
/** /**

View File

@ -7,13 +7,14 @@
package org.hibernate.tuple; package org.hibernate.tuple;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.EnumSet;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.Internal; import org.hibernate.Internal;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.annotations.GeneratorType; import org.hibernate.annotations.GeneratorType;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.generator.EventType;
import org.hibernate.generator.InMemoryGenerator; import org.hibernate.generator.InMemoryGenerator;
import static org.hibernate.internal.util.ReflectHelper.getDefaultConstructor; import static org.hibernate.internal.util.ReflectHelper.getDefaultConstructor;
@ -30,7 +31,7 @@ import static org.hibernate.internal.util.ReflectHelper.getDefaultConstructor;
@Deprecated(since = "6.2") @Deprecated(since = "6.2")
public class VmValueGeneration implements InMemoryGenerator { public class VmValueGeneration implements InMemoryGenerator {
private final GenerationTime timing; private final EnumSet<EventType> eventTypes;
private final ValueGenerator<?> generator; private final ValueGenerator<?> generator;
public VmValueGeneration(GeneratorType annotation) { public VmValueGeneration(GeneratorType annotation) {
@ -41,26 +42,14 @@ public class VmValueGeneration implements InMemoryGenerator {
catch (Exception e) { catch (Exception e) {
throw new HibernateException( "Couldn't instantiate value generator", e ); throw new HibernateException( "Couldn't instantiate value generator", e );
} }
timing = annotation.when(); eventTypes = annotation.when().eventTypes();
} }
/**
* @return {@code true}
*/
@Override @Override
public boolean generatedOnInsert() { public EnumSet<EventType> getEventTypes() {
return timing.includesInsert(); return eventTypes;
} }
/**
* @return {@code false}
*/
@Override
public boolean generatedOnUpdate() {
return timing.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

@ -10,6 +10,7 @@ import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.BitSet; import java.util.BitSet;
import java.util.Collections; import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -29,6 +30,7 @@ import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadeStyles; import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.engine.spi.CascadingActions; import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.generator.EventType;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.collections.ArrayHelper;
@ -56,6 +58,7 @@ import org.hibernate.type.EntityType;
import org.hibernate.type.ManyToOneType; import org.hibernate.type.ManyToOneType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import static org.hibernate.generator.EventTypeSets.NONE;
import static org.hibernate.internal.CoreLogging.messageLogger; import static org.hibernate.internal.CoreLogging.messageLogger;
/** /**
@ -309,7 +312,7 @@ public class EntityMetamodel implements Serializable {
propertyInsertability[i] = false; propertyInsertability[i] = false;
propertyUpdateability[i] = false; propertyUpdateability[i] = false;
} }
if ( generator.generatedOnInsert() ) { if ( generator.generatesOnInsert() ) {
if ( generator.generatedByDatabase() ) { if ( generator.generatedByDatabase() ) {
foundPostInsertGeneratedValues = true; foundPostInsertGeneratedValues = true;
} }
@ -317,7 +320,7 @@ public class EntityMetamodel implements Serializable {
foundPreInsertGeneratedValues = true; foundPreInsertGeneratedValues = true;
} }
} }
if ( generator.generatedOnUpdate() ) { if ( generator.generatesOnUpdate() ) {
if ( generator.generatedByDatabase() ) { if ( generator.generatedByDatabase() ) {
foundPostUpdateGeneratedValues = true; foundPostUpdateGeneratedValues = true;
} }
@ -454,7 +457,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.isNotNever() ) { if ( generator.generatesSometimes() ) {
return generator; return generator;
} }
} }
@ -510,7 +513,7 @@ public class EntityMetamodel implements Serializable {
} }
private void add(InMemoryGenerator inMemoryStrategy) { private void add(InMemoryGenerator inMemoryStrategy) {
if ( inMemoryStrategy.isNotNever() ) { if ( inMemoryStrategy.generatesSometimes() ) {
hadInMemoryGeneration = true; hadInMemoryGeneration = true;
} }
} }
@ -521,7 +524,7 @@ public class EntityMetamodel implements Serializable {
} }
inDatabaseStrategies.add( inDatabaseStrategy ); inDatabaseStrategies.add( inDatabaseStrategy );
if ( inDatabaseStrategy.isNotNever() ) { if ( inDatabaseStrategy.generatesSometimes() ) {
hadInDatabaseGeneration = true; hadInDatabaseGeneration = true;
} }
} }
@ -549,8 +552,7 @@ 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.
boolean generatedOnInsert = false; EnumSet<EventType> eventTypes = EnumSet.noneOf(EventType.class);
boolean generatedOnUpdate = false;
boolean referenceColumns = false; boolean referenceColumns = false;
String[] columnValues = new String[ composite.getColumnSpan() ]; String[] columnValues = new String[ composite.getColumnSpan() ];
@ -559,15 +561,14 @@ public class EntityMetamodel implements Serializable {
int columnIndex = 0; int columnIndex = 0;
for ( Property property : composite.getProperties() ) { for ( Property property : composite.getProperties() ) {
propertyIndex++; propertyIndex++;
final InDatabaseGenerator subStrategy = inDatabaseStrategies.get( propertyIndex ); final InDatabaseGenerator generator = inDatabaseStrategies.get( propertyIndex );
generatedOnUpdate = generatedOnUpdate || subStrategy.generatedOnUpdate(); eventTypes.addAll( generator.getEventTypes() );
generatedOnInsert = generatedOnInsert || subStrategy.generatedOnInsert(); if ( generator.referenceColumnsInSql(dialect) ) {
if ( subStrategy.referenceColumnsInSql(dialect) ) {
// override base-line value // override base-line value
referenceColumns = true; referenceColumns = true;
} }
if ( subStrategy.getReferencedColumnValues(dialect) != null ) { if ( generator.getReferencedColumnValues(dialect) != null ) {
if ( subStrategy.getReferencedColumnValues(dialect).length != property.getColumnSpan() ) { if ( generator.getReferencedColumnValues(dialect).length != property.getColumnSpan() ) {
throw new ValueGenerationStrategyException( throw new ValueGenerationStrategyException(
"Internal error : mismatch between number of collected 'referenced column values'" + "Internal error : mismatch between number of collected 'referenced column values'" +
" and number of columns for composite attribute : " + mappingProperty.getName() + " and number of columns for composite attribute : " + mappingProperty.getName() +
@ -575,7 +576,7 @@ public class EntityMetamodel implements Serializable {
); );
} }
System.arraycopy( System.arraycopy(
subStrategy.getReferencedColumnValues(dialect), generator.getReferencedColumnValues(dialect),
0, 0,
columnValues, columnValues,
columnIndex, columnIndex,
@ -585,19 +586,14 @@ 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( generatedOnUpdate, generatedOnInsert, referenceColumns, columnValues ); return new InDatabaseGeneratorImpl( eventTypes, referenceColumns, columnValues );
} }
else { else {
return new Generator() { return new Generator() {
@Override @Override
public boolean generatedOnInsert() { public EnumSet<EventType> getEventTypes() {
return false; return NONE;
} }
@Override
public boolean generatedOnUpdate() {
return false;
}
@Override
public boolean generatedByDatabase() { public boolean generatedByDatabase() {
return false; return false;
} }
@ -607,30 +603,22 @@ public class EntityMetamodel implements Serializable {
} }
private static class InDatabaseGeneratorImpl implements InDatabaseGenerator { private static class InDatabaseGeneratorImpl implements InDatabaseGenerator {
private final boolean generatedOnUpdate; private final EnumSet<EventType> eventTypes;
private final boolean generatedOnInsert;
private final boolean referenceColumnInSql; private final boolean referenceColumnInSql;
private final String[] referencedColumnValues; private final String[] referencedColumnValues;
private InDatabaseGeneratorImpl( private InDatabaseGeneratorImpl(
boolean generatedOnUpdate, EnumSet<EventType> eventTypes,
boolean generatedOnInsert,
boolean referenceColumnInSql, boolean referenceColumnInSql,
String[] referencedColumnValues) { String[] referencedColumnValues) {
this.generatedOnUpdate = generatedOnUpdate; this.eventTypes = eventTypes;
this.generatedOnInsert = generatedOnInsert;
this.referenceColumnInSql = referenceColumnInSql; this.referenceColumnInSql = referenceColumnInSql;
this.referencedColumnValues = referencedColumnValues; this.referencedColumnValues = referencedColumnValues;
} }
@Override @Override
public boolean generatedOnInsert() { public EnumSet<EventType> getEventTypes() {
return generatedOnInsert; return eventTypes;
}
@Override
public boolean generatedOnUpdate() {
return generatedOnUpdate;
} }
@Override @Override
@ -672,17 +660,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.isNotNever(); return strategy != null && strategy.generatesSometimes();
} }
public boolean isVersionGeneratedByDatabase() { public boolean isVersionGeneratedByDatabase() {
final Generator strategy = generators[ versionPropertyIndex ]; final Generator strategy = generators[ versionPropertyIndex ];
return strategy != null && strategy.isNotNever() && strategy.generatedByDatabase(); return strategy != null && strategy.generatesSometimes() && strategy.generatedByDatabase();
} }
public boolean isVersionGeneratedInMemory() { public boolean isVersionGeneratedInMemory() {
final Generator strategy = generators[ versionPropertyIndex ]; final Generator strategy = generators[ versionPropertyIndex ];
return strategy != null && strategy.isNotNever() && !strategy.generatedByDatabase(); return strategy != null && strategy.generatesSometimes() && !strategy.generatedByDatabase();
} }
public int[] getNaturalIdentifierProperties() { public int[] getNaturalIdentifierProperties() {

View File

@ -22,8 +22,8 @@ import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.hibernate.annotations.GenerationTime.INSERT; import static org.hibernate.generator.EventType.INSERT;
import static org.hibernate.annotations.GenerationTime.INSERT_OR_UPDATE; import static org.hibernate.generator.EventType.UPDATE;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -66,9 +66,7 @@ public class CurrentTimestampAnnotationTests {
waitALittle(); waitALittle();
// lastly, make sure we can load it.. // lastly, make sure we can load it..
final AuditedEntity loaded = scope.fromTransaction( (session) -> { final AuditedEntity loaded = scope.fromTransaction( (session) -> session.get( AuditedEntity.class, 1 ) );
return session.get( AuditedEntity.class, 1 );
} );
assertThat( loaded ).isNotNull(); assertThat( loaded ).isNotNull();
assertThat( loaded.createdAt ).isEqualTo( merged.createdAt ); assertThat( loaded.createdAt ).isEqualTo( merged.createdAt );
@ -86,7 +84,7 @@ public class CurrentTimestampAnnotationTests {
@CurrentTimestamp(event = INSERT) @CurrentTimestamp(event = INSERT)
public Instant createdAt; public Instant createdAt;
@CurrentTimestamp(event = INSERT_OR_UPDATE) @CurrentTimestamp(event = {INSERT, UPDATE})
public Instant lastUpdatedAt; public Instant lastUpdatedAt;
//end::mapping-generated-CurrentTimestamp-ex1[] //end::mapping-generated-CurrentTimestamp-ex1[]

View File

@ -11,6 +11,7 @@ import java.lang.annotation.Inherited;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.util.EnumSet;
import java.util.UUID; import java.util.UUID;
import jakarta.persistence.Basic; import jakarta.persistence.Basic;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
@ -19,6 +20,7 @@ import jakarta.persistence.Table;
import org.hibernate.annotations.ValueGenerationType; import org.hibernate.annotations.ValueGenerationType;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.generator.EventType;
import org.hibernate.tuple.GenerationTiming; import org.hibernate.tuple.GenerationTiming;
import org.hibernate.generator.InMemoryGenerator; import org.hibernate.generator.InMemoryGenerator;
@ -84,20 +86,15 @@ public class GeneratedUuidTests {
//tag::mapping-generated-custom-ex3[] //tag::mapping-generated-custom-ex3[]
public static class UuidValueGeneration implements InMemoryGenerator { public static class UuidValueGeneration implements InMemoryGenerator {
private final GenerationTiming timing; private final EnumSet<EventType> eventTypes;
public UuidValueGeneration(GeneratedUuidValue annotation) { public UuidValueGeneration(GeneratedUuidValue annotation) {
timing = annotation.timing(); eventTypes = annotation.timing().getEquivalent().eventTypes();
} }
@Override @Override
public boolean generatedOnInsert() { public EnumSet<EventType> getEventTypes() {
return timing.includesInsert(); return eventTypes;
}
@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 GeneratedGeneration) { if ( generation instanceof GeneratedGeneration) {
final GeneratedGeneration valueGeneration = (GeneratedGeneration) generation; final GeneratedGeneration valueGeneration = (GeneratedGeneration) generation;
if ( valueGeneration.generatedOnInsert() ) { if ( valueGeneration.generatesOnInsert() ) {
return true; return true;
} }
} }
@ -189,7 +189,6 @@ public final class AuditMetadataGenerator extends AbstractMetadataGenerator {
} }
} }
@SuppressWarnings("unchecked")
private void addJoins( private void addJoins(
PersistentClass persistentClass, PersistentClass persistentClass,
CompositeMapperBuilder currentMapper, CompositeMapperBuilder currentMapper,