HHH-18186 - Remove @GeneratorType

HHH-18188 - Remove GenerationTime and its uses
This commit is contained in:
Steve Ebersole 2024-07-23 12:42:36 -05:00
parent f63e7cb1ac
commit 2b6f4b5ff9
50 changed files with 558 additions and 1351 deletions

View File

@ -1,277 +0,0 @@
[[generated-values-guide]]
= Generated Values
:toc:
This guide discusses the Hibernate feature of generating non-identifier values. Jakarta Persistence allows for the generation of
identifier values. Beyond generation of identifier values, Hibernate allows for the generation of other types of
values. At a high level Hibernate supports both in-database and in-memory generation. In-database
refers to generation strategy where the value is actually generated in the database as part of an INSERT/UPDATE
execution, and must be re-read by SELECT afterwards to access the generated value. On the other hand, in-memory refers
to strategies where the value is generated in memory and then passed along to the database via the INSERT/UPDATE
statement.
== Legacy support (in-database generation)
Historically applications would have to manually refresh the state of any entities that included such generated values
to account for these generated values. Starting in version 3.2, however, Hibernate began allowing the application to
mark attributes as generated, which allows the application to delegate this responsibility to Hibernate. When
Hibernate issues an SQL INSERT or UPDATE for an entity that has defined in-database value generation, it immediately
issues a select afterwards to retrieve the generated values.
To mark an attribute as generated, applications used `@Generated`:
[[legacy-syntax-example]]
.Legacy Syntax
====
[source, JAVA]
----
@Entity
public class Document {
...
@Generated
private Date created;
@Generated(event={INSERT,UPDATE})
private Date lastModified;
}
----
====
The assumption above is that the values of the 2 attributes are generated during the execution of the SQL INSERT/UPDATE
statements. `@Generated` tells Hibernate to read those values back after the INSERT/UPDATE execution.
== @ValueGenerationType meta-annotation
Version 4.3 expands on that support by adding a new approach to declaring generated attributes and even custom
generators via the `@ValueGenerationType` meta-annotation, which is used to annotate other annotations that describe
generated attributes. For discussion purposes, I here copy all the contracts used in value generation:
[source, JAVA]
----
@Target( value = ElementType.ANNOTATION_TYPE )
@Retention( RetentionPolicy.RUNTIME )
public @interface ValueGenerationType {
/**
* The type of value generation associated with the annotated value generator
* annotation type. The referenced generation type must be parameterized with
* the type of the given generator annotation.
*
* @return the value generation type
*/
Class<? extends AnnotationValueGeneration<?>> generatedBy();
}
public interface AnnotationValueGeneration<A extends Annotation>
extends ValueGeneration {
/**
* Initializes this generation strategy for the given annotation instance.
*
* @param annotation an instance of the strategy's annotation type. Typically
* implementations will retrieve the annotation's attribute values and store
* them in fields.
* @param propertyType the type of the property annotated with the generator
* annotation. Implementations may use the type to determine the right
* {@link ValueGenerator} to be applied.
*
* @throws HibernateException in case an error occurred during initialization,
* e.g. if an implementation can't create a value for the given property type.
*/
void initialize(A annotation, Class<?> propertyType);
}
public interface ValueGeneration {
/**
* When is this value generated : NEVER, INSERT, ALWAYS (INSERT+UPDATE)
*
* @return When the value is generated.
*/
public GenerationTiming getGenerationTiming();
/**
* Obtain the in-VM value generator.
* <p>
* May return {@code null}. In fact for values that are generated
* "in the database" via execution of the INSERT/UPDATE statement, the
* expectation is that {@code null} be returned here
*
* @return The strategy for performing in-VM value generation
*/
public ValueGenerator<?> getValueGenerator();
/**
* For values which are generated in the database (i.e,
* {@link #getValueGenerator()} == {@code null}), should the column
* be referenced in the INSERT / UPDATE SQL?
* <p>
* This will be false most often to have a DDL-defined DEFAULT value
* be applied on INSERT
*
* @return {@code true} indicates the column should be included in the SQL.
*/
public boolean referenceColumnInSql();
/**
* For values which are generated in the database (i.e.,
* {@link #getValueGenerator} == {@code null}), if the column will be
* referenced in the SQL (i.e.,
* {@link #referenceColumnInSql()} == {@code true}), what value should be
* used in the SQL as the column value.
* <p>
* Generally this will be a function call or a marker (DEFAULTS).
* <p>
* NOTE : for in-VM generation, this will not be called and the column
* value will implicitly be a JDBC parameter ('?')
*
* @return The column value to be used in the SQL.
*/
public String getDatabaseGeneratedReferencedColumnValue();
}
----
Ultimately, `ValueGeneration` is the thing seen by the Hibernate internals. But `AnnotationValueGeneration` gives
the opportunity to configure the `ValueGeneration` via the annotation that named it. As mentioned, these contracts
cater to both in-database and in-memory scenarios. Below we'll look at some specific examples of usage in both
in-database and in-memory scenarios as a means of illustration.
== In-database Generation
`@Generated` has been retrofitted to use `@ValueGenerationType`. But `@ValueGenerationType` exposes more features
than what `@Generated` currently supports. To leverage some of those features, you'd simply wire up a new
generator annotation. For example, lets say we want the timestamps to be generated by calls to the standard
ANSI SQL function `current_timestamp` (rather than triggers or DEFAULT values):
[[in-database-example]]
.In-database Custom Annotation Example
====
[source, JAVA]
----
@ValueGenerationType(generatedBy = FunctionCreationValueGeneration.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface FunctionCreationTimestamp {
}
public class FunctionCreationValueGeneration
implements AnnotationValueGeneration<FunctionCreationTimestamp> {
@Override
public void initialize(FunctionCreationTimestamp annotation, Class<?> propertyType) {
}
public GenerationTiming getGenerationTiming() {
// its creation...
return GenerationTiming.INSERT;
}
public ValueGenerator<?> getValueGenerator() {
// no in-memory generation
}
public boolean referenceColumnInSql() {
return true;
}
public String getDatabaseGeneratedReferencedColumnValue() {
return "current_timestamp";
}
}
@Entity
public class ErrorReport {
...
@FunctionCreationTimestamp
private Date created;
}
----
====
== In-memory Generation
Going back to the earlier <<legacy-syntax-example,Document example>> we can use some of the new pre-defined
annotations to make the code a little cleaner and easier to understand:
[[in-memory-example1]]
.In-memory Generation Example
====
[source, JAVA]
----
@Entity
public class Document {
...
@CreationTimestamp
private Date created;
@UpdateTimestamp
private Date lastModified;
}
----
====
Both `@CreationTimestamp` and `@UpdateTimestamp` perform in-memory generation of the timestamp (using the VM time).
Let's also add an annotation for tracking the username who last modified the entity:
[[in-memory-example2]]
.Another In-memory Generation Example
====
[source, JAVA]
----
@ValueGenerationType(generatedBy = ModifiedByValueGeneration.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface ModifiedBy {
}
public class ModifiedByValueGeneration
implements AnnotationValueGeneration<ModifiedBy> {
private final ValueGenerator<String> generator = new ValueGenerator<String>() {
public String generateValue(Session session, Object owner) {
// lets use a custom Service in the Hibernate ServiceRegistry to keep this
// look up contextual and portable..
UserService userService = ( (SessionImplementor) session ).getFactory()
.getServiceRegistry()
.getService( UserService.class );
return userService.getCurrentUserName();
}
}
@Override
public void initialize(ModifiedBy annotation, Class<?> propertyType) {
}
public GenerationTiming getGenerationTiming() {
return GenerationTiming.ALWAYS;
}
public ValueGenerator<?> getValueGenerator() {
return generator;
}
public boolean referenceColumnInSql() {
// n/a
return false;
}
public String getDatabaseGeneratedReferencedColumnValue() {
// n/a
return null;
}
}
@Entity
public class Document {
...
@CreationTimestamp
private Date created;
@UpdateTimestamp
private Date lastModified;
@ModifiedBy
private String lastModifiedBy;
}
----
====

View File

@ -2482,7 +2482,6 @@ Hibernate supports multiple ways to mark an attribute as generated:
* `@CreationTimestamp` - <<mapping-generated-CreationTimestamp>>
* `@UpdateTimestamp` - <<mapping-generated-UpdateTimestamp>>
* `@Generated` - <<mapping-generated-Generated>>
* `@GeneratorType` - is deprecated and not covered here
* Using a custom generation strategy - <<mapping-generated-custom>>
@ -2565,7 +2564,7 @@ include::{example-dir-basic-mapping}/generated/GeneratedTest.java[tags=mapping-g
[[mapping-generated-custom]]
===== Custom generation strategy
Hibernate also supports value generation via a pluggable API using `@ValueGenerationType` and `AnnotationValueGeneration`
Hibernate also supports value generation via a pluggable API using `@ValueGenerationType` and `AnnotationBasedGenerator`
allowing users to define any generation strategy they wish.
Let's look at an example of generating UUID values. First the attribute mapping
@ -2604,7 +2603,7 @@ include::{example-dir-generated}/temporals/GeneratedUuidTests.java[tags=mapping-
====
See https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/ValueGenerationType.html[`@ValueGenerationType`]
and https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/tuple/AnnotationValueGeneration.html[`AnnotationValueGeneration`]
and https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/generator/AnnotationValueGeneration.html[`AnnotationBasedGenerator`]
for details of each contract

View File

@ -9,10 +9,8 @@ package org.hibernate.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import org.hibernate.Remove;
import org.hibernate.generator.EventType;
import org.hibernate.generator.internal.CurrentTimestampGeneration;
import org.hibernate.tuple.GenerationTiming;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
@ -23,7 +21,7 @@ import static org.hibernate.generator.EventType.UPDATE;
/**
* Specifies that the annotated field of property is a generated timestamp,
* and also specifies the {@linkplain #timing() timing} of the timestamp
* and also specifies the {@linkplain #event() timing} of the timestamp
* generation, and whether it is generated in Java or by the database:
* <ul>
* <li>{@link SourceType#VM source = VM} indicates that the virtual machine
@ -76,17 +74,6 @@ public @interface CurrentTimestamp {
*/
EventType[] event() default {INSERT, 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;
/**
* Specifies how the timestamp is generated. By default, it is generated
* by the database, and fetched using a subsequent {@code select} statement.

View File

@ -74,24 +74,6 @@ public @interface Generated {
*/
EventType[] event() default INSERT;
/**
* Specifies the events that cause the value to be generated by the
* database.
* <ul>
* <li>If {@link GenerationTime#INSERT}, the generated value will be
* selected after each SQL {@code insert} statement is executed.
* <li>If {@link GenerationTime#UPDATE}, the generated value will be
* selected after each SQL {@code update} statement is executed.
* <li>If {@link GenerationTime#ALWAYS}, the generated value will be
* selected after each SQL {@code insert} or {@code update}
* statement is executed.
* </ul>
*
* @deprecated use {@link #event()}
*/
@Deprecated(since = "6.2")
GenerationTime value() default GenerationTime.INSERT;
/**
* A SQL expression used to generate the value of the column mapped by
* the annotated property. The expression is included in generated SQL

View File

@ -1,86 +0,0 @@
/*
* 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.annotations;
import java.util.EnumSet;
import org.hibernate.AssertionFailure;
import org.hibernate.Internal;
import org.hibernate.generator.EventType;
import org.hibernate.generator.EventTypeSets;
import org.hibernate.tuple.GenerationTiming;
/**
* 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
* @see CurrentTimestamp
*
* @deprecated use {@link EventType} and {@link EventTypeSets} instead
*/
@Deprecated(since = "6.2")
public enum GenerationTime {
/**
* Indicates that a value is never generated.
*/
NEVER,
/**
* Indicates that a new value is generated on insert.
*/
INSERT,
/**
* Indicates that a new value is generated on update.
*
* @since 6.2
*/
UPDATE,
/**
* Indicates that a new value is generated on insert and on update.
*/
ALWAYS;
public EnumSet<EventType> eventTypes() {
switch (this) {
case NEVER:
return EventTypeSets.NONE;
case ALWAYS:
return EventTypeSets.ALL;
case INSERT:
return EventTypeSets.INSERT_ONLY;
case UPDATE:
return EventTypeSets.UPDATE_ONLY;
default:
throw new AssertionFailure("unknown event");
}
}
/**
* @return the equivalent instance of {@link GenerationTiming}
*
* @deprecated Needed for backwards compatibility until the deprecated, legacy
* generation stuff can be removed
*/
@Internal @Deprecated(forRemoval = true)
public GenerationTiming getEquivalent() {
switch (this) {
case ALWAYS:
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

@ -1,72 +0,0 @@
/*
* 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.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import org.hibernate.Session;
import org.hibernate.tuple.AnnotationValueGeneration;
import org.hibernate.tuple.ValueGenerator;
import org.hibernate.tuple.VmValueGeneration;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Marks a field or property of an entity as automatically generated by
* code written in Java, before any SQL statement to {@code insert} or
* {@code update} the entity is executed, specifying an implementation
* of {@link ValueGenerator} used for generating its values.
* <p>
* It is the responsibility of the client to ensure that a specified
* {@linkplain #type generator type} produces values which are assignable
* to the annotated property.
* <p>
* This annotation is only useful for values generated in the Java code,
* and it is not used for generating the values of entity identifiers:
* <ul>
* <li>For identifier generators, use {@link GenericGenerator} or
* {@link IdGeneratorType}.
* <li>If the value of a field or property is generated by the database
* when an {@code insert} or {@code update} statement is executed,
* use the {@link Generated} annotation.
* </ul>
*
* @author Gunnar Morling
*
* @deprecated {@link ValueGenerationType} and {@link AnnotationValueGeneration}
* now provide a much more powerful and typesafe alternative
*/
@ValueGenerationType( generatedBy = VmValueGeneration.class )
@Retention(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}
* of the annotated field or property.
*
* @return the value generator type
*/
Class<? extends ValueGenerator<?>> type();
/**
* Specifies when values should be generated:
* <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>
*/
GenerationTime when() default GenerationTime.ALWAYS;
}

View File

@ -59,7 +59,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* which is responsible for generating values. It must be either:
* <ul>
* <li>a {@link BeforeExecutionGenerator}, for values that are generated in
* Java code, using a {@link org.hibernate.tuple.ValueGenerator}, or
* Java code, or
* <li>an {@link OnExecutionGenerator}, for values which are generated by
* the database.
* </ul>

View File

@ -0,0 +1,81 @@
/*
* 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.boot.jaxb.mapping;
import java.util.EnumSet;
import java.util.Locale;
import org.hibernate.generator.EventType;
/**
* Represents the {@linkplain EventType timing} of {@link org.hibernate.generator.Generator value generation}
* in XML mappings. That is, whether the value is generated on{@linkplain EventType#INSERT INSERT},
* {@linkplain EventType#UPDATE UPDATE} or both.
*
* @author Steve Ebersole
*/
public enum GenerationTiming {
/**
* Value generation that never occurs.
*/
NEVER,
/**
* Value generation that occurs when a row is inserted in the database.
*/
INSERT,
/**
* Value generation that occurs when a row is updated in the database.
*/
UPDATE,
/**
* Value generation that occurs when a row is inserted or updated in the database.
*/
ALWAYS;
/**
* Does value generation happen for SQL {@code insert} statements?
*/
public boolean includesInsert() {
return this == INSERT || this == ALWAYS;
}
/**
* Does value generation happen for SQL {@code update} statements?
*/
public boolean includesUpdate() {
return this == UPDATE || this == ALWAYS;
}
public boolean includes(GenerationTiming timing) {
return switch ( this ) {
case NEVER -> timing == NEVER;
case INSERT -> timing.includesInsert();
case UPDATE -> timing.includesUpdate();
case ALWAYS -> true;
};
}
public static GenerationTiming parseFromName(String name) {
return switch ( name.toLowerCase( Locale.ROOT ) ) {
case "insert" -> INSERT;
case "update" -> UPDATE;
case "always" -> ALWAYS;
default -> NEVER;
};
}
/**
* Return the equivalent set of {@linkplain EventType event types}
*/
public EnumSet<EventType> getEventTypes() {
return switch ( this ) {
case ALWAYS -> EnumSet.allOf( EventType.class );
case INSERT -> EnumSet.of( EventType.INSERT );
case UPDATE -> EnumSet.of( EventType.UPDATE );
case NEVER -> null;
};
}
}

View File

@ -6,7 +6,7 @@
*/
package org.hibernate.boot.jaxb.mapping.internal;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.boot.jaxb.mapping.GenerationTiming ;
/**
* JAXB marshalling for {@link GenerationTiming}

View File

@ -2485,7 +2485,7 @@ public class ModelBinder {
);
}
if ( timing != GenerationTiming.NEVER ) {
property.setValueGeneratorCreator(context -> new GeneratedGeneration( timing.getEquivalent() ) );
property.setValueGeneratorCreator(context -> new GeneratedGeneration( timing.getEventTypes() ) );
// generated properties can *never* be insertable...
if ( property.isInsertable() && timing.includesInsert() ) {

View File

@ -294,10 +294,6 @@ public interface HibernateAnnotations {
GeneratedColumn.class,
GeneratedColumnAnnotation.class
);
OrmAnnotationDescriptor<GeneratorType,GeneratorTypeAnnotation> GENERATOR_TYPE = new OrmAnnotationDescriptor<>(
GeneratorType.class,
GeneratorTypeAnnotation.class
);
OrmAnnotationDescriptor<GenericGenerators,GenericGeneratorsAnnotation> GENERIC_GENERATORS = new OrmAnnotationDescriptor<>(
GenericGenerators.class,
GenericGeneratorsAnnotation.class

View File

@ -15,20 +15,20 @@ import org.hibernate.models.spi.SourceModelBuildingContext;
import org.jboss.jandex.AnnotationInstance;
import static org.hibernate.boot.models.internal.OrmAnnotationHelper.extractJandexValue;
import static org.hibernate.generator.EventType.INSERT;
import static org.hibernate.generator.EventType.UPDATE;
@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" })
@jakarta.annotation.Generated("org.hibernate.orm.build.annotations.ClassGeneratorProcessor")
public class CurrentTimestampAnnotation implements CurrentTimestamp {
private org.hibernate.generator.EventType[] event;
private org.hibernate.tuple.GenerationTiming timing;
private org.hibernate.annotations.SourceType source;
/**
* Used in creating dynamic annotation instances (e.g. from XML)
*/
public CurrentTimestampAnnotation(SourceModelBuildingContext modelContext) {
this.event = new org.hibernate.generator.EventType[0];
this.timing = org.hibernate.tuple.GenerationTiming.ALWAYS;
this.event = new org.hibernate.generator.EventType[] {INSERT, UPDATE};
this.source = org.hibernate.annotations.SourceType.DB;
}
@ -37,7 +37,6 @@ public class CurrentTimestampAnnotation implements CurrentTimestamp {
*/
public CurrentTimestampAnnotation(CurrentTimestamp annotation, SourceModelBuildingContext modelContext) {
this.event = annotation.event();
this.timing = annotation.timing();
this.source = annotation.source();
}
@ -46,7 +45,6 @@ public class CurrentTimestampAnnotation implements CurrentTimestamp {
*/
public CurrentTimestampAnnotation(AnnotationInstance annotation, SourceModelBuildingContext modelContext) {
this.event = extractJandexValue( annotation, HibernateAnnotations.CURRENT_TIMESTAMP, "event", modelContext );
this.timing = extractJandexValue( annotation, HibernateAnnotations.CURRENT_TIMESTAMP, "timing", modelContext );
this.source = extractJandexValue( annotation, HibernateAnnotations.CURRENT_TIMESTAMP, "source", modelContext );
}
@ -64,17 +62,6 @@ public class CurrentTimestampAnnotation implements CurrentTimestamp {
this.event = value;
}
@Override
public org.hibernate.tuple.GenerationTiming timing() {
return timing;
}
public void timing(org.hibernate.tuple.GenerationTiming value) {
this.timing = value;
}
@Override
public org.hibernate.annotations.SourceType source() {
return source;

View File

@ -10,6 +10,7 @@ import java.lang.annotation.Annotation;
import org.hibernate.annotations.Generated;
import org.hibernate.boot.models.HibernateAnnotations;
import org.hibernate.generator.EventType;
import org.hibernate.models.spi.SourceModelBuildingContext;
import org.jboss.jandex.AnnotationInstance;
@ -20,7 +21,6 @@ import static org.hibernate.boot.models.internal.OrmAnnotationHelper.extractJand
@jakarta.annotation.Generated("org.hibernate.orm.build.annotations.ClassGeneratorProcessor")
public class GeneratedAnnotation implements Generated {
private org.hibernate.generator.EventType[] event;
private org.hibernate.annotations.GenerationTime value;
private String sql;
private boolean writable;
@ -28,8 +28,7 @@ public class GeneratedAnnotation implements Generated {
* Used in creating dynamic annotation instances (e.g. from XML)
*/
public GeneratedAnnotation(SourceModelBuildingContext modelContext) {
this.event = new org.hibernate.generator.EventType[0];
this.value = org.hibernate.annotations.GenerationTime.INSERT;
this.event = new org.hibernate.generator.EventType[] { EventType.INSERT };
this.sql = "";
this.writable = false;
}
@ -39,7 +38,6 @@ public class GeneratedAnnotation implements Generated {
*/
public GeneratedAnnotation(Generated annotation, SourceModelBuildingContext modelContext) {
this.event = annotation.event();
this.value = annotation.value();
this.sql = annotation.sql();
this.writable = annotation.writable();
}
@ -49,7 +47,6 @@ public class GeneratedAnnotation implements Generated {
*/
public GeneratedAnnotation(AnnotationInstance annotation, SourceModelBuildingContext modelContext) {
this.event = extractJandexValue( annotation, HibernateAnnotations.GENERATED, "event", modelContext );
this.value = extractJandexValue( annotation, HibernateAnnotations.GENERATED, "value", modelContext );
this.sql = extractJandexValue( annotation, HibernateAnnotations.GENERATED, "sql", modelContext );
this.writable = extractJandexValue( annotation, HibernateAnnotations.GENERATED, "writable", modelContext );
}
@ -69,16 +66,6 @@ public class GeneratedAnnotation implements Generated {
}
@Override
public org.hibernate.annotations.GenerationTime value() {
return value;
}
public void value(org.hibernate.annotations.GenerationTime value) {
this.value = value;
}
@Override
public String sql() {
return sql;

View File

@ -1,73 +0,0 @@
/*
* 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.boot.models.annotations.internal;
import java.lang.annotation.Annotation;
import org.hibernate.annotations.GeneratorType;
import org.hibernate.boot.models.HibernateAnnotations;
import org.hibernate.models.spi.SourceModelBuildingContext;
import org.jboss.jandex.AnnotationInstance;
import static org.hibernate.boot.models.internal.OrmAnnotationHelper.extractJandexValue;
@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" })
@jakarta.annotation.Generated("org.hibernate.orm.build.annotations.ClassGeneratorProcessor")
public class GeneratorTypeAnnotation implements GeneratorType {
private java.lang.Class<? extends org.hibernate.tuple.ValueGenerator<?>> type;
private org.hibernate.annotations.GenerationTime when;
/**
* Used in creating dynamic annotation instances (e.g. from XML)
*/
public GeneratorTypeAnnotation(SourceModelBuildingContext modelContext) {
this.when = org.hibernate.annotations.GenerationTime.ALWAYS;
}
/**
* Used in creating annotation instances from JDK variant
*/
public GeneratorTypeAnnotation(GeneratorType annotation, SourceModelBuildingContext modelContext) {
this.type = annotation.type();
this.when = annotation.when();
}
/**
* Used in creating annotation instances from Jandex variant
*/
public GeneratorTypeAnnotation(AnnotationInstance annotation, SourceModelBuildingContext modelContext) {
this.type = extractJandexValue( annotation, HibernateAnnotations.GENERATOR_TYPE, "type", modelContext );
this.when = extractJandexValue( annotation, HibernateAnnotations.GENERATOR_TYPE, "when", modelContext );
}
@Override
public Class<? extends Annotation> annotationType() {
return GeneratorType.class;
}
@Override
public java.lang.Class<? extends org.hibernate.tuple.ValueGenerator<?>> type() {
return type;
}
public void type(java.lang.Class<? extends org.hibernate.tuple.ValueGenerator<?>> value) {
this.type = value;
}
@Override
public org.hibernate.annotations.GenerationTime when() {
return when;
}
public void when(org.hibernate.annotations.GenerationTime value) {
this.when = value;
}
}

View File

@ -14,9 +14,6 @@ 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
*

View File

@ -6,25 +6,6 @@
*/
package org.hibernate.generator.internal;
import org.hibernate.AssertionFailure;
import org.hibernate.SessionFactory;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.CurrentTimestamp;
import org.hibernate.annotations.SourceType;
import org.hibernate.annotations.UpdateTimestamp;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.generator.EventType;
import org.hibernate.generator.OnExecutionGenerator;
import org.hibernate.generator.BeforeExecutionGenerator;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.generator.GeneratorCreationContext;
import org.hibernate.mapping.BasicValue;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.type.descriptor.java.ClockHelper;
import java.lang.reflect.Member;
import java.sql.Time;
import java.sql.Timestamp;
@ -47,6 +28,24 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
import org.hibernate.AssertionFailure;
import org.hibernate.SessionFactory;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.CurrentTimestamp;
import org.hibernate.annotations.SourceType;
import org.hibernate.annotations.UpdateTimestamp;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.generator.BeforeExecutionGenerator;
import org.hibernate.generator.EventType;
import org.hibernate.generator.GeneratorCreationContext;
import org.hibernate.generator.OnExecutionGenerator;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.mapping.BasicValue;
import org.hibernate.type.descriptor.java.ClockHelper;
import org.checkerframework.checker.nullness.qual.Nullable;
import static org.hibernate.generator.EventTypeSets.INSERT_AND_UPDATE;
@ -187,9 +186,7 @@ public class CurrentTimestampGeneration implements BeforeExecutionGenerator, OnE
public CurrentTimestampGeneration(CurrentTimestamp annotation, Member member, GeneratorCreationContext context) {
delegate = getGeneratorDelegate( annotation.source(), member, context );
eventTypes = annotation.timing() == GenerationTiming.ALWAYS
? fromArray( annotation.event() )
: annotation.timing().getEquivalent().eventTypes();
eventTypes = fromArray( annotation.event() );
}
public CurrentTimestampGeneration(CreationTimestamp annotation, Member member, GeneratorCreationContext context) {

View File

@ -7,7 +7,6 @@
package org.hibernate.generator.internal;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.dialect.Dialect;
import org.hibernate.generator.EventType;
import org.hibernate.generator.OnExecutionGenerator;
@ -32,16 +31,14 @@ public class GeneratedGeneration implements OnExecutionGenerator {
private final boolean writable;
private final String[] sql;
public GeneratedGeneration(GenerationTime event) {
eventTypes = event.eventTypes();
public GeneratedGeneration(EnumSet<EventType> eventTypes) {
this.eventTypes = eventTypes;
writable = false;
sql = null;
}
public GeneratedGeneration(Generated annotation) {
eventTypes = annotation.value() == GenerationTime.INSERT
? fromArray( annotation.event() )
: annotation.value().eventTypes();
eventTypes = fromArray( annotation.event() );
sql = isEmpty( annotation.sql() ) ? null : new String[] { annotation.sql() };
writable = annotation.writable() || sql != null;
}

View File

@ -1,67 +0,0 @@
/*
* 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.tuple;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import org.hibernate.AssertionFailure;
import org.hibernate.generator.AnnotationBasedGenerator;
import org.hibernate.generator.Generator;
import org.hibernate.generator.GeneratorCreationContext;
/**
* An implementation of {@link ValueGeneration} which receives parameters from a custom
* {@linkplain org.hibernate.annotations.ValueGenerationType generator annotation}.
* <p>
* This is an older API that predates {@link Generator} and {@link AnnotationBasedGenerator}.
* It's often cleaner to implement {@code AnnotationBasedGenerator} directly.
*
* @param <A> The generator annotation type supported by an implementation
*
* @see org.hibernate.annotations.ValueGenerationType
*
* @author Gunnar Morling
*
* @see ValueGeneration
*
* @deprecated Replaced by {@link AnnotationBasedGenerator}
*/
@Deprecated(since = "6.2", forRemoval = true)
public interface AnnotationValueGeneration<A extends Annotation>
extends ValueGeneration, AnnotationBasedGenerator<A> {
/**
* Initializes this generation strategy for the given annotation instance.
*
* @param annotation an instance of the strategy's annotation type. Typically,
* implementations will retrieve the annotation's attribute
* values and store them in fields.
* @param propertyType the type of the property annotated with the generator annotation.
* @throws org.hibernate.HibernateException in case an error occurred during initialization, e.g. if
* an implementation can't create a value for the given property type.
*/
void initialize(A annotation, Class<?> propertyType);
default void initialize(A annotation, Member member, GeneratorCreationContext context) {
initialize( annotation, getPropertyType( member ) );
}
private static Class<?> getPropertyType(Member member) {
if (member instanceof Field) {
return ((Field) member).getType();
}
else if (member instanceof Method) {
return ((Method) member).getReturnType();
}
else {
throw new AssertionFailure("member should have been a method or field");
}
}
}

View File

@ -6,23 +6,21 @@
*/
package org.hibernate.tuple;
import java.util.EnumSet;
import java.util.Locale;
import org.hibernate.AssertionFailure;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.generator.EventType;
/**
* Represents the timing of {@link ValueGeneration value generation} that occurs
* in the Java program, or in the database.
* Represents the {@linkplain #getEventTypes timing} of value generation.
*
* @author Steve Ebersole
*
* @see ValueGeneration
*
* @deprecated Replaced by {@link EventType} as id-generation has been
* redefined using the new broader {@linkplain org.hibernate.generator generation}
* approach.
* approach. For 7.0, this is kept around to support {@code hbm.xml} mappings and
* will be removed in 8.0 once we finally drop {@code hbm.xml} support.
*/
@Deprecated(since = "6.2", forRemoval = true)
public enum GenerationTiming {
@ -85,20 +83,14 @@ public enum GenerationTiming {
}
/**
* @return the equivalent instance of {@link GenerationTime}
* Return the equivalent set of {@linkplain EventType event types}
*/
public GenerationTime getEquivalent() {
switch (this) {
case ALWAYS:
return GenerationTime.ALWAYS;
case INSERT:
return GenerationTime.INSERT;
case UPDATE:
return GenerationTime.UPDATE;
case NEVER:
return GenerationTime.NEVER;
default:
throw new AssertionFailure("unknown timing");
}
public EnumSet<EventType> getEventTypes() {
return switch ( this ) {
case ALWAYS -> EnumSet.allOf( EventType.class );
case INSERT -> EnumSet.of( EventType.INSERT );
case UPDATE -> EnumSet.of( EventType.UPDATE );
case NEVER -> null;
};
}
}

View File

@ -1,167 +0,0 @@
/*
* 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.tuple;
import java.util.EnumSet;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.generator.EventType;
import org.hibernate.generator.Generator;
import org.hibernate.generator.OnExecutionGenerator;
import org.hibernate.generator.BeforeExecutionGenerator;
/**
* A value generator that can adapt to both Java value generation and database value generation.
* <p>
* This is an older API that predates {@link Generator}. It's often cleaner to implement either
* {@link BeforeExecutionGenerator} or {@link OnExecutionGenerator} directly.
*
* @author Steve Ebersole
* @author Gavin King
*
* @see AnnotationValueGeneration
*
* @deprecated Replaced by {@link Generator}
*/
@Deprecated(since = "6.2", forRemoval = true)
public interface ValueGeneration extends BeforeExecutionGenerator, OnExecutionGenerator {
/**
* 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 EnumSet<EventType> getEventTypes() {
return getGenerationTiming().getEquivalent().eventTypes();
}
/**
* 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.
*
* @return The value generator
*/
ValueGenerator<?> getValueGenerator();
@Override
default Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue, EventType eventType) {
return getValueGenerator().generateValue( session.asSessionImplementor(), owner, currentValue );
}
/**
* Determines if the column whose value is generated is included in the column list of the
* SQL {@code insert} or {@code update} statement, in the case where the value is generated
* by the database. For example, this method should return:
* <ul>
* <li>{@code true} if the value is generated by calling a SQL function like
* {@code current_timestamp}, or
* <li>{@code false} if the value is generated by a trigger,
* by {@link org.hibernate.annotations.GeneratedColumn generated always as}, or
* using a {@linkplain org.hibernate.annotations.ColumnDefault column default value}.
* </ul>
* <p>
* If the value is generated in Java, this method is not called, and so for backward
* compatibility with Hibernate 5 it is permitted to return any value. On the other hand,
* when a property value is generated in Java, the column certainly must be included in the
* column list, and so it's most correct for this method to return {@code true}!
*
* @return {@code true} if the column is included in the column list of the SQL statement.
*/
boolean referenceColumnInSql();
/**
* A SQL expression indicating how to calculate the generated value when the property value
* is {@linkplain #generatedOnExecution() generated in the database} and the mapped column is
* {@linkplain #referenceColumnInSql() included in the SQL statement}. The SQL expression
* might be:
* <ul>
* <li>a function call like {@code current_timestamp} or {@code nextval('mysequence')}, or
* <li>a syntactic marker like {@code default}.
* </ul>
* <p>
* When the property value is generated in Java, this method is not called, and its value is
* implicitly the string {@code "?"}, that is, a JDBC parameter to which the generated value
* is bound.
*
* @return The column value to be used in the generated SQL statement.
*/
String getDatabaseGeneratedReferencedColumnValue();
/**
* A SQL expression indicating how to calculate the generated value when the property value
* is {@linkplain #generatedOnExecution() generated in the database} and the mapped column is
* {@linkplain #referenceColumnInSql() included in the SQL statement}. The SQL expression
* might be:
* <ul>
* <li>a function call like {@code current_timestamp} or {@code nextval('mysequence')}, or
* <li>a syntactic marker like {@code default}.
* </ul>
* <p>
* When the property value is generated in Java, this method is not called, and its value is
* implicitly the string {@code "?"}, that is, a JDBC parameter to which the generated value
* is bound.
*
* @param dialect The {@linkplain Dialect SQL dialect}, allowing generation of an expression
* in dialect-specific SQL.
* @return The column value to be used in the generated SQL statement.
*/
default String getDatabaseGeneratedReferencedColumnValue(Dialect dialect) {
return getDatabaseGeneratedReferencedColumnValue();
}
@Override
default String[] getReferencedColumnValues(Dialect dialect) {
String columnValue = getDatabaseGeneratedReferencedColumnValue( dialect );
return columnValue == null ? null : new String[] { columnValue };
}
@Override
default boolean referenceColumnsInSql(Dialect dialect) {
return referenceColumnInSql();
}
/**
* Determines if the property value is generated in Java, or by the database.
* <p>
* This default implementation returns true if the {@linkplain #getValueGenerator() Java
* value generator} is {@code null}.
*
* @return {@code true} if the value is generated by the database, or false if it is
* generated in Java using a {@link ValueGenerator}.
*/
@Override
default boolean generatedOnExecution() {
return getValueGenerator() == null;
}
/**
* Determines if the property value is written to JDBC as the argument of a JDBC {@code ?}
* parameter. This is the case when either:
* <ul>
* <li>the value is generated in Java, or
* <li>{@link #referenceColumnInSql()} is {@code true} and
* {@link #getDatabaseGeneratedReferencedColumnValue()} returns {@code null}.
* </ul>
*
* @see org.hibernate.annotations.Generated#writable()
*/
@Override
default boolean writePropertyValue() {
return !this.generatedOnExecution() // value generated in memory and then written as normal
// current value of property of entity instance written completely as normal
|| referenceColumnInSql() && getDatabaseGeneratedReferencedColumnValue()==null;
}
}

View File

@ -1,43 +0,0 @@
/*
* 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.tuple;
import org.hibernate.Session;
import org.hibernate.generator.Generator;
/**
* Defines a generator for in-VM generation of (non-identifier) attribute values.
*
* @deprecated Replaced by {@link Generator}
*
* @author Steve Ebersole
*/
@Deprecated(since = "6.2", forRemoval = true)
public interface ValueGenerator<T> {
/**
* Generate the value.
*
* @param session The Session from which the request originates.
* @param owner The instance of the object owning the attribute for which we are generating a value.
*
* @return The generated value
*/
T generateValue(Session session, Object owner);
/**
* Generate the value.
*
* @param session The Session from which the request originates.
* @param owner The instance of the object owning the attribute for which we are generating a value.
* @param currentValue The current value assigned to the property
*
* @return The generated value
*/
default T generateValue(Session session, Object owner, Object currentValue) {
return generateValue( session, owner );
}
}

View File

@ -1,56 +0,0 @@
/*
* 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.tuple;
import java.lang.reflect.Constructor;
import java.util.EnumSet;
import org.hibernate.HibernateException;
import org.hibernate.Internal;
import org.hibernate.annotations.GeneratorType;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.generator.EventType;
import org.hibernate.generator.BeforeExecutionGenerator;
import static org.hibernate.internal.util.ReflectHelper.getDefaultConstructor;
/**
* A {@link BeforeExecutionGenerator} which delegates to a {@link ValueGenerator}.
* Underlies the {@link GeneratorType} annotation.
*
* @author Gunnar Morling
*
* @deprecated since {@link GeneratorType} is deprecated
*/
@Internal
@Deprecated(since = "6.2")
public class VmValueGeneration implements BeforeExecutionGenerator {
private final EnumSet<EventType> eventTypes;
private final ValueGenerator<?> generator;
public VmValueGeneration(GeneratorType annotation) {
Constructor<? extends ValueGenerator<?>> constructor = getDefaultConstructor( annotation.type() );
try {
generator = constructor.newInstance();
}
catch (Exception e) {
throw new HibernateException( "Couldn't instantiate value generator", e );
}
eventTypes = annotation.when().eventTypes();
}
@Override
public EnumSet<EventType> getEventTypes() {
return eventTypes;
}
@Override
public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue, EventType eventType) {
return generator.generateValue( session.asSessionImplementor(), owner, currentValue );
}
}

View File

@ -740,7 +740,7 @@
</bindings>
<bindings node="//xsd:simpleType[@name='basic-generation-timing-type']">
<javaType name="org.hibernate.tuple.GenerationTiming"
<javaType name="org.hibernate.boot.jaxb.mapping.GenerationTiming"
parseMethod="org.hibernate.boot.jaxb.mapping.internal.GenerationTimingMarshalling.fromXml"
printMethod="org.hibernate.boot.jaxb.mapping.internal.GenerationTimingMarshalling.toXml" />
</bindings>

View File

@ -9,29 +9,33 @@ package org.hibernate.orm.test.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Date;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import java.util.EnumSet;
import org.hibernate.annotations.NaturalId;
import org.hibernate.annotations.ValueGenerationType;
import org.hibernate.tuple.AnnotationValueGeneration;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.ValueGenerator;
import org.hibernate.dialect.Dialect;
import org.hibernate.generator.EventType;
import org.hibernate.generator.EventTypeSets;
import org.hibernate.generator.OnExecutionGenerator;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.Jpa;
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
/**
* @author Vlad Mihalcea
*/
@TestForIssue( jiraKey = "HHH-11096" )
@SuppressWarnings("JUnitMalformedDeclaration")
@JiraKey( "HHH-11096" )
@RequiresDialectFeature( feature = DialectFeatureChecks.UsesStandardCurrentTimestampFunction.class )
@Jpa(
annotatedClasses = {
@ -41,7 +45,7 @@ import org.junit.jupiter.api.Test;
public class DatabaseCreationTimestampNullableColumnTest {
@Entity(name = "Person")
public class Person {
public static class Person {
@Id
@GeneratedValue
@ -76,43 +80,25 @@ public class DatabaseCreationTimestampNullableColumnTest {
@Retention(RetentionPolicy.RUNTIME)
public @interface FunctionCreationTimestamp {}
public static class FunctionCreationValueGeneration
implements AnnotationValueGeneration<FunctionCreationTimestamp> {
public static class FunctionCreationValueGeneration implements OnExecutionGenerator {
@Override
public EnumSet<EventType> getEventTypes() {
return EventTypeSets.INSERT_ONLY;
}
@Override
public void initialize(FunctionCreationTimestamp annotation, Class<?> propertyType) {
}
/**
* Generate value on INSERT
* @return when to generate the value
*/
public GenerationTiming getGenerationTiming() {
return GenerationTiming.INSERT;
}
/**
* Returns null because the value is generated by the database.
* @return null
*/
public ValueGenerator<?> getValueGenerator() {
return null;
}
/**
* Returns true because the value is generated by the database.
* @return true
*/
public boolean referenceColumnInSql() {
public boolean referenceColumnsInSql(Dialect dialect) {
return true;
}
/**
* Returns the database-generated value
* @return database-generated value
*/
public String getDatabaseGeneratedReferencedColumnValue() {
return "current_timestamp";
@Override
public boolean writePropertyValue() {
return false;
}
@Override
public String[] getReferencedColumnValues(Dialect dialect) {
return new String[] { dialect.currentTimestamp() };
}
}

View File

@ -6,31 +6,36 @@
*/
package org.hibernate.orm.test.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Member;
import java.util.Date;
import java.util.EnumSet;
import org.hibernate.annotations.NaturalId;
import org.hibernate.annotations.ValueGenerationType;
import org.hibernate.dialect.Dialect;
import org.hibernate.generator.EventType;
import org.hibernate.generator.EventTypeSets;
import org.hibernate.generator.GeneratorCreationContext;
import org.hibernate.generator.OnExecutionGenerator;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.annotations.NaturalId;
import org.hibernate.annotations.ValueGenerationType;
import org.hibernate.dialect.Dialect;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
import org.hibernate.tuple.AnnotationValueGeneration;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.ValueGenerator;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Date;
@SuppressWarnings("JUnitMalformedDeclaration")
@Jpa(annotatedClasses = DatabaseTimestampsColumnTest.Person.class)
public class DatabaseTimestampsColumnTest {
@Entity(name = "Person")
public class Person {
public static class Person {
@Id
@GeneratedValue
@ -40,15 +45,15 @@ public class DatabaseTimestampsColumnTest {
private String name;
@Column(nullable = false)
@Timestamp(GenerationTime.INSERT)
@Timestamp
private Date creationDate;
@Column(nullable = true)
@Timestamp(GenerationTime.UPDATE)
@Timestamp(EventType.UPDATE)
private Date editionDate;
@Column(nullable = false, name="version")
@Timestamp(GenerationTime.ALWAYS)
@Timestamp({ EventType.INSERT, EventType.UPDATE })
private Date timestamp;
public String getName() {
@ -74,36 +79,33 @@ public class DatabaseTimestampsColumnTest {
@ValueGenerationType(generatedBy = TimestampValueGeneration.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface Timestamp { GenerationTime value(); }
public @interface Timestamp { EventType[] value() default EventType.INSERT; }
public static class TimestampValueGeneration
implements AnnotationValueGeneration<Timestamp> {
public static class TimestampValueGeneration implements OnExecutionGenerator {
private EnumSet<EventType> events;
private GenerationTiming timing;
public TimestampValueGeneration(Timestamp annotation, Member member, GeneratorCreationContext context) {
events = EventTypeSets.fromArray( annotation.value() );
}
@Override
public void initialize(Timestamp annotation, Class<?> propertyType) {
timing = annotation.value().getEquivalent();
public EnumSet<EventType> getEventTypes() {
return events;
}
public GenerationTiming getGenerationTiming() {
return timing;
}
public ValueGenerator<?> getValueGenerator() {
return null;
}
public boolean referenceColumnInSql() {
@Override
public boolean referenceColumnsInSql(Dialect dialect) {
return true;
}
public String getDatabaseGeneratedReferencedColumnValue() {
return "current_timestamp";
@Override
public String[] getReferencedColumnValues(Dialect dialect) {
return new String[] { dialect.currentTimestamp() };
}
public String getDatabaseGeneratedReferencedColumnValue(Dialect dialect) {
return dialect.currentTimestamp();
@Override
public boolean writePropertyValue() {
return false;
}
}

View File

@ -7,25 +7,27 @@
//$Id$
package org.hibernate.orm.test.annotations.various;
import org.hibernate.annotations.Generated;
import org.hibernate.generator.EventType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
/**
* @author Emmanuel Bernard
*/
@Entity
public class Antenna {
@Id public Integer id;
@Generated(GenerationTime.ALWAYS) @Column()
@Generated(event = { EventType.INSERT, EventType.UPDATE})
@Column()
public String longitude;
@Generated(GenerationTime.INSERT) @Column(insertable = false)
@Generated(event = EventType.INSERT)
@Column(insertable = false)
public String latitude;
@Generated(GenerationTime.NEVER)
public Double power;
}

View File

@ -4,6 +4,7 @@ import org.hibernate.annotations.Generated;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLInsert;
import org.hibernate.annotations.SQLUpdate;
import org.hibernate.generator.EventType;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
@ -19,9 +20,9 @@ import jakarta.persistence.Table;
import jakarta.persistence.Version;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hibernate.annotations.GenerationTime.ALWAYS;
import static org.junit.jupiter.api.Assertions.assertEquals;
@SuppressWarnings("JUnitMalformedDeclaration")
@SessionFactory
@DomainModel(annotatedClasses = CustomSqlGeneratedTest.Custom.class)
public class CustomSqlGeneratedTest {
@ -63,9 +64,9 @@ public class CustomSqlGeneratedTest {
Long id;
@Version @Column(name = "revision")
int version;
@Generated(value = ALWAYS, writable = true)
@Generated(event = { EventType.INSERT, EventType.UPDATE}, writable = true)
String name;
@Generated(value = ALWAYS, writable = true)
@Generated(event = { EventType.INSERT, EventType.UPDATE}, writable = true)
@Column(table = "CustomSecondary")
String text;
}

View File

@ -20,21 +20,16 @@ import java.time.YearMonth;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.annotations.GeneratorType;
import org.hibernate.annotations.UpdateTimestamp;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.dialect.TiDBDialect;
import org.hibernate.generator.EventType;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
@ -42,6 +37,11 @@ import org.hibernate.testing.orm.junit.SkipForDialect;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import static org.assertj.core.api.Assertions.assertThat;
/**
@ -52,6 +52,7 @@ import static org.assertj.core.api.Assertions.assertThat;
@SkipForDialect(dialectClass = TiDBDialect.class, reason = "See HHH-10196")
@DomainModel( annotatedClasses = ComplexValueGenerationTests.AuditedEntity.class )
@SessionFactory
@SuppressWarnings("JUnitMalformedDeclaration")
public class ComplexValueGenerationTests {
@Test
public void testGenerations(SessionFactoryScope scope) {
@ -139,12 +140,12 @@ public class ComplexValueGenerationTests {
@Id
private Integer id;
@Generated( GenerationTime.INSERT )
@Generated
@ColumnDefault( "CURRENT_TIMESTAMP" )
@Column( nullable = false )
private Date createdDate;
@Generated( GenerationTime.ALWAYS )
@Generated(event = { EventType.INSERT, EventType.UPDATE } )
@ColumnDefault( "CURRENT_TIMESTAMP" )
@Column( nullable = false )
private Calendar alwaysDate;
@ -197,7 +198,7 @@ public class ComplexValueGenerationTests {
@UpdateTimestamp
private Timestamp updated;
@GeneratorType( type = DefaultGeneratedValueTest.MyVmValueGenerator.class, when = GenerationTime.INSERT )
@StaticGeneration( value = "Bob" )
private String name;
@SuppressWarnings("unused")

View File

@ -9,21 +9,24 @@ package org.hibernate.orm.test.mapping.generated;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Date;
import java.util.EnumSet;
import org.hibernate.annotations.ValueGenerationType;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.generator.EventType;
import org.hibernate.generator.EventTypeSets;
import org.hibernate.generator.OnExecutionGenerator;
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.SkipForDialect;
import org.junit.Test;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import org.hibernate.annotations.ValueGenerationType;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
import org.hibernate.tuple.AnnotationValueGeneration;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.ValueGenerator;
import org.hibernate.testing.SkipForDialect;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
@ -81,43 +84,25 @@ public class DatabaseValueGenerationTest extends BaseEntityManagerFunctionalTest
@Retention(RetentionPolicy.RUNTIME)
public @interface FunctionCreationTimestamp {}
public static class FunctionCreationValueGeneration
implements AnnotationValueGeneration<FunctionCreationTimestamp> {
public static class FunctionCreationValueGeneration implements OnExecutionGenerator {
@Override
public EnumSet<EventType> getEventTypes() {
return EventTypeSets.INSERT_ONLY;
}
@Override
public void initialize(FunctionCreationTimestamp annotation, Class<?> propertyType) {
}
/**
* Generate value on INSERT
* @return when to generate the value
*/
public GenerationTiming getGenerationTiming() {
return GenerationTiming.INSERT;
}
/**
* Returns null because the value is generated by the database.
* @return null
*/
public ValueGenerator<?> getValueGenerator() {
return null;
}
/**
* Returns true because the value is generated by the database.
* @return true
*/
public boolean referenceColumnInSql() {
public boolean referenceColumnsInSql(Dialect dialect) {
return true;
}
/**
* Returns the database-generated value
* @return database-generated value
*/
public String getDatabaseGeneratedReferencedColumnValue() {
return "current_timestamp";
@Override
public boolean writePropertyValue() {
return false;
}
@Override
public String[] getReferencedColumnValues(Dialect dialect) {
return new String[] { dialect.currentTimestamp() };
}
}
//end::mapping-database-generated-value-example[]

View File

@ -8,6 +8,7 @@ package org.hibernate.orm.test.mapping.generated;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Member;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.Instant;
@ -22,25 +23,20 @@ import java.time.YearMonth;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import java.util.EnumSet;
import org.hibernate.Session;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.annotations.GeneratorType;
import org.hibernate.annotations.UpdateTimestamp;
import org.hibernate.annotations.ValueGenerationType;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.tuple.AnnotationValueGeneration;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.ValueGenerator;
import org.hibernate.generator.AnnotationBasedGenerator;
import org.hibernate.generator.EventType;
import org.hibernate.generator.GeneratorCreationContext;
import org.hibernate.generator.OnExecutionGenerator;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
@ -49,6 +45,12 @@ import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@ -149,12 +151,12 @@ public class DefaultGeneratedValueIdentityTest extends BaseCoreFunctionalTestCas
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Generated( GenerationTime.INSERT )
@Generated
@ColumnDefault( "CURRENT_TIMESTAMP" )
@Column( nullable = false )
private Date createdDate;
@Generated( GenerationTime.ALWAYS )
@Generated(event = { EventType.INSERT, EventType.UPDATE})
@ColumnDefault( "CURRENT_TIMESTAMP" )
@Column( nullable = false )
private Calendar alwaysDate;
@ -210,7 +212,7 @@ public class DefaultGeneratedValueIdentityTest extends BaseCoreFunctionalTestCas
@UpdateTimestamp
private Timestamp updated;
@GeneratorType( type = MyVmValueGenerator.class, when = GenerationTime.INSERT )
@StaticGeneration
private String name;
@SuppressWarnings("unused")
@ -224,42 +226,30 @@ public class DefaultGeneratedValueIdentityTest extends BaseCoreFunctionalTestCas
}
}
public static class MyVmValueGenerator implements ValueGenerator<String> {
@Override
public String generateValue(Session session, Object owner) {
return "Bob";
}
}
@ValueGenerationType(generatedBy = FunctionCreationValueGeneration.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface FunctionCreationTimestamp {
}
public static class FunctionCreationValueGeneration
implements AnnotationValueGeneration<FunctionCreationTimestamp> {
public static class FunctionCreationValueGeneration implements OnExecutionGenerator {
@Override
public EnumSet<EventType> getEventTypes() {
return EnumSet.of( EventType.INSERT );
}
@Override
public void initialize(FunctionCreationTimestamp annotation, Class<?> propertyType) {
}
public GenerationTiming getGenerationTiming() {
// its creation...
return GenerationTiming.INSERT;
}
public ValueGenerator<?> getValueGenerator() {
// no in-memory generation
return null;
}
public boolean referenceColumnInSql() {
public boolean referenceColumnsInSql(Dialect dialect) {
return true;
}
public String getDatabaseGeneratedReferencedColumnValue() {
return "current_timestamp";
@Override
public boolean writePropertyValue() {
return false;
}
@Override
public String[] getReferencedColumnValues(Dialect dialect) {
return new String[] { "current_timestamp" };
}
}

View File

@ -20,28 +20,19 @@ import java.time.YearMonth;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.Session;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.annotations.GeneratorType;
import org.hibernate.annotations.UpdateTimestamp;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.dialect.TiDBDialect;
import org.hibernate.generator.EventType;
import org.hibernate.generator.internal.CurrentTimestampGeneration;
import org.hibernate.orm.test.annotations.MutableClock;
import org.hibernate.orm.test.annotations.MutableClockSettingProvider;
import org.hibernate.tuple.ValueGenerator;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.ServiceRegistry;
@ -49,19 +40,22 @@ import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.SettingProvider;
import org.hibernate.testing.orm.junit.SkipForDialect;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
* Test for the generation of column values using different
* {@link org.hibernate.tuple.ValueGeneration} implementations.
* Test for the generation of column values using different value generation strategies.
*
* @author Steve Ebersole
* @author Gunnar Morling
@ -69,9 +63,10 @@ import static org.junit.Assert.assertTrue;
@SkipForDialect( dialectClass = SybaseDialect.class, matchSubTypes = true, reason = "CURRENT_TIMESTAMP not supported as default value in Sybase" )
@SkipForDialect( dialectClass = MySQLDialect.class, reason = "See HHH-10196" )
@SkipForDialect( dialectClass = TiDBDialect.class, reason = "See HHH-10196" )
@ServiceRegistry(settingProviders = @SettingProvider(settingName = CurrentTimestampGeneration.CLOCK_SETTING_NAME, provider = MutableClockSettingProvider.class))
@DomainModel( annotatedClasses = DefaultGeneratedValueTest.TheEntity.class )
@SessionFactory
@ServiceRegistry(settingProviders = @SettingProvider(settingName = CurrentTimestampGeneration.CLOCK_SETTING_NAME, provider = MutableClockSettingProvider.class))
@SuppressWarnings("JUnitMalformedDeclaration")
public class DefaultGeneratedValueTest {
private MutableClock clock;
@ -155,7 +150,7 @@ public class DefaultGeneratedValueTest {
}
@Test
@TestForIssue(jiraKey = "HHH-2907")
@JiraKey("HHH-2907")
public void testUpdateTimestampGeneration(SessionFactoryScope scope) {
final TheEntity created = scope.fromTransaction( (s) -> {
TheEntity theEntity = new TheEntity( 1 );
@ -195,12 +190,12 @@ public class DefaultGeneratedValueTest {
@Id
private Integer id;
@Generated( GenerationTime.INSERT )
@Generated
@ColumnDefault( "CURRENT_TIMESTAMP" )
@Column( nullable = false )
private Date createdDate;
@Generated( GenerationTime.ALWAYS )
@Generated( event = { EventType.INSERT, EventType.UPDATE } )
@ColumnDefault( "CURRENT_TIMESTAMP" )
@Column( nullable = false )
private Calendar alwaysDate;
@ -253,7 +248,7 @@ public class DefaultGeneratedValueTest {
@UpdateTimestamp
private Timestamp updated;
@GeneratorType( type = MyVmValueGenerator.class, when = GenerationTime.INSERT )
@StaticGeneration( value = "Bob" )
private String name;
@SuppressWarnings("unused")
@ -266,13 +261,4 @@ public class DefaultGeneratedValueTest {
this.id = id;
}
}
public static class MyVmValueGenerator implements ValueGenerator<String> {
@Override
public String generateValue(Session session, Object owner) {
return "Bob";
}
}
}

View File

@ -8,15 +8,11 @@ package org.hibernate.orm.test.mapping.generated;
import java.time.Instant;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.HibernateError;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.generator.EventType;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialect;
@ -26,11 +22,16 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Steve Ebersole
*/
@SuppressWarnings("JUnitMalformedDeclaration")
@DomainModel( annotatedClasses = GeneratedAnnotationTests.AuditedEntity.class )
@SessionFactory
@RequiresDialect(value = PostgreSQLDialect.class, comment = "To write a trigger only once")
@ -108,10 +109,10 @@ public class GeneratedAnnotationTests {
@Id
public Integer id;
public String name;
@Generated( GenerationTime.INSERT )
@Generated
@ColumnDefault( "current_timestamp" )
public Instant createdAt;
@Generated( GenerationTime.ALWAYS )
@Generated( event = { EventType.INSERT, EventType.UPDATE } )
@ColumnDefault( "current_timestamp" )
public Instant lastUpdatedAt;

View File

@ -6,17 +6,22 @@
*/
package org.hibernate.orm.test.mapping.generated;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import java.lang.reflect.Member;
import java.util.EnumSet;
import org.hibernate.Session;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.annotations.GeneratorType;
import org.hibernate.annotations.ValueGenerationType;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.generator.BeforeExecutionGenerator;
import org.hibernate.generator.EventType;
import org.hibernate.generator.EventTypeSets;
import org.hibernate.generator.GeneratorCreationContext;
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
import org.hibernate.tuple.ValueGenerator;
import org.junit.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
@ -81,13 +86,31 @@ public class GeneratorTypeTest extends BaseEntityManagerFunctionalTestCase {
}
}
public static class LoggedUserGenerator implements ValueGenerator<String> {
@ValueGenerationType( generatedBy = LoggedUserGenerator.class)
public @interface CurrentUserGeneration {
EventType[] timing() default EventType.INSERT;
}
public static class LoggedUserGenerator implements BeforeExecutionGenerator {
private final EnumSet<EventType> events;
public LoggedUserGenerator(CurrentUserGeneration annotation, Member member, GeneratorCreationContext context) {
this.events = EventTypeSets.fromArray( annotation.timing() );
}
@Override
public String generateValue(
Session session, Object owner) {
public Object generate(
SharedSessionContractImplementor session,
Object owner,
Object currentValue,
EventType eventType) {
return CurrentUser.INSTANCE.get();
}
@Override
public EnumSet<EventType> getEventTypes() {
return events;
}
}
@Entity(name = "Person")
@ -100,10 +123,10 @@ public class GeneratorTypeTest extends BaseEntityManagerFunctionalTestCase {
private String lastName;
@GeneratorType(type = LoggedUserGenerator.class, when = GenerationTime.INSERT)
@CurrentUserGeneration
private String createdBy;
@GeneratorType(type = LoggedUserGenerator.class, when = GenerationTime.ALWAYS)
@CurrentUserGeneration( timing = {EventType.INSERT, EventType.UPDATE} )
private String updatedBy;
//end::mapping-generated-GeneratorType-example[]

View File

@ -7,16 +7,12 @@
package org.hibernate.orm.test.mapping.generated;
import java.sql.Timestamp;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.HibernateError;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import org.hibernate.annotations.CurrentTimestamp;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.annotations.UpdateTimestamp;
import org.hibernate.generator.EventType;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
@ -26,6 +22,11 @@ import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import static org.assertj.core.api.Assertions.assertThat;
/**
@ -94,9 +95,9 @@ public class InDbGenerationsWithAnnotationsTests {
@Basic
public String name;
@CurrentTimestamp( timing = GenerationTiming.INSERT )
@CurrentTimestamp(event = EventType.INSERT)
public Timestamp createdOn;
@CurrentTimestamp( timing = GenerationTiming.ALWAYS )
@CurrentTimestamp
public Timestamp lastUpdatedOn;
public AuditedEntity() {

View File

@ -9,19 +9,22 @@ package org.hibernate.orm.test.mapping.generated;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Date;
import java.util.EnumSet;
import org.hibernate.annotations.ValueGenerationType;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.generator.BeforeExecutionGenerator;
import org.hibernate.generator.EventType;
import org.hibernate.generator.EventTypeSets;
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
import org.junit.Test;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import org.hibernate.annotations.ValueGenerationType;
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
import org.hibernate.tuple.AnnotationValueGeneration;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.ValueGenerator;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
@ -77,43 +80,19 @@ public class InMemoryValueGenerationTest extends BaseEntityManagerFunctionalTest
@Retention(RetentionPolicy.RUNTIME)
public @interface FunctionCreationTimestamp {}
public static class FunctionCreationValueGeneration
implements AnnotationValueGeneration<FunctionCreationTimestamp> {
public static class FunctionCreationValueGeneration implements BeforeExecutionGenerator {
@Override
public Object generate(
SharedSessionContractImplementor session,
Object owner,
Object currentValue,
EventType eventType) {
return new Date();
}
@Override
public void initialize(FunctionCreationTimestamp annotation, Class<?> propertyType) {
}
/**
* Generate value on INSERT
* @return when to generate the value
*/
public GenerationTiming getGenerationTiming() {
return GenerationTiming.INSERT;
}
/**
* Returns the in-memory generated value
* @return {@code true}
*/
public ValueGenerator<?> getValueGenerator() {
return (session, owner) -> new Date();
}
/**
* Returns false because the value is generated by the database.
* @return false
*/
public boolean referenceColumnInSql() {
return false;
}
/**
* Returns null because the value is generated in-memory.
* @return null
*/
public String getDatabaseGeneratedReferencedColumnValue() {
return null;
public EnumSet<EventType> getEventTypes() {
return EventTypeSets.INSERT_ONLY;
}
}
//end::mapping-in-memory-generated-value-example[]

View File

@ -0,0 +1,28 @@
/*
* 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.orm.test.mapping.generated;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import org.hibernate.annotations.ValueGenerationType;
import org.hibernate.generator.EventType;
import static org.hibernate.generator.EventType.INSERT;
/**
* @author Steve Ebersole
*/
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@ValueGenerationType( generatedBy = StaticValueGenerator.class )
public @interface StaticGeneration {
String value() default "Bob";
EventType[] event() default INSERT;
}

View File

@ -0,0 +1,55 @@
/*
* 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.orm.test.mapping.generated;
import java.lang.reflect.Member;
import java.util.EnumSet;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.generator.BeforeExecutionGenerator;
import org.hibernate.generator.EventType;
import org.hibernate.generator.GeneratorCreationContext;
/**
* @author Steve Ebersole
*/
public class StaticValueGenerator implements BeforeExecutionGenerator {
private final String staticValue;
private final EnumSet<EventType> events;
public StaticValueGenerator(StaticGeneration annotation, Member member, GeneratorCreationContext context) {
this.staticValue = annotation.value();
this.events = toEnumSet( annotation.event() );
}
private static EnumSet<EventType> toEnumSet(EventType[] events) {
if ( events.length == 0 ) {
return EnumSet.of( EventType.INSERT );
}
if ( events.length == 1 ) {
return EnumSet.of ( events[0] );
}
assert events.length == 2;
return EnumSet.allOf( EventType.class );
}
@Override
public String generate(
SharedSessionContractImplementor session,
Object owner,
Object currentValue,
EventType eventType) {
return staticValue;
}
@Override
public EnumSet<EventType> getEventTypes() {
return events;
}
}

View File

@ -1,23 +1,25 @@
package org.hibernate.orm.test.mapping.generated.sqldefault;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import java.math.BigDecimal;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import static org.junit.Assert.assertEquals;
/**
* @author Gavin King
*/
@SuppressWarnings("JUnitMalformedDeclaration")
@DomainModel(annotatedClasses = DefaultTest.OrderLine.class)
@SessionFactory
public class DefaultTest {
@ -59,7 +61,7 @@ public class DefaultTest {
private BigDecimal unitPrice;
@Id @ColumnDefault(value = "1")
private int quantity;
@Generated(GenerationTime.INSERT)
@Generated
@ColumnDefault(value = "'new'")
private String status;

View File

@ -1,25 +1,27 @@
package org.hibernate.orm.test.mapping.generated.sqldefault;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import java.math.BigDecimal;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.DialectOverride;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import static org.junit.Assert.assertEquals;
/**
* @author Gavin King
*/
@SuppressWarnings("JUnitMalformedDeclaration")
@DomainModel(annotatedClasses = OverriddenDefaultTest.OrderLine.class)
@SessionFactory
public class OverriddenDefaultTest {
@ -65,7 +67,7 @@ public class OverriddenDefaultTest {
private BigDecimal unitPrice;
@Id @ColumnDefault("1")
private int quantity;
@Generated(GenerationTime.INSERT)
@Generated
@ColumnDefault("'new'")
@DialectOverride.ColumnDefault(dialect = H2Dialect.class,
sameOrAfter = @DialectOverride.Version(major=1, minor=4),

View File

@ -7,13 +7,10 @@
package org.hibernate.orm.test.mapping.generated.temporals;
import java.time.Instant;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.HibernateError;
import org.hibernate.annotations.CurrentTimestamp;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.generator.EventType;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
@ -22,6 +19,10 @@ import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import static org.assertj.core.api.Assertions.assertThat;
/**
@ -96,10 +97,10 @@ public class GeneratedInstantTests {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Legacy `Generated`
@CurrentTimestamp( timing = GenerationTiming.INSERT )
@CurrentTimestamp(event = EventType.INSERT)
public Instant createdAt;
@CurrentTimestamp( timing = GenerationTiming.ALWAYS )
@CurrentTimestamp
public Instant updatedAt;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -13,32 +13,36 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.EnumSet;
import java.util.UUID;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.annotations.ValueGenerationType;
import org.hibernate.dialect.SybaseASEDialect;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.generator.EventType;
import org.hibernate.testing.util.uuid.SafeRandomUUIDGenerator;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.generator.BeforeExecutionGenerator;
import org.hibernate.generator.EventType;
import org.hibernate.generator.EventTypeSets;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.SkipForDialect;
import org.hibernate.testing.util.uuid.SafeRandomUUIDGenerator;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hibernate.generator.EventType.INSERT;
import static org.hibernate.generator.EventType.UPDATE;
/**
* Test illustrating usage of {@link ValueGenerationType}
*
* @author Steve Ebersole
*/
@SuppressWarnings("JUnitMalformedDeclaration")
@DomainModel( annotatedClasses = GeneratedUuidTests.GeneratedUuidEntity.class )
@SessionFactory
@SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "Driver or DB omit trailing zero bytes of a varbinary, making this test fail intermittently")
@ -84,7 +88,7 @@ public class GeneratedUuidTests {
@Target( { ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE } )
@Inherited
public @interface GeneratedUuidValue {
GenerationTiming timing();
EventType[] timing();
}
//end::mapping-generated-custom-ex2[]
@ -93,7 +97,7 @@ public class GeneratedUuidTests {
private final EnumSet<EventType> eventTypes;
public UuidValueGeneration(GeneratedUuidValue annotation) {
eventTypes = annotation.timing().getEquivalent().eventTypes();
eventTypes = EventTypeSets.fromArray( annotation.timing() );
}
@Override
@ -117,10 +121,10 @@ public class GeneratedUuidTests {
public String name;
//tag::mapping-generated-custom-ex1[]
@GeneratedUuidValue( timing = GenerationTiming.INSERT )
@GeneratedUuidValue( timing = INSERT )
public UUID createdUuid;
@GeneratedUuidValue( timing = GenerationTiming.ALWAYS )
@GeneratedUuidValue( timing = {INSERT, UPDATE} )
public UUID updatedUuid;
//end::mapping-generated-custom-ex1[]

View File

@ -7,15 +7,12 @@
package org.hibernate.orm.test.mapping.generated.temporals;
import java.time.Instant;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.HibernateError;
import org.hibernate.annotations.CurrentTimestamp;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.dialect.SybaseASEDialect;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.generator.EventType;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
@ -25,6 +22,10 @@ import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.SkipForDialect;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import static org.assertj.core.api.Assertions.assertThat;
/**
@ -32,6 +33,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*
* @author Steve Ebersole
*/
@SuppressWarnings("JUnitMalformedDeclaration")
@DomainModel( annotatedClasses = MultipleGeneratedValuesTests.GeneratedInstantEntity.class )
@SessionFactory
@RequiresDialectFeature(feature = DialectFeatureChecks.CurrentTimestampHasMicrosecondPrecision.class, comment = "Without this, we might not see an update to the timestamp")
@ -103,18 +105,18 @@ public class MultipleGeneratedValuesTests {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Legacy `Generated`
@CurrentTimestamp( timing = GenerationTiming.INSERT )
@CurrentTimestamp(event = EventType.INSERT)
public Instant createdAt;
@CurrentTimestamp( timing = GenerationTiming.ALWAYS )
@CurrentTimestamp
public Instant updatedAt;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// `GeneratedValue`
@ProposedGenerated( timing = GenerationTiming.INSERT, sqlDefaultValue = "current_timestamp" )
@ProposedGenerated( timing = EventType.INSERT, sqlDefaultValue = "current_timestamp" )
public Instant createdAt2;
@ProposedGenerated( timing = GenerationTiming.ALWAYS, sqlDefaultValue = "current_timestamp" )
@ProposedGenerated( timing = {EventType.INSERT,EventType.UPDATE}, sqlDefaultValue = "current_timestamp" )
public Instant updatedAt2;
public GeneratedInstantEntity() {

View File

@ -12,7 +12,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.hibernate.annotations.ValueGenerationType;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.generator.EventType;
/**
* Proposal for making {@link org.hibernate.annotations.Generated} work for update (they don't work in 5.x either)
@ -28,7 +28,7 @@ public @interface ProposedGenerated {
/**
* When the generation should occur
*/
GenerationTiming timing();
EventType[] timing();
/**
* Value to use as the value for the column reference in the SQL.

View File

@ -7,13 +7,10 @@
package org.hibernate.orm.test.mapping.generated.temporals;
import java.time.Instant;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.HibernateError;
import org.hibernate.dialect.SybaseASEDialect;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.generator.EventType;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
@ -23,6 +20,10 @@ import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.SkipForDialect;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import static org.assertj.core.api.Assertions.assertThat;
/**
@ -89,9 +90,9 @@ public class ProposedGeneratedTests {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Proposed update to the legacy `Generated` annotation
@ProposedGenerated( timing = GenerationTiming.INSERT, sqlDefaultValue = "current_timestamp" )
@ProposedGenerated( timing = EventType.INSERT, sqlDefaultValue = "current_timestamp" )
public Instant createdAt;
@ProposedGenerated( timing = GenerationTiming.ALWAYS, sqlDefaultValue = "current_timestamp" )
@ProposedGenerated( timing = {EventType.INSERT, EventType.UPDATE}, sqlDefaultValue = "current_timestamp" )
public Instant updatedAt;
public GeneratedInstantEntity() {

View File

@ -6,10 +6,15 @@
*/
package org.hibernate.orm.test.mapping.generated.temporals;
import java.lang.reflect.Member;
import java.util.EnumSet;
import org.hibernate.dialect.Dialect;
import org.hibernate.generator.EventType;
import org.hibernate.generator.EventTypeSets;
import org.hibernate.generator.GeneratorCreationContext;
import org.hibernate.generator.OnExecutionGenerator;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.tuple.AnnotationValueGeneration;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.ValueGenerator;
/**
* Proposal for making `@GeneratedValueGeneration` work for update (they don't work in 5.x either)
@ -18,37 +23,32 @@ import org.hibernate.tuple.ValueGenerator;
*
* @author Steve Ebersole
*/
public class ProposedGeneratedValueGeneration implements AnnotationValueGeneration<ProposedGenerated> {
private GenerationTiming timing;
private String defaultValue;
public class ProposedGeneratedValueGeneration implements OnExecutionGenerator {
private final EnumSet<EventType> timing;
private final String defaultValue;
@Override
public void initialize(ProposedGenerated annotation, Class propertyType) {
timing = annotation.timing();
final String defaultValue = annotation.sqlDefaultValue();
this.defaultValue = StringHelper.isEmpty( defaultValue )
? null
: defaultValue;
public ProposedGeneratedValueGeneration(ProposedGenerated annotation, Member member, GeneratorCreationContext context) {
timing = EventTypeSets.fromArray( annotation.timing() );
defaultValue = StringHelper.nullIfEmpty( annotation.sqlDefaultValue() );
}
@Override
public GenerationTiming getGenerationTiming() {
public EnumSet<EventType> getEventTypes() {
return timing;
}
@Override
public ValueGenerator<?> getValueGenerator() {
return null;
}
@Override
public boolean referenceColumnInSql() {
public boolean referenceColumnsInSql(Dialect dialect) {
return defaultValue != null;
}
@Override
public String getDatabaseGeneratedReferencedColumnValue() {
return defaultValue;
public boolean writePropertyValue() {
return false;
}
@Override
public String[] getReferencedColumnValues(Dialect dialect) {
return new String[] { defaultValue };
}
}

View File

@ -12,7 +12,6 @@ import java.util.Date;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.query.Query;
import org.hibernate.type.StandardBasicTypes;
@ -195,12 +194,12 @@ public class MySQLTimestampPropertyTest {
private Date ts;
@Temporal(value = TemporalType.TIMESTAMP)
@Generated(value = GenerationTime.INSERT)
@Generated
@ColumnDefault(value = "CURRENT_TIMESTAMP(6)")
private Date tsColumnDefault;
@Temporal(value = TemporalType.TIMESTAMP)
@Generated(value = GenerationTime.INSERT)
@Generated
@Column(columnDefinition = "datetime(6) default NOW(6)")
private Date tsColumnDefinition;

View File

@ -12,7 +12,6 @@ import java.util.Date;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.query.Query;
@ -43,6 +42,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
*
* @author Gail Badner
*/
@SuppressWarnings("JUnitMalformedDeclaration")
@SkipForDialect(dialectClass = MySQLDialect.class, matchSubTypes = true, reason = "CURRENT_TIMESTAMP not supported as default value in MySQL")
@SkipForDialect(dialectClass = SybaseDialect.class, matchSubTypes = true, reason = "CURRENT_TIMESTAMP not supported as default value in Sybase")
@DomainModel(
@ -163,7 +163,7 @@ public class TimestampPropertyTest {
private Date ts;
@Temporal(value = TemporalType.TIMESTAMP)
@Generated(value = GenerationTime.INSERT)
@Generated
@ColumnDefault(value = "CURRENT_TIMESTAMP")
private Date tsColumnDefault;
}

View File

@ -6,28 +6,25 @@
*/
package org.hibernate.orm.test.version.sybase;
import org.hibernate.Session;
import org.hibernate.annotations.Generated;
import org.hibernate.dialect.SybaseASEDialect;
import org.hibernate.generator.EventType;
import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
import org.hibernate.type.descriptor.jdbc.VarbinaryJdbcType;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.Version;
import org.junit.Test;
import org.hibernate.Session;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.dialect.SybaseASEDialect;
import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
import org.hibernate.type.descriptor.jdbc.VarbinaryJdbcType;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
/**
@ -91,7 +88,7 @@ public class SybaseTimestampComparisonAnnotationsTest extends BaseCoreFunctional
private long id;
@Version
@Generated(GenerationTime.ALWAYS)
@Generated(event = { EventType.INSERT,EventType.UPDATE})
@Column(name = "ver", columnDefinition = "timestamp")
private byte[] version;

View File

@ -6,24 +6,23 @@
*/
package org.hibernate.orm.test.envers.integration.basic;
import org.hibernate.annotations.Generated;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.envers.Audited;
import org.hibernate.mapping.Table;
import org.hibernate.orm.test.envers.BaseEnversJPAFunctionalTestCase;
import org.hibernate.orm.test.envers.Priority;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
import org.junit.ComparisonFailure;
import org.junit.Test;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.envers.Audited;
import org.hibernate.orm.test.envers.BaseEnversJPAFunctionalTestCase;
import org.hibernate.orm.test.envers.Priority;
import org.hibernate.mapping.Table;
import org.junit.ComparisonFailure;
import org.junit.Test;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
import static org.hibernate.boot.model.naming.Identifier.toIdentifier;
import static org.hibernate.engine.jdbc.Size.DEFAULT_LENGTH;
import static org.hibernate.engine.jdbc.Size.DEFAULT_PRECISION;
@ -119,7 +118,7 @@ public class BasicTypeColumnDefinitionTest extends BaseEnversJPAFunctionalTestCa
@GeneratedValue
private Integer id;
@Generated(GenerationTime.INSERT)
@Generated
@Column(name = "caseNumber", columnDefinition = "integer not null auto_increment")
private Integer caseNumber;

View File

@ -6,15 +6,14 @@
*/
package org.hibernate.orm.test.envers.integration.generated;
import org.hibernate.annotations.Generated;
import org.hibernate.envers.Audited;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.envers.Audited;
/**
* @author Chris Cranford
*/
@ -27,7 +26,7 @@ public class SimpleEntity {
private String data;
@Generated(GenerationTime.INSERT)
@Generated
@Column(columnDefinition = "integer default 1")
private int caseNumberInsert;