Hibernate 6.2 Final

Posted by    |       Hibernate ORM Releases

Hibernate ORM 6.2.0 Final has just been released.

In many ways, this release marks the final step for the major forcus of 6.x centered around changing how Hibernate generates SQL. Many improvements in this release, as well as 6.0 and 6.1, have been implemented on top of this SQL AST work. As of 6.0 and 6.1, Hibernate used this SQL AST for loading state from the database. With 6.2, Hibernate also uses SQL AST for writing to the database.

Support for Structured SQL Types

Hibernate now supports structured SQL types including struct, XML and JSON. Christian wrote a blog post about this support which covers the details. See also the Aggregate embeddable mapping and @Struct aggregate embeddable mapping User Guide sections.

Support for Java records

Hibernate now support the mapping of Java records as embeddables. E.g.

public record Name(
        String firstName;
        String lastName;
) {}

even combined with Support for Structured SQL Types to persist to a struct!

@Struct(name = "Name")
public record Name(
        String firstName;
        String lastName;
) {}

See the @Struct aggregate embeddable mapping User Guide section for more details.

Unified generated value support

Support for generated persisted values has been has been unified to use the same contracts, whether for identifiers or other basic values, based on org.hibernate.annotations.Generated, org.hibernate.annotations.ValueGenerationType and org.hibernate.generator.Generator. E.g.

@Generated( GenerationTime.INSERT )
@ColumnDefault( "CURRENT_TIMESTAMP" )
private Date createdDate;


@Target( { ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE } )
@ValueGenerationType( generatedBy = UuidValueGeneration.class )
public @interface GeneratedUuidValue {
        GenerationTiming timing();

public static class UuidValueGeneration implements BeforeExecutionGenerator {...}


@GeneratedUuidValue( timing = GenerationTiming.INSERT )
public UUID createdUuid;

See the Generated properties User Guide section for details.

Database Partitions

Hibernate now supports database partitions as a first-class citizen using org.hibernate.annotations.PartitionKey to map the parition column. E.g.

public static class User {
    @Id private Integer id;
    @PartitionKey private String region;

See the Paritioning User Guide section for details.

SQL MERGE for "optional table" updates

Building on top of the SQL AST, Hibernate can now use the SQL MERGE command to handle updates against optional tables.

An update to an optional table will have one of 3 ultimate outcomes:

  1. if there is no corresponding row already in the table, insert the row

  2. else if all the new "value" columns are null, delete the row

  3. else update the row

The legacy behavior was to just do these if-checks ourselves at runtime and execute the insert, update and delete statements individually. The MERGE command allows that to happen more efficiently in a single JDBC call.

Currently this is supported on:

The fall back is to just use the legacy behavior.

Proprietary SQL types

Dealing with certain SQL types requires access to JDBC driver specific classes in order to properly read and write values of that type. In some environments (various containers, e.g.), those classes are not available to Hibernate.

Hibernate better handles these situations now when it can, usually based on casts to more standardized types. For example, we might read a JSON value from a ResultSet as a String by wrapping the JSON expression in a cast function.


For additional details, see:

See the website for getting in touch with us.

Back to top