HHH-16138 Add documentation for joins in UPDATE/DELETE

This commit is contained in:
Christian Beikov 2023-12-21 13:58:46 +01:00
parent 78f1be6fa1
commit 22e5fe06ae
5 changed files with 49 additions and 4 deletions

View File

@ -232,9 +232,22 @@ include::{example-dir-hql}/../batch/BatchTests.java[tags=batch-bulk-hql-update-v
Update statements are polymorphic, and affect mapped subclasses of the given entity class. Update statements are polymorphic, and affect mapped subclasses of the given entity class.
[IMPORTANT] An `update` statement may use implicit or explicit joins. Beware that if joins lead to row duplications,
e.g. when joining the target row against a non-unique column,
it is undefined which row is updated or whether an error is thrown.
[[hql-update-join-example]]
//.Example update join queries
==== ====
No `update` or `delete` statement may have an implicit (or explicit) join. [source, JAVA, indent=0]
----
include::{example-dir-hql}/../query/hql/UpdateJoinTests.java[tags=hql-update-join-example]
----
====
[NOTE]
====
With JPA compliance enabled, `update` or `delete` statement may not have an implicit (or explicit) join.
==== ====
[[hql-delete]] [[hql-delete]]
@ -257,6 +270,22 @@ The integer value returned by `executeUpdate()` indicates the number of entity i
Delete statements are polymorphic, and affect mapped subclasses of the given entity class. Delete statements are polymorphic, and affect mapped subclasses of the given entity class.
A `delete` statement may use implicit or explicit joins.
[[hql-delete-join-example]]
//.Example delete join queries
====
[source, JAVA, indent=0]
----
include::{example-dir-hql}/../query/hql/DeleteJoinTests.java[tags=hql-delete-join-example]
----
====
[NOTE]
====
With JPA compliance enabled, `update` or `delete` statement may not have an implicit (or explicit) join.
====
[[hql-insert]] [[hql-insert]]
==== Insert statements ==== Insert statements

View File

@ -1,2 +1,8 @@
deleteStatement deleteStatement
: "DELETE" "FROM"? targetEntity whereClause? : "DELETE" "FROM"? entityWithJoins whereClause?
entityWithJoins
: fromRoot (join | crossJoin | jpaCollectionJoin)*
fromRoot
: entityName variable?

View File

@ -1,5 +1,11 @@
updateStatement updateStatement
: "UPDATE" "VERSIONED"? targetEntity setClause whereClause? : "UPDATE" "VERSIONED"? entityWithJoins setClause whereClause?
entityWithJoins
: fromRoot (join | crossJoin | jpaCollectionJoin)*
fromRoot
: entityName variable?
targetEntity targetEntity
: entityName variable? : entityName variable?

View File

@ -63,10 +63,12 @@ public class DeleteJoinTests {
public void testDeleteWithJoin(SessionFactoryScope scope) { public void testDeleteWithJoin(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
//tag::hql-delete-join-example[]
int updated = session.createMutationQuery( int updated = session.createMutationQuery(
"delete from BasicEntity b left join Contact c on b.id = c.id " + "delete from BasicEntity b left join Contact c on b.id = c.id " +
"where c.id is not null" "where c.id is not null"
).executeUpdate(); ).executeUpdate();
//end::hql-delete-join-example[]
assertEquals( 1, updated ); assertEquals( 1, updated );
assertNull( session.find( BasicEntity.class, 1 ) ); assertNull( session.find( BasicEntity.class, 1 ) );
} }

View File

@ -62,11 +62,13 @@ public class UpdateJoinTests {
public void testUpdateWithJoin(SessionFactoryScope scope) { public void testUpdateWithJoin(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
//tag::hql-update-join-example[]
int updated = session.createMutationQuery( int updated = session.createMutationQuery(
"update BasicEntity b left join Contact c on b.id = c.id " + "update BasicEntity b left join Contact c on b.id = c.id " +
"set b.data = c.name.first " + "set b.data = c.name.first " +
"where c.id is not null" "where c.id is not null"
).executeUpdate(); ).executeUpdate();
//end::hql-update-join-example[]
assertEquals( 1, updated ); assertEquals( 1, updated );
final BasicEntity basicEntity = session.find( BasicEntity.class, 1 ); final BasicEntity basicEntity = session.find( BasicEntity.class, 1 );
assertEquals( "A", basicEntity.getData() ); assertEquals( "A", basicEntity.getData() );