2.3.18. Generated properties

<div class="paragraph">

Generated properties are properties that have their values generated by the database.
Typically, Hibernate applications needed to `refresh` objects that contain any properties for which the database was generating values.
Marking properties as generated, however, lets the application delegate this responsibility to Hibernate.
When Hibernate issues an SQL INSERT or UPDATE for an entity that has defined generated properties, it immediately issues a select to retrieve the generated values.

</div>
<div class="paragraph">

Properties marked as generated must additionally be _non-insertable_ and _non-updateable_.
Only `@Version` and `@Basic` types can be marked as generated.

</div>
<div class="dlist">
<dl>
<dt class="hdlist1">`never` (the default)</dt>
<dd>

the given property value is not generated within the database.

</dd>
<dt class="hdlist1">`insert`</dt>
<dd>

the given property value is generated on insert, but is not regenerated on subsequent updates. Properties like _creationTimestamp_ fall into this category.

</dd>
<dt class="hdlist1">`always`</dt>
<dd>

the property value is generated both on insert and on update.

</dd>
</dl>
</div>
<div class="paragraph">

To mark a property as generated, use The Hibernate specific `@Generated` annotation.

</div>
<div class="sect4">

##### `@CreationTimestamp` annotation

<div class="paragraph">

The `@CreationTimestamp` annotation instructs Hibernate to set the annotated entity attribute with the current timestamp value of the JVM
when the entity is being persisted.

</div>
<div class="paragraph">

The supported property types are:

</div>
<div class="ulist">
  • java.util.Date
  • java.util.Calendar
  • java.sql.Date
  • java.sql.Time
  • java.sql.Timestamp </div>

    Example 55. `@CreationTimestamp` mapping example
    `@Entity(name = "Event")
    public static class Event {

    @Id
    @GeneratedValue
    private Long id;
    
    @Column(name = "`timestamp`")
    @CreationTimestamp
    private Date timestamp;
    
    public Event() {}
    
    public Long getId() {
        return id;
    }
    
    public Date getTimestamp() {
        return timestamp;
    }
    

    }`</pre> </div> </div> </div> </div>

    When the Event entity is persisted, Hibernate is going to populate the underlying timestamp column with the current JVM timestamp value:

    </div>

    Example 56. `@CreationTimestamp` persist example
    `Event dateEvent = new Event( );
    entityManager.persist( dateEvent );`
    </div>
    `INSERT INTO Event("timestamp", id)
    VALUES (?, ?)

    -- binding parameter [1] as [TIMESTAMP] - [Tue Nov 15 16:24:20 EET 2016] -- binding parameter [2] as [BIGINT] - [1]`</pre> </div> </div> </div> </div> </div>

    @ValueGenerationType meta-annotation

    Hibernate 4.3 introduced the @ValueGenerationType meta-annotation, which is a new approach to declaring generated attributes or customizing generators.

    </div>

    @Generated has been retrofitted to use the @ValueGenerationType meta-annotation. But @ValueGenerationType exposes more features than what @Generated currently supports, and, to leverage some of those features, you’d simply wire up a new generator annotation.

    </div>

    As you’ll see in the following examples, the @ValueGenerationType meta-annotation is used when declaring the custom annotation used to mark the entity properties that need a specific generation strategy. The actual generation logic must be implemented in class that implements the AnnotationValueGeneration interface.

    </div>

    Database-generated values

    For example, let’s say we want the timestamps to be generated by calls to the standard ANSI SQL function current_timestamp (rather than triggers or DEFAULT values):

    </div>

    Example 57. A `ValueGenerationType` mapping for database generation
    `@Entity(name = "Event")
    public static class Event {

    @Id
    @GeneratedValue
    private Long id;
    
    @Column(name = "`timestamp`")
    @FunctionCreationTimestamp
    private Date timestamp;
    
    public Event() {}
    
    public Long getId() {
        return id;
    }
    
    public Date getTimestamp() {
        return timestamp;
    }
    

    }

    @ValueGenerationType(generatedBy = FunctionCreationValueGeneration.class) @Retention(RetentionPolicy.RUNTIME) public @interface FunctionCreationTimestamp {}

    public static class FunctionCreationValueGeneration

        implements AnnotationValueGeneration&lt;FunctionCreationTimestamp&gt; {
    
    @Override
    public void initialize(FunctionCreationTimestamp annotation, Class&lt;?&gt; 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&lt;?&gt; getValueGenerator() {
        return null;
    }
    
    /**
     * Returns true because the value is generated by the database.
     * @return true
     */
    public boolean referenceColumnInSql() {
        return true;
    }
    
    /**
     * Returns the database-generated value
     * @return database-generated value
     */
    public String getDatabaseGeneratedReferencedColumnValue() {
        return "current_timestamp";
    }
    

    }`</pre> </div> </div> </div> </div>

    When persisting an Event entity, Hibernate generates the following SQL statement:

    </div>

    `INSERT INTO Event ("timestamp", id)
    VALUES (current_timestamp, 1)`
    </div> </div> </div>

    As you can see, the current_timestamp value was used for assigning the timestamp column value.

    </div> </div>

    In-memory-generated values

    If the timestamp value needs to be generated in-memory, the following mapping must be used instead:

    </div>

    Example 58. A `ValueGenerationType` mapping for in-memory value generation
    `@Entity(name = "Event")
    public static class Event {

    @Id
    @GeneratedValue
    private Long id;
    
    @Column(name = "`timestamp`")
    @FunctionCreationTimestamp
    private Date timestamp;
    
    public Event() {}
    
    public Long getId() {
        return id;
    }
    
    public Date getTimestamp() {
        return timestamp;
    }
    

    }

    @ValueGenerationType(generatedBy = FunctionCreationValueGeneration.class) @Retention(RetentionPolicy.RUNTIME) public @interface FunctionCreationTimestamp {}

    public static class FunctionCreationValueGeneration

        implements AnnotationValueGeneration&lt;FunctionCreationTimestamp&gt; {
    
    @Override
    public void initialize(FunctionCreationTimestamp annotation, Class&lt;?&gt; 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&lt;?&gt; getValueGenerator() {
        return (session, owner) -&gt; 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;
    }
    

    }`</pre> </div> </div> </div> </div>

    When persisting an Event entity, Hibernate generates the following SQL statement:

    </div>

    `INSERT INTO Event ("timestamp", id)
    VALUES ('Tue Mar 01 10:58:18 EET 2016', 1)`
    </div> </div> </div>

    As you can see, the new Date() object value was used for assigning the timestamp column value.

    </div> </div> </div> </div>

results matching ""

    No results matching ""