HHH-15800 reverse previous work to standardizing on GenerationTiming

...and go in exact opposite direction to migrate to GenerationTime
This commit is contained in:
Gavin 2022-12-03 13:56:48 +01:00 committed by Gavin King
parent 216fe0f615
commit 95aa852e15
14 changed files with 132 additions and 87 deletions

View File

@ -82,7 +82,7 @@ public class GeneratedTest {
private String middleName5;
@Generated(value = GenerationTime.ALWAYS)
@Generated
@Column(columnDefinition =
"AS CONCAT(" +
" COALESCE(firstName, ''), " +

View File

@ -20,7 +20,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* <ul>
* <li>{@code DynamicInsert}, to let the database fill in the value of
* a null entity attribute, or
* <li>{@code @Generated(timing=INSERT)}, to populate an entity attribute
* <li>{@code @Generated(event=INSERT)}, to populate an entity attribute
* with the defaulted value of a database column.
* </ul>
* If {@link Generated} is not used, a {@code default} value can state held

View File

@ -9,6 +9,7 @@ package org.hibernate.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import org.hibernate.Remove;
import org.hibernate.tuple.CurrentTimestampGeneration;
import org.hibernate.tuple.GenerationTiming;
@ -67,8 +68,19 @@ public @interface CurrentTimestamp {
* Determines when the timestamp is generated. But default, it is updated
* when any SQL {@code insert} or {@code update} statement is executed.
* If it should be generated just once, on the initial SQL {@code insert},
* explicitly specify {@link GenerationTiming#INSERT timing = INSERT}.
* explicitly specify {@link GenerationTime#INSERT time = INSERT}.
*/
GenerationTime event() default GenerationTime.INSERT_OR_UPDATE;
/**
* Determines when the timestamp is generated. But default, it is updated
* when any SQL {@code insert} or {@code update} statement is executed.
* If it should be generated just once, on the initial SQL {@code insert},
* explicitly specify {@link GenerationTiming#INSERT timing = INSERT}.
*
* @deprecated This was introduced in error
*/
@Deprecated(since = "6.2") @Remove
GenerationTiming timing() default GenerationTiming.ALWAYS;
/**

View File

@ -12,7 +12,6 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.hibernate.tuple.GeneratedValueGeneration;
import org.hibernate.tuple.GenerationTiming;
/**
* Specifies that the value of the annotated property is generated by the
@ -28,7 +27,7 @@ import org.hibernate.tuple.GenerationTiming;
* <ul>
* <li>a database table has a column value populated by a database trigger,
* <li>a mapped column has a default value defined in DDL, in which case
* {@code Generated(INSERT)} is used in conjunction with
* {@code @Generated(event=INSERT)} is used in conjunction with
* {@link ColumnDefault},
* <li>a {@linkplain #sql() SQL expression} is used to compute the value of
* a mapped column, or
@ -60,16 +59,16 @@ public @interface Generated {
* Specifies the events that cause the value to be generated by the
* database.
* <ul>
* <li>If {@link GenerationTiming#INSERT}, the generated value will be
* <li>If {@link GenerationTime#INSERT}, the generated value will be
* selected after each SQL {@code insert} statement is executed.
* <li>If {@link GenerationTiming#UPDATE}, the generated value will be
* <li>If {@link GenerationTime#UPDATE}, the generated value will be
* selected after each SQL {@code update} statement is executed.
* <li>If {@link GenerationTiming#ALWAYS}, the generated value will be
* selected after each SQL {@code insert} or {@code update}
* <li>If {@link GenerationTime#INSERT_OR_UPDATE}, the generated value
* will be selected after each SQL {@code insert} or {@code update}
* statement is executed.
* </ul>
*/
GenerationTiming timing() default GenerationTiming.ALWAYS;
GenerationTime event() default GenerationTime.INSERT_OR_UPDATE;
/**
* Specifies the events that cause the value to be generated by the
@ -83,7 +82,7 @@ public @interface Generated {
* selected after each SQL {@code insert} or {@code update}
* statement is executed.
* </ul>
* @deprecated use {@link #timing()}
* @deprecated use {@link #event()}
*/
@Deprecated(since = "6.2")
GenerationTime value() default GenerationTime.ALWAYS;

View File

@ -6,46 +6,80 @@
*/
package org.hibernate.annotations;
import org.hibernate.AssertionFailure;
import org.hibernate.Internal;
import org.hibernate.tuple.GenerationTiming;
/**
* Represents the timing of value generation that occurs in the database.
* Intended for use with the {@link Generated} annotation.
* Represents a class of events involving interaction with the database
* that causes generation of a new value. Intended for use with the
* {@link Generated} and {@link CurrentTimestamp} annotations.
*
* @author Emmanuel Bernard
*
* @see Generated
*
* @deprecated use {@link GenerationTiming}
* @see CurrentTimestamp
*/
@Deprecated(since = "6.2")
public enum GenerationTime {
/**
* Indicates the value is never generated.
* Indicates that a value is never generated.
*/
NEVER( GenerationTiming.NEVER ),
NEVER,
/**
* Indicates the value is generated on insert.
* Indicates that a new value is generated on insert.
*/
INSERT( GenerationTiming.INSERT ),
INSERT,
/**
* Indicates the value is generated on update.
* Indicates that a new value is generated on update.
*
* @since 6.2
*/
UPDATE( GenerationTiming.UPDATE ),
UPDATE,
/**
* Indicates the value is generated on insert and on update.
* Indicates that a new value is generated on insert and on update.
*
* @since 6.2
*/
ALWAYS( GenerationTiming.ALWAYS );
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;
private final GenerationTiming equivalent;
private GenerationTime(GenerationTiming equivalent) {
this.equivalent = equivalent;
/**
* @return {@code true} if a new value is generated when an insert is executed
*/
public boolean includesInsert() {
return getEquivalent().includesInsert();
}
/**
* @return {@code true} if a new value is generated when an update is executed
*/
public boolean includesUpdate() {
return getEquivalent().includesUpdate();
}
/**
* @return the equivalent instance of {@link GenerationTiming}
*/
@Internal
public GenerationTiming getEquivalent() {
return equivalent;
switch (this) {
case ALWAYS:
case INSERT_OR_UPDATE:
return GenerationTiming.ALWAYS;
case INSERT:
return GenerationTiming.INSERT;
case UPDATE:
return GenerationTiming.UPDATE;
case NEVER:
return GenerationTiming.NEVER;
default:
throw new AssertionFailure("unknown event");
}
}
}

View File

@ -11,7 +11,6 @@ import java.lang.annotation.Target;
import org.hibernate.Session;
import org.hibernate.tuple.AnnotationValueGeneration;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.ValueGenerator;
import org.hibernate.tuple.VmValueGeneration;
@ -49,7 +48,6 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Target({FIELD, METHOD})
@Deprecated(since = "6.0")
public @interface GeneratorType {
/**
* A class that implements {@link ValueGenerator}, which will be called to
* {@linkplain ValueGenerator#generateValue(Session, Object) generate values}
@ -59,20 +57,6 @@ public @interface GeneratorType {
*/
Class<? extends ValueGenerator<?>> type();
/**
* Specifies the events that cause the value to be generated by the
* database.
* <ul>
* <li>If {@link GenerationTime#INSERT}, the value will be generated before
* each SQL {@code insert} statement is executed.
* <li>If {@link GenerationTime#UPDATE}, the value will be generated before
* each SQL {@code update} statement is executed.
* <li>If {@link GenerationTime#ALWAYS}, the value will be generated before
* each SQL {@code insert} or {@code update} statement is executed.
* </ul>
*/
GenerationTiming timing() default GenerationTiming.ALWAYS;
/**
* Specifies when values should be generated:
* <ul>
@ -83,8 +67,6 @@ public @interface GeneratorType {
* <li>If {@link GenerationTime#ALWAYS}, the value will be generated before
* each SQL {@code insert} or {@code update} statement is executed.
* </ul>
* @deprecated use {@link #timing()}
*/
@Deprecated(since = "6.2")
GenerationTime when() default GenerationTime.ALWAYS;
}

View File

@ -32,13 +32,13 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* A custom SQL insert statement might assign a value to a mapped column as it
* is written. In this case, the corresponding property of the entity remains
* unassigned after the insert is executed unless
* {@link Generated @Generated(timing=INSERT)} is specified, forcing Hibernate
* {@link Generated @Generated(event=INSERT)} is specified, forcing Hibernate
* to reread the state of the entity after each insert.
* <p>
* Similarly, a custom insert statement might transform a mapped column value
* as it is written. In this case, the state of the entity held in memory
* loses synchronization with the database after the insert is executed unless
* {@link Generated @Generated(value=INSERT, writable=true)} is specified,
* {@link Generated @Generated(event=INSERT, writable=true)} is specified,
* again forcing Hibernate to reread the state of the entity after each insert.
*
* @author Laszlo Benke

View File

@ -41,8 +41,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* Similarly, a custom update statement might transform a mapped column value
* as it is written. In this case, the state of the entity held in memory
* loses synchronization with the database after the update is executed unless
* {@link Generated @Generated(value=ALWAYS, writable=true)} is specified,
* again forcing Hibernate to reread the state of the entity after each update.
* {@link Generated @Generated(writable=true)} is specified, again forcing
* Hibernate to reread the state of the entity after each update.
*
* @author Laszlo Benke
*/

View File

@ -2536,9 +2536,9 @@ public class ModelBinder {
// NOTE : Property#is refers to whether a property is lazy via bytecode enhancement (not proxies)
property.setLazy( singularAttributeSource.isBytecodeLazy() );
final GenerationTiming generationTiming = singularAttributeSource.getGenerationTiming();
if ( generationTiming != null ) {
if ( (generationTiming == GenerationTiming.INSERT || generationTiming == GenerationTiming.UPDATE)
final GenerationTiming timing = singularAttributeSource.getGenerationTiming();
if ( timing != null ) {
if ( (timing == GenerationTiming.INSERT || timing == GenerationTiming.UPDATE)
&& property.getValue() instanceof SimpleValue
&& ((SimpleValue) property.getValue()).isVersion() ) {
// this is enforced by DTD, but just make sure
@ -2547,22 +2547,22 @@ public class ModelBinder {
mappingDocument.getOrigin()
);
}
if ( generationTiming.isNotNever() ) {
property.setValueGeneratorCreator(context -> new GeneratedValueGeneration( generationTiming ) );
if ( timing != GenerationTiming.NEVER ) {
property.setValueGeneratorCreator( context -> new GeneratedValueGeneration( timing.getEquivalent() ) );
// generated properties can *never* be insertable...
if ( property.isInsertable() && generationTiming.includesInsert() ) {
if ( property.isInsertable() && timing.includesInsert() ) {
log.debugf(
"Property [%s] specified %s generation, setting insertable to false : %s",
propertySource.getName(),
generationTiming.name(),
timing.name(),
mappingDocument.getOrigin()
);
property.setInsertable( false );
}
// properties generated on update can never be updatable...
if ( property.isUpdateable() && generationTiming.includesUpdate() ) {
if ( property.isUpdateable() && timing.includesUpdate() ) {
log.debugf(
"Property [%s] specified ALWAYS generation, setting updateable to false : %s",
propertySource.getName(),

View File

@ -10,6 +10,7 @@ import org.hibernate.AssertionFailure;
import org.hibernate.Internal;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.CurrentTimestamp;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.annotations.SourceType;
import org.hibernate.annotations.UpdateTimestamp;
import org.hibernate.dialect.Dialect;
@ -17,8 +18,8 @@ import org.hibernate.internal.util.ReflectHelper;
import java.lang.reflect.Member;
import static org.hibernate.tuple.GenerationTiming.ALWAYS;
import static org.hibernate.tuple.GenerationTiming.INSERT;
import static org.hibernate.annotations.GenerationTime.INSERT;
import static org.hibernate.annotations.GenerationTime.INSERT_OR_UPDATE;
/**
* Value generation strategy which produces a timestamp using the database
@ -39,12 +40,12 @@ import static org.hibernate.tuple.GenerationTiming.INSERT;
*/
@Internal
public class CurrentTimestampGeneration implements ValueGeneration {
private final GenerationTiming timing;
private final GenerationTime timing;
private final ValueGenerator<?> generator;
public CurrentTimestampGeneration(CurrentTimestamp annotation, Member member, GeneratorCreationContext context) {
generator = getGenerator( annotation.source(), member );
timing = annotation.timing();
timing = annotation.event() == INSERT_OR_UPDATE ? annotation.timing().getEquivalent() : annotation.event();
}
public CurrentTimestampGeneration(CreationTimestamp annotation, Member member, GeneratorCreationContext context) {
@ -54,7 +55,7 @@ public class CurrentTimestampGeneration implements ValueGeneration {
public CurrentTimestampGeneration(UpdateTimestamp annotation, Member member, GeneratorCreationContext context) {
generator = getGenerator( annotation.source(), member );
timing = ALWAYS;
timing = INSERT_OR_UPDATE;
}
private static ValueGenerator<?> getGenerator(SourceType source, Member member) {
@ -71,7 +72,7 @@ public class CurrentTimestampGeneration implements ValueGeneration {
@Override
public GenerationTiming getGenerationTiming() {
return timing;
return timing.getEquivalent();
}
@Override

View File

@ -7,8 +7,10 @@
package org.hibernate.tuple;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.dialect.Dialect;
import static org.hibernate.annotations.GenerationTime.INSERT_OR_UPDATE;
import static org.hibernate.internal.util.StringHelper.isEmpty;
/**
@ -19,21 +21,19 @@ import static org.hibernate.internal.util.StringHelper.isEmpty;
*/
public class GeneratedValueGeneration implements InDatabaseGenerator {
private GenerationTiming timing;
private GenerationTime timing;
private boolean writable;
private String[] sql;
public GeneratedValueGeneration() {
}
public GeneratedValueGeneration(GenerationTiming timing) {
this.timing = timing;
public GeneratedValueGeneration(GenerationTime event) {
this.timing = event;
}
public GeneratedValueGeneration(Generated annotation) {
timing = annotation.timing().isAlways()
? annotation.value().getEquivalent()
: annotation.timing();
timing = annotation.event() == INSERT_OR_UPDATE ? annotation.value() : annotation.event();
sql = isEmpty( annotation.sql() ) ? null : new String[] { annotation.sql() };
writable = annotation.writable() || sql != null;
}

View File

@ -6,6 +6,9 @@
*/
package org.hibernate.tuple;
import org.hibernate.AssertionFailure;
import org.hibernate.annotations.GenerationTime;
/**
* Represents the timing of {@link ValueGeneration value generation} that occurs
* in the Java program, or in the database.
@ -88,23 +91,19 @@ public enum GenerationTiming {
@Override
public boolean includes(GenerationTiming timing) {
return timing.isNotNever();
return timing != NEVER;
}
};
/**
* Does value generation happen for SQL {@code INSERT} statements?
* Does value generation happen for SQL {@code insert} statements?
*/
public abstract boolean includesInsert();
/**
* Does value generation happen for SQL {@code UPDATE} statements?
* Does value generation happen for SQL {@code update} statements?
*/
public abstract boolean includesUpdate();
public boolean isNotNever() {
return this != NEVER;
}
public boolean isAlways() {
return this == ALWAYS;
}
@ -125,4 +124,22 @@ public enum GenerationTiming {
return NEVER;
}
}
/**
* @return the equivalent instance of {@link GenerationTime}
*/
public GenerationTime getEquivalent() {
switch (this) {
case ALWAYS:
return GenerationTime.INSERT_OR_UPDATE;
case INSERT:
return GenerationTime.INSERT;
case UPDATE:
return GenerationTime.UPDATE;
case NEVER:
return GenerationTime.NEVER;
default:
throw new AssertionFailure("unknown timing");
}
}
}

View File

@ -11,6 +11,7 @@ import java.lang.reflect.Constructor;
import org.hibernate.HibernateException;
import org.hibernate.Internal;
import org.hibernate.Session;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.annotations.GeneratorType;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
@ -28,7 +29,7 @@ import static org.hibernate.internal.util.ReflectHelper.getDefaultConstructor;
@Deprecated(since = "6.2")
public class VmValueGeneration implements InMemoryGenerator {
private final GenerationTiming generationTiming;
private final GenerationTime timing;
private final ValueGenerator<?> generator;
public VmValueGeneration(GeneratorType annotation) {
@ -39,9 +40,7 @@ public class VmValueGeneration implements InMemoryGenerator {
catch (Exception e) {
throw new HibernateException( "Couldn't instantiate value generator", e );
}
generationTiming = annotation.timing().isAlways()
? annotation.when().getEquivalent()
: annotation.timing();
timing = annotation.when();
}
/**
@ -49,7 +48,7 @@ public class VmValueGeneration implements InMemoryGenerator {
*/
@Override
public boolean generatedOnInsert() {
return generationTiming.includesInsert();
return timing.includesInsert();
}
/**
@ -57,7 +56,7 @@ public class VmValueGeneration implements InMemoryGenerator {
*/
@Override
public boolean generatedOnUpdate() {
return generationTiming.includesUpdate();
return timing.includesUpdate();
}

View File

@ -13,7 +13,6 @@ import jakarta.persistence.Table;
import org.hibernate.HibernateError;
import org.hibernate.annotations.CurrentTimestamp;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
@ -23,6 +22,8 @@ import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hibernate.annotations.GenerationTime.INSERT;
import static org.hibernate.annotations.GenerationTime.INSERT_OR_UPDATE;
/**
* @author Steve Ebersole
@ -82,10 +83,10 @@ public class CurrentTimestampAnnotationTests {
public String name;
//tag::mapping-generated-CurrentTimestamp-ex1[]
@CurrentTimestamp( timing = GenerationTiming.INSERT )
@CurrentTimestamp(event = INSERT)
public Instant createdAt;
@CurrentTimestamp( timing = GenerationTiming.ALWAYS )
@CurrentTimestamp(event = INSERT_OR_UPDATE)
public Instant lastUpdatedAt;
//end::mapping-generated-CurrentTimestamp-ex1[]