From c3c3c16a659f625c863be6514bfe9db7df9b4d30 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Wed, 1 Nov 2023 23:01:23 -0500 Subject: [PATCH] HHH-17377 - Migrate to JPA 3.2 https://hibernate.atlassian.net/browse/HHH-17377 Test compilation success!! 95 test failures next --- .../criteria/HibernateCriteriaBuilder.java | 31 +++++- migration-guide.adoc | 101 +++--------------- 2 files changed, 44 insertions(+), 88 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/query/criteria/HibernateCriteriaBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/criteria/HibernateCriteriaBuilder.java index 4c99b04edc..bf15aed2da 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/criteria/HibernateCriteriaBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/criteria/HibernateCriteriaBuilder.java @@ -24,7 +24,11 @@ import org.hibernate.Incubating; import org.hibernate.query.NullPrecedence; import org.hibernate.query.SortDirection; import org.hibernate.query.sqm.FrameKind; +import org.hibernate.query.sqm.SetOperator; +import org.hibernate.query.sqm.SqmQuerySource; import org.hibernate.query.sqm.TemporalUnit; +import org.hibernate.query.sqm.tree.select.SqmQueryGroup; +import org.hibernate.query.sqm.tree.select.SqmSelectStatement; import jakarta.persistence.Tuple; import jakarta.persistence.criteria.AbstractQuery; @@ -183,16 +187,39 @@ public interface HibernateCriteriaBuilder extends CriteriaBuilder { @Override JpaCriteriaQuery union(CriteriaQuery left, CriteriaQuery right); + @SuppressWarnings({ "rawtypes", "unchecked" }) @Override default JpaCriteriaQuery unionAll(CriteriaQuery left, CriteriaQuery right) { - return null; + // for now at least... + assert left instanceof SqmSelectStatement; + final SqmSelectStatement leftSqm = (SqmSelectStatement) left; + final SqmSelectStatement rightSqm = (SqmSelectStatement) right; + + + // SqmQueryGroup is the UNION ALL between the two + final SqmQueryGroup sqmQueryGroup = new SqmQueryGroup( + leftSqm.nodeBuilder(), + SetOperator.UNION_ALL, + List.of( leftSqm.getQueryPart(), rightSqm.getQueryPart() ) + ); + + final SqmSelectStatement sqmSelectStatement = new SqmSelectStatement<>( + leftSqm.getResultType(), + SqmQuerySource.CRITERIA, + leftSqm.nodeBuilder() + ); + sqmSelectStatement.setQueryPart( sqmQueryGroup ); + return sqmSelectStatement; } default JpaSubQuery union(Subquery query1, Subquery... queries) { return union( false, query1, queries ); } - JpaSubQuery union(boolean all, Subquery query1, Subquery... queries); + default JpaSubQuery union(boolean all, Subquery query1, Subquery... queries) { + assert query1 instanceof SqmSelectStatement; + return null; + } @Override JpaCriteriaQuery intersect(CriteriaQuery left, CriteriaQuery right); diff --git a/migration-guide.adoc b/migration-guide.adoc index 039f6d32ab..238b047b52 100644 --- a/migration-guide.adoc +++ b/migration-guide.adoc @@ -30,95 +30,24 @@ earlier versions, see any other pertinent migration guides as well. * JPA has added support in its Graph API for things Hibernate has supported for some time. Some of those are collisions requiring changes to the Hibernate API. -[[oracle-implicit-array-types]] -== Oracle implicit array types -The names for implicitly created array types on Oracle have slightly changed to account for converted types. -Previously, the naming of implicit array types was only using the Java type simple name which could conflict -when the same Java type is used with different JDBC type codes or converters. -To avoid name clashes, the naming of implicitly created array types now also includes -the preferred Java type simple name of the JDBC type in case the preferred Java type differs from the field type. -In case of converted types, the converter Java class simple name is used instead. +[[cleanup]] +== Some Cleanup -The array type for a persistent property of type `BigInteger[]` was previously `BigIntegerArray` -and would now be `BigIntegerBigDecimalArray`, because the preferred Java type for the `NUMERIC`/`DECIMAL` JDBC type is `BigDecimal`. -To specify a custom array type name, annotate the persistent property with `@Column(columnDefinition = "BigIntegerArray")`. +* Removed `SqmQualifiedJoin`. All joins are qualified. -[[user-defined-type]] -== Changes to `UserDefinedType` -`UserDefinedType` was renamed to `UserDefinedObjectType` and everything except access to column information -was abstracted in a new interface named `UserDefinedType`. This was done to allow modelling dependencies between -named arrays, modeled as `UserDefinedArrayType` extending the new `UserDefinedType` interface, -and `UserDefinedObjectType` i.e. arrays of structs. +[[todo]] +== Todos -`UserDefinedType` was not explicitly annotated with `@Incubating` before, -but it was introduced for the incubating `@Struct` feature in ORM 6.2, -which made it effectively incubating as well. To make this more clear, -the types were now also explicitly marked as `@Incubating`. +NOTE:: Look for `// todo (jpa 3.2)` -The changes affect users which previously queried or created `UserDefinedType` in a `Namespace`. -Methods that return or operate on `UserDefinedType` have been marked as `@Incubating` -to make it clear that these contracts might still evolve. - -Another change is to the already incubating `ColumnOrderingStrategy`, -where the argument type of `orderUserDefinedTypeColumns` was changed from `UserDefinedType` to `UserDefinedObjectType`. - -[[array-contains-array-deprecation]] -== Subset check for arrays to use `array_includes` - -Support for `array_contains()` to accept an array as element argument is deprecated and will emit a warning. -To check if an array is a subset of another array, use the `array_includes()` function, -or the new `INCLUDES` predicate i.e. `array INCLUDES subarray`. - -[[merge-versioned-deleted]] -== Merge versioned entity when row is deleted -Previously, merging a detached entity resulted in a SQL `insert` whenever there was no matching row in the database (for example, if the object had been deleted in another transaction). -This behavior was unexpected and violated the rules of optimistic locking. - -An `OptimisticLockException` is now thrown when it is possible to determine that an entity is definitely detached, but there is no matching row. -For this determination to be possible, the entity must have either: - -- a generated `@Id` field, or -- a non-primitive `@Version` field. - -For entities which have neither, it's impossible to distinguish a new instance from a deleted detached instance, and there is no change from the previous behavior. - -[[mapped-superclass-embeddable]] -== Explicit validation of annotated class types -Hibernate has always been lax when it comes to `@Embedded` property types, allowing classes not annotated with `@Embeddable` to still work correctly. This is a nice feature that enables you to map your attributes to classes that you cannot modify to add the annotation, and will continue to work as expected in the future. - -One consequence of this, though, was letting you use both `@MappedSuperlcass` and `@Embeddable` on the same annotated class as a workaround to enable having subclasses annotated as `@Embeddable` and still use both types in embedded attribute mappings. This has never been officially supported, with things like the JPA static metamodel not working as expected, and starting from 6.6 we will explicitly validate that mapped classes are annotated _either_ `@MappedSuperclass` _or_ `@Embeddable`, _or_ `@Entity`. - -Extending a `@MappedSuperclass` annotated class with an `@Embeddable` type is still supported, but we suggest keeping the two annotated class types separate. You can now also take advantage of explicit discriminator column based <>. - -[[embeddable-inheritance]] -== Discriminator-based embeddable inheritance - -ORM 6.6 introduced support for `@Embeddable` type inheritance, always relying on a discriminator column stored within the entity mappings that contain the polymorphic `@Embedded` property of that type. -Note that this functionality will be automatically enabled for all `@Embedded` properties whose type (Java class) is extended by subclasses annotated with `@Embeddable`. Previously, `@Embeddable`-annotated subtypes were always ignored, so this should not impact your mappings, unless you were using the "workaround" described in the <>. - -With embeddable inheritance, we also enabled the `type()` and `treat()` functions to work with embeddable-typed paths. -As a consequence, the `org.hibernate.query.sqm.tree.domain.SqmTreatedPath#getTreatTarget()` method will now return a generic `ManagedDomainType` object, -which could in turn be an `EntityDomainType` (as it was before) or also an `EmbeddableDomainType` instance. - -You can find more details about embeddable inheritance in the dedicated link:{userGuideBase}#embeddable-inheritance[user guide chapter]. - -[[h2-dialect]] -== H2 database and bulk mutation strategy - -With ORM 6.6 when a bulk mutation involves multiple tables, H2 dialect will make use of global temporary tables instead of local ones. - -[[criteria-query]] -== Criteria: `jakarta.persistence.criteria.Expression#as(Class)` - -The behaviour of `jakarta.persistence.criteria.Expression#as(Class)` has been changed to conform to the Jakarta Persistence specification. - -`Expression.as()` doesn’t do anymore a real type conversions, it’s just an unsafe typecast on the Expression object itself. - -In order to perform an actual typecast, `org.hibernate.query.criteria.JpaExpression#cast(Class)` can be used. - -E.g. -``` -( (JpaExpression) from.get( "theInt" ) ).cast( String.class ) -``` +* Deprecate `SqmQualifiedJoin` in 6.x +* {@linkplain SqmCrossJoin} and its offspring are largely de-typed to account + for {@linkplain SqmCrossJoin} having only one type argument for the right-hand + side. To properly handle the type parameters in the hierarchy we need to change this to + accept type parameter for the left-handle side as well - breaking change. +* The changes in `jakarta.persistence.EntityManager#createNativeQuery(java.lang.String, java.lang.Class)` are really unfortunate. + Previously that signature was `(java.lang.String, java.lang.Class)` and our override of that was able to be + ` NativeQuery createNativeQuery(String sqlString, Class resultClass)`. JPA adding that wildcard means our + override is no longer valid. I had to change that to `` \ No newline at end of file