HHH-18186 - Remove @GeneratorType
HHH-18188 - Remove GenerationTime and its uses
This commit is contained in:
parent
f63e7cb1ac
commit
2b6f4b5ff9
|
@ -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;
|
||||
}
|
||||
----
|
||||
====
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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}
|
||||
|
|
|
@ -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() ) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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() };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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[]
|
||||
|
|
|
@ -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" };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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[]
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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[]
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -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[]
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue