Fix readOnly value and Query#scroll()

This commit is contained in:
Andrea Boriero 2021-11-28 17:09:35 +01:00 committed by Andrea Boriero
parent 0fbfc30eaa
commit b4cfe7e54a
22 changed files with 1097 additions and 715 deletions

View File

@ -18,6 +18,7 @@ import java.util.stream.Stream;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
import org.hibernate.ScrollMode; import org.hibernate.ScrollMode;
import org.hibernate.cache.spi.QueryKey; import org.hibernate.cache.spi.QueryKey;
@ -25,11 +26,17 @@ import org.hibernate.cache.spi.QueryResultsCache;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.graph.spi.AppliedGraph;
import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.query.Limit;
import org.hibernate.query.ResultListTransformer;
import org.hibernate.query.TupleTransformer; import org.hibernate.query.TupleTransformer;
import org.hibernate.query.internal.ScrollableResultsIterator; import org.hibernate.query.internal.ScrollableResultsIterator;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.spi.ScrollableResultsImplementor; import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.sql.exec.SqlExecLogger; import org.hibernate.sql.exec.SqlExecLogger;
import org.hibernate.sql.exec.spi.Callback;
import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcParameterBindings; import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcSelect; import org.hibernate.sql.exec.spi.JdbcSelect;
@ -58,6 +65,9 @@ import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@ -104,7 +114,7 @@ public class JdbcSelectExecutorStandardImpl implements JdbcSelectExecutor {
RowTransformer<R> rowTransformer) { RowTransformer<R> rowTransformer) {
final SharedSessionContractImplementor session = executionContext.getSession(); final SharedSessionContractImplementor session = executionContext.getSession();
session.autoFlushIfRequired( jdbcSelect.getAffectedTableNames() ); session.autoFlushIfRequired( jdbcSelect.getAffectedTableNames() );
return executeQuery( return executeQueryScroll(
jdbcSelect, jdbcSelect,
jdbcParameterBindings, jdbcParameterBindings,
executionContext, executionContext,
@ -169,6 +179,150 @@ public class JdbcSelectExecutorStandardImpl implements JdbcSelectExecutor {
} }
} }
} }
private <T, R> T executeQueryScroll(
JdbcSelect jdbcSelect,
JdbcParameterBindings jdbcParameterBindings,
ExecutionContext executionContext,
RowTransformer<R> rowTransformer,
Function<String, PreparedStatement> statementCreator,
ResultsConsumer<T, R> resultsConsumer) {
return doExecuteQuery(
jdbcSelect,
jdbcParameterBindings,
getScrollContext( executionContext, executionContext.getSession().getPersistenceContext() ),
rowTransformer,
statementCreator,
resultsConsumer
);
}
/*
When `Query#scroll()` is call the query is not executed immediately, a new ExecutionContext with the values of the `persistenceContext.isDefaultReadOnly()` and of the `queryOptions.isReadOnly()`
set at the moment of the Query#scroll() call is created in order to use it when the query will be executed.
*/
private ExecutionContext getScrollContext(ExecutionContext context, PersistenceContext persistenceContext) {
final QueryOptions queryOptions = context.getQueryOptions();
final Boolean readOnly;
if ( queryOptions.isReadOnly() == null ) {
readOnly = persistenceContext.isDefaultReadOnly();
}
else {
readOnly = queryOptions.isReadOnly();
}
final Integer timeout = queryOptions.getTimeout();
final FlushMode flushMode = queryOptions.getFlushMode();
final AppliedGraph appliedGraph = queryOptions.getAppliedGraph();
final TupleTransformer tupleTransformer = queryOptions.getTupleTransformer();
final ResultListTransformer resultListTransformer = queryOptions.getResultListTransformer();
final Boolean resultCachingEnabled = queryOptions.isResultCachingEnabled();
final CacheRetrieveMode cacheRetrieveMode = queryOptions.getCacheRetrieveMode();
final CacheStoreMode cacheStoreMode = queryOptions.getCacheStoreMode();
final String resultCacheRegionName = queryOptions.getResultCacheRegionName();
final LockOptions lockOptions = queryOptions.getLockOptions();
final String comment = queryOptions.getComment();
final List<String> databaseHints = queryOptions.getDatabaseHints();
final Integer fetchSize = queryOptions.getFetchSize();
final Limit limit = queryOptions.getLimit();
return new ExecutionContext() {
@Override
public QueryOptions getQueryOptions() {
return new QueryOptions() {
@Override
public Integer getTimeout() {
return timeout;
}
@Override
public FlushMode getFlushMode() {
return flushMode;
}
@Override
public Boolean isReadOnly() {
return readOnly;
}
@Override
public AppliedGraph getAppliedGraph() {
return appliedGraph;
}
@Override
public TupleTransformer getTupleTransformer() {
return tupleTransformer;
}
@Override
public ResultListTransformer getResultListTransformer() {
return resultListTransformer;
}
@Override
public Boolean isResultCachingEnabled() {
return resultCachingEnabled;
}
@Override
public CacheRetrieveMode getCacheRetrieveMode() {
return cacheRetrieveMode;
}
@Override
public CacheStoreMode getCacheStoreMode() {
return cacheStoreMode;
}
@Override
public String getResultCacheRegionName() {
return resultCacheRegionName;
}
@Override
public LockOptions getLockOptions() {
return lockOptions;
}
@Override
public String getComment() {
return comment;
}
@Override
public List<String> getDatabaseHints() {
return databaseHints;
}
@Override
public Integer getFetchSize() {
return fetchSize;
}
@Override
public Limit getLimit() {
return limit;
}
};
}
@Override
public QueryParameterBindings getQueryParameterBindings() {
return context.getQueryParameterBindings();
}
@Override
public Callback getCallback() {
return context.getCallback();
}
@Override
public SharedSessionContractImplementor getSession() {
return context.getSession();
}
};
}
private <T, R> T doExecuteQuery( private <T, R> T doExecuteQuery(
JdbcSelect jdbcSelect, JdbcSelect jdbcSelect,
JdbcParameterBindings jdbcParameterBindings, JdbcParameterBindings jdbcParameterBindings,

View File

@ -872,13 +872,8 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
private boolean isReadOnly( private boolean isReadOnly(
RowProcessingState rowProcessingState, RowProcessingState rowProcessingState,
SharedSessionContractImplementor persistenceContext) { SharedSessionContractImplementor persistenceContext) {
if ( persistenceContext.isDefaultReadOnly() ) { final Boolean readOnly = rowProcessingState.getQueryOptions().isReadOnly();
return true; return readOnly == null ? persistenceContext.isDefaultReadOnly() : readOnly;
}
final Boolean queryOption = rowProcessingState.getJdbcValuesSourceProcessingState().getQueryOptions().isReadOnly();
return queryOption == null ? false : queryOption;
} }
private void preLoad(RowProcessingState rowProcessingState) { private void preLoad(RowProcessingState rowProcessingState) {

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.readonly; package org.hibernate.orm.test.readonly;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.readonly; package org.hibernate.orm.test.readonly;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;

View File

@ -6,7 +6,7 @@
*/ */
//$Id: Course.java 5686 2005-02-12 07:27:32Z steveebersole $ //$Id: Course.java 5686 2005-02-12 07:27:32Z steveebersole $
package org.hibernate.test.readonly; package org.hibernate.orm.test.readonly;
/** /**

View File

@ -10,7 +10,7 @@
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping <hibernate-mapping
package="org.hibernate.test.readonly"> package="org.hibernate.orm.test.readonly">
<class name="DataPoint" <class name="DataPoint"
dynamic-update="true"> dynamic-update="true">

View File

@ -6,7 +6,7 @@
*/ */
//$Id: DataPoint.java 7231 2005-06-19 22:04:00Z oneovthafew $ //$Id: DataPoint.java 7231 2005-06-19 22:04:00Z oneovthafew $
package org.hibernate.test.readonly; package org.hibernate.orm.test.readonly;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal; import java.math.BigDecimal;

View File

@ -9,7 +9,7 @@
"-//Hibernate/Hibernate Mapping DTD 3.0//EN" "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.readonly"> <hibernate-mapping package="org.hibernate.orm.test.readonly">
<class name="Course"> <class name="Course">
<id name="courseCode"> <id name="courseCode">

View File

@ -6,7 +6,7 @@
*/ */
//$Id: Enrolment.java 6970 2005-05-31 20:24:41Z oneovthafew $ //$Id: Enrolment.java 6970 2005-05-31 20:24:41Z oneovthafew $
package org.hibernate.test.readonly; package org.hibernate.orm.test.readonly;
import java.io.Serializable; import java.io.Serializable;
/** /**

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.readonly; package org.hibernate.orm.test.readonly;
/** /**

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.readonly; package org.hibernate.orm.test.readonly;
import java.io.Serializable; import java.io.Serializable;
/** /**

View File

@ -20,11 +20,6 @@ import org.hibernate.proxy.HibernateProxy;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.test.readonly.AbstractReadOnlyTest;
import org.hibernate.test.readonly.Container;
import org.hibernate.test.readonly.DataPoint;
import org.hibernate.test.readonly.Info;
import org.hibernate.test.readonly.Owner;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
@ -56,7 +51,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
* @author Gail Badner * @author Gail Badner
*/ */
@DomainModel( @DomainModel(
xmlMappings = { "org/hibernate/test/readonly/DataPoint.hbm.xml" } xmlMappings = { "org/hibernate/orm/test/readonly/DataPoint.hbm.xml" }
) )
public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest { public class ReadOnlySessionLazyNonLazyTest extends AbstractReadOnlyTest {

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.readonly; package org.hibernate.orm.test.readonly;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;
@ -34,8 +34,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
*/ */
@DomainModel( @DomainModel(
xmlMappings = { xmlMappings = {
"org/hibernate/test/readonly/DataPoint.hbm.xml", "org/hibernate/orm/test/readonly/DataPoint.hbm.xml",
"org/hibernate/test/readonly/TextHolder.hbm.xml" "org/hibernate/orm/test/readonly/TextHolder.hbm.xml"
} }
) )
public class ReadOnlySessionTest extends AbstractReadOnlyTest { public class ReadOnlySessionTest extends AbstractReadOnlyTest {

View File

@ -17,9 +17,6 @@ import org.hibernate.Transaction;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.test.readonly.AbstractReadOnlyTest;
import org.hibernate.test.readonly.DataPoint;
import org.hibernate.test.readonly.TextHolder;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
@ -34,8 +31,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
*/ */
@DomainModel( @DomainModel(
xmlMappings = { xmlMappings = {
"org/hibernate/test/readonly/DataPoint.hbm.xml", "org/hibernate/orm/test/readonly/DataPoint.hbm.xml",
"org/hibernate/test/readonly/TextHolder.hbm.xml" "org/hibernate/orm/test/readonly/TextHolder.hbm.xml"
} }
) )
public class ReadOnlyTest extends AbstractReadOnlyTest { public class ReadOnlyTest extends AbstractReadOnlyTest {

View File

@ -9,8 +9,6 @@ package org.hibernate.orm.test.readonly;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.FailureExpected; import org.hibernate.testing.orm.junit.FailureExpected;
import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.test.readonly.AbstractReadOnlyTest;
import org.hibernate.test.readonly.VersionedNode;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -23,7 +21,7 @@ import static org.junit.jupiter.api.Assertions.assertSame;
* @author Gail Badner * @author Gail Badner
*/ */
@DomainModel( @DomainModel(
xmlMappings = "org/hibernate/test/readonly/VersionedNode.hbm.xml" xmlMappings = "org/hibernate/orm/test/readonly/VersionedNode.hbm.xml"
) )
public class ReadOnlyVersionedNodesTest extends AbstractReadOnlyTest { public class ReadOnlyVersionedNodesTest extends AbstractReadOnlyTest {

View File

@ -6,7 +6,7 @@
*/ */
//$Id: Student.java 9116 2006-01-23 21:21:01Z steveebersole $ //$Id: Student.java 9116 2006-01-23 21:21:01Z steveebersole $
package org.hibernate.test.readonly; package org.hibernate.orm.test.readonly;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;

View File

@ -9,7 +9,7 @@
* Created on 28-Jan-2005 * Created on 28-Jan-2005
* *
*/ */
package org.hibernate.test.readonly; package org.hibernate.orm.test.readonly;
/** /**

View File

@ -9,7 +9,7 @@
"-//Hibernate/Hibernate Mapping DTD 3.0//EN" "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.readonly"> <hibernate-mapping package="org.hibernate.orm.test.readonly">
<class name="TextHolder" > <class name="TextHolder" >
<id name="id"> <id name="id">

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.readonly; package org.hibernate.orm.test.readonly;
/** /**

View File

@ -9,7 +9,7 @@
"-//Hibernate/Hibernate Mapping DTD 3.0//EN" "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.readonly"> <hibernate-mapping package="org.hibernate.orm.test.readonly">
<class name="VersionedNode" table="V_NODE"> <class name="VersionedNode" table="V_NODE">
<id name="id" column="ID" type="string"> <id name="id" column="ID" type="string">

View File

@ -7,7 +7,7 @@
//$Id: $ //$Id: $
package org.hibernate.test.readonly; package org.hibernate.orm.test.readonly;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;