From 72b548b912134abe1097b72df02bf7f8a5cb0b45 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Thu, 27 Aug 2020 14:34:35 +0100 Subject: [PATCH] MutationExecutor Add call to autoFlushIfRequired --- .../engine/spi/SessionDelegatorBaseImpl.java | 5 ++++ .../spi/SharedSessionContractImplementor.java | 11 +++++++++ .../org/hibernate/internal/SessionImpl.java | 7 ++---- .../internal/StatelessSessionImpl.java | 6 +++++ .../sqm/internal/SimpleDeleteQueryPlan.java | 8 ++++--- .../sqm/internal/SimpleInsertQueryPlan.java | 10 +++++--- .../sqm/internal/SimpleUpdateQueryPlan.java | 8 ++++--- .../idtable/ExecuteWithIdTableHelper.java | 1 - .../idtable/ExecuteWithoutIdTableHelper.java | 1 - .../spi/StandardSqlAstDeleteTranslator.java | 3 ++- .../hibernate/sql/ast/tree/cte/CteTable.java | 1 - .../sql/ast/tree/from/StandardTableGroup.java | 3 +-- .../StandardJdbcMutationExecutor.java | 12 ++++++---- .../collection/map/PersistentMapTest.java | 24 ++++++++++++------- 14 files changed, 67 insertions(+), 33 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionDelegatorBaseImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionDelegatorBaseImpl.java index 505ddfd97f..d965094b8f 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionDelegatorBaseImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/SessionDelegatorBaseImpl.java @@ -371,6 +371,11 @@ public class SessionDelegatorBaseImpl implements SessionImplementor { return delegate.getPersistenceContextInternal(); } + @Override + public boolean autoFlushIfRequired(Set querySpaces) throws HibernateException { + return delegate.autoFlushIfRequired( querySpaces ); + } + @Override public SessionEventListenerManager getEventListenerManager() { return delegate.getEventListenerManager(); diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/SharedSessionContractImplementor.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/SharedSessionContractImplementor.java index 07ebe1c77c..463b186aaf 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/SharedSessionContractImplementor.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/SharedSessionContractImplementor.java @@ -9,6 +9,7 @@ package org.hibernate.engine.spi; import java.io.Serializable; import java.sql.Connection; import java.util.List; +import java.util.Set; import java.util.UUID; import javax.persistence.FlushModeType; import javax.persistence.TransactionRequiredException; @@ -466,6 +467,16 @@ public interface SharedSessionContractImplementor */ PersistenceContext getPersistenceContextInternal(); + /** + * detect in-memory changes, determine if the changes are to tables + * named in the query and, if so, complete execution the flush + * + * @param querySpaces the tables named in the query. + * + * @return true if flush is required, false otherwise. + */ + boolean autoFlushIfRequired(Set querySpaces) throws HibernateException; + default boolean isEnforcingFetchGraph() { return false; } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java index 64f72c7920..b5c8a547c2 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java @@ -1288,11 +1288,8 @@ public class SessionImpl delayedAfterCompletion(); } - /** - * detect in-memory changes, determine if the changes are to tables - * named in the query and, if so, complete execution the flush - */ - protected boolean autoFlushIfRequired(Set querySpaces) throws HibernateException { + @Override + public boolean autoFlushIfRequired(Set querySpaces) throws HibernateException { checkOpen(); if ( !isTransactionInProgress() ) { // do not auto-flush while outside a transaction diff --git a/hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java index 44635f77ef..1da6fe8c23 100755 --- a/hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/StatelessSessionImpl.java @@ -8,6 +8,7 @@ package org.hibernate.internal; import java.io.Serializable; import java.sql.Connection; +import java.util.Set; import javax.transaction.SystemException; import org.hibernate.CacheMode; @@ -565,6 +566,11 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen return temporaryPersistenceContext; } + @Override + public boolean autoFlushIfRequired(Set querySpaces) throws HibernateException { + return false; + } + // @Override // public int executeNativeUpdate( // NativeSQLQuerySpecification nativeSQLQuerySpecification, diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SimpleDeleteQueryPlan.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SimpleDeleteQueryPlan.java index 424d367440..bfed5831bc 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SimpleDeleteQueryPlan.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SimpleDeleteQueryPlan.java @@ -12,6 +12,7 @@ import java.util.Map; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.MappingModelHelper; @@ -62,7 +63,8 @@ public class SimpleDeleteQueryPlan implements NonSelectQueryPlan { @Override public int executeUpdate(ExecutionContext executionContext) { - final SessionFactoryImplementor factory = executionContext.getSession().getFactory(); + final SharedSessionContractImplementor session = executionContext.getSession(); + final SessionFactoryImplementor factory = session.getFactory(); final JdbcServices jdbcServices = factory.getJdbcServices(); if ( jdbcDelete == null ) { @@ -98,7 +100,7 @@ public class SimpleDeleteQueryPlan implements NonSelectQueryPlan { jdbcParamsXref, factory.getDomainModel(), sqmInterpretation.getFromClauseAccess()::findTableGroup, - executionContext.getSession() + session ); jdbcDelete.bindFilterJdbcParameters( jdbcParameterBindings ); @@ -151,7 +153,7 @@ public class SimpleDeleteQueryPlan implements NonSelectQueryPlan { return jdbcServices.getJdbcMutationExecutor().execute( jdbcDelete, jdbcParameterBindings, - sql -> executionContext.getSession() + sql -> session .getJdbcCoordinator() .getStatementPreparer() .prepareStatement( sql ), diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SimpleInsertQueryPlan.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SimpleInsertQueryPlan.java index 43842518a4..8b7d10f939 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SimpleInsertQueryPlan.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SimpleInsertQueryPlan.java @@ -9,6 +9,7 @@ package org.hibernate.query.sqm.internal; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.query.spi.NonSelectQueryPlan; import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryParameterImplementor; @@ -48,7 +49,8 @@ public class SimpleInsertQueryPlan implements NonSelectQueryPlan { @Override public int executeUpdate(ExecutionContext executionContext) { - final SessionFactoryImplementor factory = executionContext.getSession().getFactory(); + final SharedSessionContractImplementor session = executionContext.getSession(); + final SessionFactoryImplementor factory = session.getFactory(); final JdbcServices jdbcServices = factory.getJdbcServices(); if ( jdbcInsert == null ) { @@ -87,13 +89,15 @@ public class SimpleInsertQueryPlan implements NonSelectQueryPlan { jdbcParamsXref, factory.getDomainModel(), tableGroupAccess::findTableGroup, - executionContext.getSession() + session ); + jdbcInsert.bindFilterJdbcParameters( jdbcParameterBindings ); + return jdbcServices.getJdbcMutationExecutor().execute( jdbcInsert, jdbcParameterBindings, - sql -> executionContext.getSession() + sql -> session .getJdbcCoordinator() .getStatementPreparer() .prepareStatement( sql ), diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SimpleUpdateQueryPlan.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SimpleUpdateQueryPlan.java index 37316b7cd8..30751585cc 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SimpleUpdateQueryPlan.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SimpleUpdateQueryPlan.java @@ -12,6 +12,7 @@ import java.util.Map; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.query.spi.NonSelectQueryPlan; import org.hibernate.query.spi.QueryEngine; import org.hibernate.query.spi.QueryParameterImplementor; @@ -48,7 +49,8 @@ public class SimpleUpdateQueryPlan implements NonSelectQueryPlan { @Override public int executeUpdate(ExecutionContext executionContext) { - final SessionFactoryImplementor factory = executionContext.getSession().getFactory(); + final SharedSessionContractImplementor session = executionContext.getSession(); + final SessionFactoryImplementor factory = session.getFactory(); final JdbcServices jdbcServices = factory.getJdbcServices(); if ( jdbcUpdate == null ) { @@ -87,14 +89,14 @@ public class SimpleUpdateQueryPlan implements NonSelectQueryPlan { jdbcParamsXref, factory.getDomainModel(), tableGroupAccess::findTableGroup, - executionContext.getSession() + session ); jdbcUpdate.bindFilterJdbcParameters( jdbcParameterBindings ); return jdbcServices.getJdbcMutationExecutor().execute( jdbcUpdate, jdbcParameterBindings, - sql -> executionContext.getSession() + sql -> session .getJdbcCoordinator() .getStatementPreparer() .prepareStatement( sql ), diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/ExecuteWithIdTableHelper.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/ExecuteWithIdTableHelper.java index 128ccbc362..a017c1a2b7 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/ExecuteWithIdTableHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/ExecuteWithIdTableHelper.java @@ -169,7 +169,6 @@ public final class ExecuteWithIdTableHelper { entityDescriptor, LockMode.NONE, idTableReference, - Collections.emptyList(), null, executionContext.getSession().getFactory() ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/ExecuteWithoutIdTableHelper.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/ExecuteWithoutIdTableHelper.java index 3bbd6b778c..0e534d0e60 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/ExecuteWithoutIdTableHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/ExecuteWithoutIdTableHelper.java @@ -45,7 +45,6 @@ public final class ExecuteWithoutIdTableHelper { rootEntityPersister, LockMode.PESSIMISTIC_WRITE, rootTableReference, - Collections.emptyList(), null, sessionFactory ); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/StandardSqlAstDeleteTranslator.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/StandardSqlAstDeleteTranslator.java index 287d89565b..50be972a48 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/StandardSqlAstDeleteTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/StandardSqlAstDeleteTranslator.java @@ -30,7 +30,8 @@ public class StandardSqlAstDeleteTranslator extends AbstractSqlAstTranslator imp @Override public JdbcDelete translate(DeleteStatement sqlAst) { appendSql( "delete from " ); - appendSql( sqlAst.getTargetTable().getTableExpression() ); + + renderTableReference( sqlAst.getTargetTable() ); if ( sqlAst.getRestriction() != null ) { appendSql( " where " ); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/cte/CteTable.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/cte/CteTable.java index d04960a93a..aaa633d1b1 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/cte/CteTable.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/cte/CteTable.java @@ -83,7 +83,6 @@ public class CteTable { null, LockMode.NONE, tableValueConstructorReference, - Collections.emptyList(), null, sessionFactory ); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/StandardTableGroup.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/StandardTableGroup.java index 75c4c45695..f6fb65417d 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/StandardTableGroup.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/StandardTableGroup.java @@ -33,12 +33,11 @@ public class StandardTableGroup extends AbstractTableGroup { TableGroupProducer tableGroupProducer, LockMode lockMode, TableReference primaryTableReference, - List tableJoins, SqlAliasBase sqlAliasBase, SessionFactoryImplementor sessionFactory) { super( navigablePath, tableGroupProducer, lockMode, sqlAliasBase, sessionFactory ); this.primaryTableReference = primaryTableReference; - this.tableJoins = tableJoins; + this.tableJoins = Collections.emptyList(); this.tableReferenceJoinCreator = null; this.tableReferenceJoinNameChecker = s -> { for ( int i = 0; i < tableJoins.size(); i++ ) { diff --git a/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/StandardJdbcMutationExecutor.java b/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/StandardJdbcMutationExecutor.java index 0da561a2b8..d21dae7277 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/StandardJdbcMutationExecutor.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/StandardJdbcMutationExecutor.java @@ -12,6 +12,7 @@ import java.util.function.BiConsumer; import java.util.function.Function; import org.hibernate.engine.jdbc.spi.JdbcServices; +import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor; import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.JdbcMutation; @@ -35,11 +36,14 @@ public class StandardJdbcMutationExecutor implements JdbcMutationExecutor { Function statementCreator, BiConsumer expectationCheck, ExecutionContext executionContext) { - final LogicalConnectionImplementor logicalConnection = executionContext.getSession() + final SharedSessionContractImplementor session = executionContext.getSession(); + session.autoFlushIfRequired( jdbcMutation.getAffectedTableNames() ); + + final LogicalConnectionImplementor logicalConnection = session .getJdbcCoordinator() .getLogicalConnection(); - final JdbcServices jdbcServices = executionContext.getSession().getJdbcServices(); + final JdbcServices jdbcServices = session.getJdbcServices(); final String sql = jdbcMutation.getSql(); try { @@ -63,14 +67,14 @@ public class StandardJdbcMutationExecutor implements JdbcMutationExecutor { ); } - executionContext.getSession().getEventListenerManager().jdbcExecuteStatementStart(); + session.getEventListenerManager().jdbcExecuteStatementStart(); try { int rows = preparedStatement.executeUpdate(); expectationCheck.accept( rows, preparedStatement ); return rows; } finally { - executionContext.getSession().getEventListenerManager().jdbcExecuteStatementEnd(); + session.getEventListenerManager().jdbcExecuteStatementEnd(); } } finally { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/collection/map/PersistentMapTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/collection/map/PersistentMapTest.java index 7033a13cd0..a6c6f7f4d5 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/collection/map/PersistentMapTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/collection/map/PersistentMapTest.java @@ -187,6 +187,7 @@ public class PersistentMapTest { List list = q.list(); assertEquals( 1, list.size() ); + session.delete( list.get( 0 ) ); } ); } @@ -209,11 +210,11 @@ public class PersistentMapTest { session.beginTransaction(); - user = session.get( User.class, 1 ); + user = session.get( User.class, user.id ); user.userDatas.clear(); session.update( user ); - Query q = session.createQuery( "DELETE FROM " + UserData.class.getName() + " d WHERE d.user = :user" ); + Query q = session.createQuery( "DELETE FROM " + UserData.class.getName() + " d WHERE d.user = :user" ); q.setParameter( "user", user ); q.executeUpdate(); @@ -361,30 +362,31 @@ select @Test @TestForIssue(jiraKey = "HHH-11038") public void testMapKeyColumnNonInsertableNonUpdatableUnidirOneToMany(SessionFactoryScope scope) { - User user = new User(); - scope.inTransaction( + + Integer userId = scope.fromTransaction( session -> { + User user = new User(); Detail detail = new Detail(); detail.description = "desc"; detail.detailType = "trivial"; user.details.put( detail.detailType, detail ); session.persist( user ); + return user.getId(); } ); scope.inTransaction( session -> { - User u = session.get( User.class, user.id ); - u.details.clear(); + User user = session.get( User.class, userId); + user.details.clear(); } ); scope.inTransaction( session -> { - User u = session.get( User.class, user.id ); - session.delete( u ); + User user = session.get( User.class, userId ); + session.delete( user ); session.createQuery( "delete from " + User.class.getName() ).executeUpdate(); - } ); } @@ -408,6 +410,10 @@ select @MapKeyColumn(name = "detailType", insertable = false, updatable = false) @JoinColumn private Map details = new HashMap<>(); + + public Integer getId() { + return id; + } } @Entity