HHH-11958 Make EntityManager.find() support QueryHints.HINT_READONLY
This commit is contained in:
parent
49fe4f6494
commit
00e9db2b8b
|
@ -52,12 +52,19 @@ public class LoadQueryInfluencers implements Serializable {
|
||||||
|
|
||||||
private final EffectiveEntityGraph effectiveEntityGraph = new EffectiveEntityGraph();
|
private final EffectiveEntityGraph effectiveEntityGraph = new EffectiveEntityGraph();
|
||||||
|
|
||||||
|
private Boolean readOnly;
|
||||||
|
|
||||||
public LoadQueryInfluencers() {
|
public LoadQueryInfluencers() {
|
||||||
this( null );
|
this( null, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoadQueryInfluencers(SessionFactoryImplementor sessionFactory) {
|
public LoadQueryInfluencers(SessionFactoryImplementor sessionFactory) {
|
||||||
|
this(sessionFactory, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoadQueryInfluencers(SessionFactoryImplementor sessionFactory, Boolean readOnly) {
|
||||||
this.sessionFactory = sessionFactory;
|
this.sessionFactory = sessionFactory;
|
||||||
|
this.readOnly = readOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SessionFactoryImplementor getSessionFactory() {
|
public SessionFactoryImplementor getSessionFactory() {
|
||||||
|
@ -282,4 +289,11 @@ public class LoadQueryInfluencers implements Serializable {
|
||||||
effectiveEntityGraph.applyGraph( (RootGraphImplementor<?>) loadGraph, GraphSemantic.LOAD );
|
effectiveEntityGraph.applyGraph( (RootGraphImplementor<?>) loadGraph, GraphSemantic.LOAD );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean getReadOnly() {
|
||||||
|
return readOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReadOnly(Boolean readOnly) {
|
||||||
|
this.readOnly = readOnly;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -570,7 +570,8 @@ public class DefaultLoadEventListener implements LoadEventListener {
|
||||||
event.getEntityId(),
|
event.getEntityId(),
|
||||||
event.getInstanceToLoad(),
|
event.getInstanceToLoad(),
|
||||||
event.getLockOptions(),
|
event.getLockOptions(),
|
||||||
event.getSession()
|
event.getSession(),
|
||||||
|
event.getReadOnly()
|
||||||
);
|
);
|
||||||
|
|
||||||
final StatisticsImplementor statistics = event.getSession().getFactory().getStatistics();
|
final StatisticsImplementor statistics = event.getSession().getFactory().getStatistics();
|
||||||
|
|
|
@ -46,23 +46,24 @@ public class LoadEvent extends AbstractEvent {
|
||||||
private boolean isAssociationFetch;
|
private boolean isAssociationFetch;
|
||||||
private Object result;
|
private Object result;
|
||||||
private PostLoadEvent postLoadEvent;
|
private PostLoadEvent postLoadEvent;
|
||||||
|
private Boolean readOnly;
|
||||||
|
|
||||||
public LoadEvent(Serializable entityId, Object instanceToLoad, EventSource source) {
|
public LoadEvent(Serializable entityId, Object instanceToLoad, EventSource source, Boolean readOnly) {
|
||||||
this( entityId, null, instanceToLoad, DEFAULT_LOCK_OPTIONS, false, source );
|
this( entityId, null, instanceToLoad, DEFAULT_LOCK_OPTIONS, false, source, readOnly );
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoadEvent(Serializable entityId, String entityClassName, LockMode lockMode, EventSource source) {
|
public LoadEvent(Serializable entityId, String entityClassName, LockMode lockMode, EventSource source, Boolean readOnly) {
|
||||||
this( entityId, entityClassName, null, lockMode, false, source );
|
this( entityId, entityClassName, null, lockMode, false, source, readOnly );
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoadEvent(Serializable entityId, String entityClassName, LockOptions lockOptions, EventSource source) {
|
public LoadEvent(Serializable entityId, String entityClassName, LockOptions lockOptions, EventSource source, Boolean readOnly) {
|
||||||
this( entityId, entityClassName, null, lockOptions, false, source );
|
this( entityId, entityClassName, null, lockOptions, false, source, readOnly );
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoadEvent(Serializable entityId, String entityClassName, boolean isAssociationFetch, EventSource source) {
|
public LoadEvent(Serializable entityId, String entityClassName, boolean isAssociationFetch, EventSource source, Boolean readOnly) {
|
||||||
this( entityId, entityClassName, null, DEFAULT_LOCK_OPTIONS, isAssociationFetch, source );
|
this( entityId, entityClassName, null, DEFAULT_LOCK_OPTIONS, isAssociationFetch, source, readOnly );
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAssociationFetch() {
|
public boolean isAssociationFetch() {
|
||||||
return isAssociationFetch;
|
return isAssociationFetch;
|
||||||
}
|
}
|
||||||
|
@ -73,10 +74,11 @@ public class LoadEvent extends AbstractEvent {
|
||||||
Object instanceToLoad,
|
Object instanceToLoad,
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
boolean isAssociationFetch,
|
boolean isAssociationFetch,
|
||||||
EventSource source) {
|
EventSource source,
|
||||||
|
Boolean readOnly) {
|
||||||
this( entityId, entityClassName, instanceToLoad,
|
this( entityId, entityClassName, instanceToLoad,
|
||||||
lockMode == DEFAULT_LOCK_MODE ? DEFAULT_LOCK_OPTIONS : new LockOptions().setLockMode( lockMode ),
|
lockMode == DEFAULT_LOCK_MODE ? DEFAULT_LOCK_OPTIONS : new LockOptions().setLockMode( lockMode ),
|
||||||
isAssociationFetch, source );
|
isAssociationFetch, source, readOnly );
|
||||||
}
|
}
|
||||||
|
|
||||||
private LoadEvent(
|
private LoadEvent(
|
||||||
|
@ -85,7 +87,8 @@ public class LoadEvent extends AbstractEvent {
|
||||||
Object instanceToLoad,
|
Object instanceToLoad,
|
||||||
LockOptions lockOptions,
|
LockOptions lockOptions,
|
||||||
boolean isAssociationFetch,
|
boolean isAssociationFetch,
|
||||||
EventSource source) {
|
EventSource source,
|
||||||
|
Boolean readOnly) {
|
||||||
|
|
||||||
super( source );
|
super( source );
|
||||||
|
|
||||||
|
@ -106,6 +109,7 @@ public class LoadEvent extends AbstractEvent {
|
||||||
this.lockOptions = lockOptions;
|
this.lockOptions = lockOptions;
|
||||||
this.isAssociationFetch = isAssociationFetch;
|
this.isAssociationFetch = isAssociationFetch;
|
||||||
this.postLoadEvent = new PostLoadEvent( source );
|
this.postLoadEvent = new PostLoadEvent( source );
|
||||||
|
this.readOnly = readOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Serializable getEntityId() {
|
public Serializable getEntityId() {
|
||||||
|
@ -190,4 +194,12 @@ public class LoadEvent extends AbstractEvent {
|
||||||
public void setPostLoadEvent(PostLoadEvent postLoadEvent) {
|
public void setPostLoadEvent(PostLoadEvent postLoadEvent) {
|
||||||
this.postLoadEvent = postLoadEvent;
|
this.postLoadEvent = postLoadEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean getReadOnly() {
|
||||||
|
return readOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReadOnly(Boolean readOnly) {
|
||||||
|
this.readOnly = readOnly;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -928,7 +928,7 @@ public final class SessionImpl
|
||||||
LoadEvent event = loadEvent;
|
LoadEvent event = loadEvent;
|
||||||
loadEvent = null;
|
loadEvent = null;
|
||||||
if ( event == null ) {
|
if ( event == null ) {
|
||||||
event = new LoadEvent( id, object, this );
|
event = new LoadEvent( id, object, this, getReadOnlyFromLoadQueryInfluencers() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
event.setEntityClassName( null );
|
event.setEntityClassName( null );
|
||||||
|
@ -1059,7 +1059,7 @@ public final class SessionImpl
|
||||||
*/
|
*/
|
||||||
private LoadEvent recycleEventInstance(final LoadEvent event, final Serializable id, final String entityName) {
|
private LoadEvent recycleEventInstance(final LoadEvent event, final Serializable id, final String entityName) {
|
||||||
if ( event == null ) {
|
if ( event == null ) {
|
||||||
return new LoadEvent( id, entityName, true, this );
|
return new LoadEvent( id, entityName, true, this, getReadOnlyFromLoadQueryInfluencers() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
event.setEntityClassName( entityName );
|
event.setEntityClassName( entityName );
|
||||||
|
@ -2748,12 +2748,12 @@ public final class SessionImpl
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected T doGetReference(Serializable id) {
|
protected T doGetReference(Serializable id) {
|
||||||
if ( this.lockOptions != null ) {
|
if ( this.lockOptions != null ) {
|
||||||
LoadEvent event = new LoadEvent( id, entityPersister.getEntityName(), lockOptions, SessionImpl.this );
|
LoadEvent event = new LoadEvent( id, entityPersister.getEntityName(), lockOptions, SessionImpl.this, getReadOnlyFromLoadQueryInfluencers() );
|
||||||
fireLoad( event, LoadEventListener.LOAD );
|
fireLoad( event, LoadEventListener.LOAD );
|
||||||
return (T) event.getResult();
|
return (T) event.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadEvent event = new LoadEvent( id, entityPersister.getEntityName(), false, SessionImpl.this );
|
LoadEvent event = new LoadEvent( id, entityPersister.getEntityName(), false, SessionImpl.this, getReadOnlyFromLoadQueryInfluencers() );
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
try {
|
try {
|
||||||
fireLoad( event, LoadEventListener.LOAD );
|
fireLoad( event, LoadEventListener.LOAD );
|
||||||
|
@ -2784,12 +2784,12 @@ public final class SessionImpl
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected final T doLoad(Serializable id) {
|
protected final T doLoad(Serializable id) {
|
||||||
if ( this.lockOptions != null ) {
|
if ( this.lockOptions != null ) {
|
||||||
LoadEvent event = new LoadEvent( id, entityPersister.getEntityName(), lockOptions, SessionImpl.this );
|
LoadEvent event = new LoadEvent( id, entityPersister.getEntityName(), lockOptions, SessionImpl.this, getReadOnlyFromLoadQueryInfluencers() );
|
||||||
fireLoad( event, LoadEventListener.GET );
|
fireLoad( event, LoadEventListener.GET );
|
||||||
return (T) event.getResult();
|
return (T) event.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadEvent event = new LoadEvent( id, entityPersister.getEntityName(), false, SessionImpl.this );
|
LoadEvent event = new LoadEvent( id, entityPersister.getEntityName(), false, SessionImpl.this, getReadOnlyFromLoadQueryInfluencers() );
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
try {
|
try {
|
||||||
fireLoad( event, LoadEventListener.GET );
|
fireLoad( event, LoadEventListener.GET );
|
||||||
|
@ -3311,7 +3311,8 @@ public final class SessionImpl
|
||||||
|
|
||||||
try {
|
try {
|
||||||
getLoadQueryInfluencers().getEffectiveEntityGraph().applyConfiguredGraph( properties );
|
getLoadQueryInfluencers().getEffectiveEntityGraph().applyConfiguredGraph( properties );
|
||||||
|
Boolean readOnly = properties == null ? null : (Boolean) properties.get( QueryHints.HINT_READONLY );
|
||||||
|
getLoadQueryInfluencers().setReadOnly( readOnly );
|
||||||
final IdentifierLoadAccess<T> loadAccess = byId( entityClass );
|
final IdentifierLoadAccess<T> loadAccess = byId( entityClass );
|
||||||
loadAccess.with( determineAppropriateLocalCacheMode( properties ) );
|
loadAccess.with( determineAppropriateLocalCacheMode( properties ) );
|
||||||
|
|
||||||
|
@ -3366,6 +3367,7 @@ public final class SessionImpl
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
getLoadQueryInfluencers().getEffectiveEntityGraph().clear();
|
getLoadQueryInfluencers().getEffectiveEntityGraph().clear();
|
||||||
|
getLoadQueryInfluencers().setReadOnly( null );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3786,4 +3788,12 @@ public final class SessionImpl
|
||||||
( (FilterImpl) loadQueryInfluencers.getEnabledFilter( filterName ) ).afterDeserialize( getFactory() );
|
( (FilterImpl) loadQueryInfluencers.getEnabledFilter( filterName ) ).afterDeserialize( getFactory() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Boolean getReadOnlyFromLoadQueryInfluencers() {
|
||||||
|
Boolean readOnly = null;
|
||||||
|
if ( loadQueryInfluencers != null ) {
|
||||||
|
readOnly = loadQueryInfluencers.getReadOnly();
|
||||||
|
}
|
||||||
|
return readOnly;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2389,7 +2389,8 @@ public abstract class Loader {
|
||||||
final String optionalEntityName,
|
final String optionalEntityName,
|
||||||
final Serializable optionalIdentifier,
|
final Serializable optionalIdentifier,
|
||||||
final EntityPersister persister,
|
final EntityPersister persister,
|
||||||
LockOptions lockOptions) throws HibernateException {
|
final LockOptions lockOptions,
|
||||||
|
final Boolean readOnly) throws HibernateException {
|
||||||
if ( LOG.isDebugEnabled() ) {
|
if ( LOG.isDebugEnabled() ) {
|
||||||
LOG.debugf( "Loading entity: %s", MessageHelper.infoString( persister, id, identifierType, getFactory() ) );
|
LOG.debugf( "Loading entity: %s", MessageHelper.infoString( persister, id, identifierType, getFactory() ) );
|
||||||
}
|
}
|
||||||
|
@ -2403,6 +2404,9 @@ public abstract class Loader {
|
||||||
qp.setOptionalEntityName( optionalEntityName );
|
qp.setOptionalEntityName( optionalEntityName );
|
||||||
qp.setOptionalId( optionalIdentifier );
|
qp.setOptionalId( optionalIdentifier );
|
||||||
qp.setLockOptions( lockOptions );
|
qp.setLockOptions( lockOptions );
|
||||||
|
if ( readOnly != null ) {
|
||||||
|
qp.setReadOnly( readOnly );
|
||||||
|
}
|
||||||
result = doQueryAndInitializeNonLazyCollections( session, qp, false );
|
result = doQueryAndInitializeNonLazyCollections( session, qp, false );
|
||||||
}
|
}
|
||||||
catch (SQLException sqle) {
|
catch (SQLException sqle) {
|
||||||
|
@ -2477,6 +2481,22 @@ public abstract class Loader {
|
||||||
final Serializable optionalId,
|
final Serializable optionalId,
|
||||||
final EntityPersister persister,
|
final EntityPersister persister,
|
||||||
LockOptions lockOptions) throws HibernateException {
|
LockOptions lockOptions) throws HibernateException {
|
||||||
|
return loadEntityBatch( session, ids, idType, optionalObject, optionalEntityName, optionalId, persister, lockOptions, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by wrappers that batch load entities
|
||||||
|
*/
|
||||||
|
public final List loadEntityBatch(
|
||||||
|
final SharedSessionContractImplementor session,
|
||||||
|
final Serializable[] ids,
|
||||||
|
final Type idType,
|
||||||
|
final Object optionalObject,
|
||||||
|
final String optionalEntityName,
|
||||||
|
final Serializable optionalId,
|
||||||
|
final EntityPersister persister,
|
||||||
|
final LockOptions lockOptions,
|
||||||
|
final Boolean readOnly) throws HibernateException {
|
||||||
if ( LOG.isDebugEnabled() ) {
|
if ( LOG.isDebugEnabled() ) {
|
||||||
LOG.debugf( "Batch loading entity: %s", MessageHelper.infoString( persister, ids, getFactory() ) );
|
LOG.debugf( "Batch loading entity: %s", MessageHelper.infoString( persister, ids, getFactory() ) );
|
||||||
}
|
}
|
||||||
|
@ -2492,6 +2512,9 @@ public abstract class Loader {
|
||||||
qp.setOptionalEntityName( optionalEntityName );
|
qp.setOptionalEntityName( optionalEntityName );
|
||||||
qp.setOptionalId( optionalId );
|
qp.setOptionalId( optionalId );
|
||||||
qp.setLockOptions( lockOptions );
|
qp.setLockOptions( lockOptions );
|
||||||
|
if ( readOnly != null ) {
|
||||||
|
qp.setReadOnly( readOnly );
|
||||||
|
}
|
||||||
result = doQueryAndInitializeNonLazyCollections( session, qp, false );
|
result = doQueryAndInitializeNonLazyCollections( session, qp, false );
|
||||||
}
|
}
|
||||||
catch (SQLException sqle) {
|
catch (SQLException sqle) {
|
||||||
|
|
|
@ -8,8 +8,6 @@ package org.hibernate.loader.entity;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
@ -46,12 +44,23 @@ public abstract class AbstractEntityLoader
|
||||||
@Override
|
@Override
|
||||||
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session) {
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session) {
|
||||||
// this form is deprecated!
|
// this form is deprecated!
|
||||||
return load( id, optionalObject, session, LockOptions.NONE );
|
return load( id, optionalObject, session, LockOptions.NONE, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, Boolean readOnly) {
|
||||||
|
// this form is deprecated!
|
||||||
|
return load( id, optionalObject, session, LockOptions.NONE, readOnly );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions) {
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions) {
|
||||||
return load( session, id, optionalObject, id, lockOptions );
|
return load( id, optionalObject, session, lockOptions, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions, Boolean readOnly) {
|
||||||
|
return load( session, id, optionalObject, id, lockOptions, readOnly );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object load(
|
protected Object load(
|
||||||
|
@ -59,7 +68,8 @@ public abstract class AbstractEntityLoader
|
||||||
Object id,
|
Object id,
|
||||||
Object optionalObject,
|
Object optionalObject,
|
||||||
Serializable optionalId,
|
Serializable optionalId,
|
||||||
LockOptions lockOptions) {
|
LockOptions lockOptions,
|
||||||
|
Boolean readOnly) {
|
||||||
|
|
||||||
List list = loadEntity(
|
List list = loadEntity(
|
||||||
session,
|
session,
|
||||||
|
@ -69,7 +79,8 @@ public abstract class AbstractEntityLoader
|
||||||
entityName,
|
entityName,
|
||||||
optionalId,
|
optionalId,
|
||||||
persister,
|
persister,
|
||||||
lockOptions
|
lockOptions,
|
||||||
|
readOnly
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( list.size()==1 ) {
|
if ( list.size()==1 ) {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import java.sql.SQLException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
import org.hibernate.engine.internal.BatchFetchQueueHelper;
|
import org.hibernate.engine.internal.BatchFetchQueueHelper;
|
||||||
import org.hibernate.engine.spi.QueryParameters;
|
import org.hibernate.engine.spi.QueryParameters;
|
||||||
|
@ -50,11 +51,27 @@ public abstract class BatchingEntityLoader implements UniqueEntityLoader {
|
||||||
return load( id, optionalObject, session, LockOptions.NONE );
|
return load( id, optionalObject, session, LockOptions.NONE );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object load(
|
||||||
|
Serializable id,
|
||||||
|
Object optionalObject,
|
||||||
|
SharedSessionContractImplementor session,
|
||||||
|
LockOptions lockOptions,
|
||||||
|
Boolean readOnly) {
|
||||||
|
return load( id, optionalObject, session, lockOptions, readOnly );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, Boolean readOnly) {
|
||||||
|
return load( id, optionalObject, session, LockOptions.NONE, readOnly );
|
||||||
|
}
|
||||||
|
|
||||||
protected QueryParameters buildQueryParameters(
|
protected QueryParameters buildQueryParameters(
|
||||||
Serializable id,
|
Serializable id,
|
||||||
Serializable[] ids,
|
Serializable[] ids,
|
||||||
Object optionalObject,
|
Object optionalObject,
|
||||||
LockOptions lockOptions) {
|
LockOptions lockOptions,
|
||||||
|
Boolean readOnly) {
|
||||||
Type[] types = new Type[ids.length];
|
Type[] types = new Type[ids.length];
|
||||||
Arrays.fill( types, persister().getIdentifierType() );
|
Arrays.fill( types, persister().getIdentifierType() );
|
||||||
|
|
||||||
|
@ -65,6 +82,9 @@ public abstract class BatchingEntityLoader implements UniqueEntityLoader {
|
||||||
qp.setOptionalEntityName( persister().getEntityName() );
|
qp.setOptionalEntityName( persister().getEntityName() );
|
||||||
qp.setOptionalId( id );
|
qp.setOptionalId( id );
|
||||||
qp.setLockOptions( lockOptions );
|
qp.setLockOptions( lockOptions );
|
||||||
|
if ( readOnly != null ) {
|
||||||
|
qp.setReadOnly( readOnly );
|
||||||
|
}
|
||||||
return qp;
|
return qp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,12 +108,13 @@ public abstract class BatchingEntityLoader implements UniqueEntityLoader {
|
||||||
SharedSessionContractImplementor session,
|
SharedSessionContractImplementor session,
|
||||||
Serializable[] ids,
|
Serializable[] ids,
|
||||||
Object optionalObject,
|
Object optionalObject,
|
||||||
LockOptions lockOptions) {
|
LockOptions lockOptions,
|
||||||
|
Boolean readOnly) {
|
||||||
if ( log.isDebugEnabled() ) {
|
if ( log.isDebugEnabled() ) {
|
||||||
log.debugf( "Batch loading entity: %s", MessageHelper.infoString( persister, ids, session.getFactory() ) );
|
log.debugf( "Batch loading entity: %s", MessageHelper.infoString( persister, ids, session.getFactory() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryParameters qp = buildQueryParameters( id, ids, optionalObject, lockOptions );
|
QueryParameters qp = buildQueryParameters( id, ids, optionalObject, lockOptions, readOnly );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final List results = loaderToUse.doQueryAndInitializeNonLazyCollections( session, qp, false );
|
final List results = loaderToUse.doQueryAndInitializeNonLazyCollections( session, qp, false );
|
||||||
|
|
|
@ -105,7 +105,8 @@ public class DynamicBatchingEntityLoaderBuilder extends BatchingEntityLoaderBuil
|
||||||
id,
|
id,
|
||||||
persister.getMappedClass().getName(),
|
persister.getMappedClass().getName(),
|
||||||
lockOptions,
|
lockOptions,
|
||||||
(EventSource) session
|
(EventSource) session,
|
||||||
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
Object managedEntity = null;
|
Object managedEntity = null;
|
||||||
|
@ -231,7 +232,8 @@ public class DynamicBatchingEntityLoaderBuilder extends BatchingEntityLoaderBuil
|
||||||
id,
|
id,
|
||||||
persister.getMappedClass().getName(),
|
persister.getMappedClass().getName(),
|
||||||
lockOptions,
|
lockOptions,
|
||||||
(EventSource) session
|
(EventSource) session,
|
||||||
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
Object managedEntity = null;
|
Object managedEntity = null;
|
||||||
|
@ -397,6 +399,16 @@ public class DynamicBatchingEntityLoaderBuilder extends BatchingEntityLoaderBuil
|
||||||
Object optionalObject,
|
Object optionalObject,
|
||||||
SharedSessionContractImplementor session,
|
SharedSessionContractImplementor session,
|
||||||
LockOptions lockOptions) {
|
LockOptions lockOptions) {
|
||||||
|
return load (id, optionalObject, session, lockOptions, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object load(
|
||||||
|
Serializable id,
|
||||||
|
Object optionalObject,
|
||||||
|
SharedSessionContractImplementor session,
|
||||||
|
LockOptions lockOptions,
|
||||||
|
Boolean readOnly) {
|
||||||
final Serializable[] batch = session.getPersistenceContextInternal()
|
final Serializable[] batch = session.getPersistenceContextInternal()
|
||||||
.getBatchFetchQueue()
|
.getBatchFetchQueue()
|
||||||
.getEntityBatch( persister(), id, maxBatchSize, persister().getEntityMode() );
|
.getEntityBatch( persister(), id, maxBatchSize, persister().getEntityMode() );
|
||||||
|
@ -419,7 +431,7 @@ public class DynamicBatchingEntityLoaderBuilder extends BatchingEntityLoaderBuil
|
||||||
log.debugf( "Batch loading entity: %s", MessageHelper.infoString( persister(), idsToLoad, session.getFactory() ) );
|
log.debugf( "Batch loading entity: %s", MessageHelper.infoString( persister(), idsToLoad, session.getFactory() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryParameters qp = buildQueryParameters( id, idsToLoad, optionalObject, lockOptions );
|
QueryParameters qp = buildQueryParameters( id, idsToLoad, optionalObject, lockOptions, readOnly );
|
||||||
List results = dynamicLoader.doEntityBatchFetch( session, qp, idsToLoad );
|
List results = dynamicLoader.doEntityBatchFetch( session, qp, idsToLoad );
|
||||||
|
|
||||||
// The EntityKey for any entity that is not found will remain in the batch.
|
// The EntityKey for any entity that is not found will remain in the batch.
|
||||||
|
|
|
@ -141,7 +141,11 @@ public class EntityLoader extends AbstractEntityLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object loadByUniqueKey(SharedSessionContractImplementor session, Object key) {
|
public Object loadByUniqueKey(SharedSessionContractImplementor session, Object key) {
|
||||||
return load( session, key, null, null, LockOptions.NONE );
|
return loadByUniqueKey( session, key, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object loadByUniqueKey(SharedSessionContractImplementor session, Object key, Boolean readOnly) {
|
||||||
|
return load( session, key, null, null, LockOptions.NONE, readOnly );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -81,6 +81,11 @@ public class LegacyBatchingEntityLoaderBuilder extends BatchingEntityLoaderBuild
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions) {
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions) {
|
||||||
|
return load( id, optionalObject, session, lockOptions, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions, Boolean readOnly) {
|
||||||
final Serializable[] batch = session.getPersistenceContextInternal()
|
final Serializable[] batch = session.getPersistenceContextInternal()
|
||||||
.getBatchFetchQueue()
|
.getBatchFetchQueue()
|
||||||
.getEntityBatch( persister(), id, batchSizes[0], persister().getEntityMode() );
|
.getEntityBatch( persister(), id, batchSizes[0], persister().getEntityMode() );
|
||||||
|
@ -99,7 +104,8 @@ public class LegacyBatchingEntityLoaderBuilder extends BatchingEntityLoaderBuild
|
||||||
persister().getEntityName(),
|
persister().getEntityName(),
|
||||||
id,
|
id,
|
||||||
persister(),
|
persister(),
|
||||||
lockOptions
|
lockOptions,
|
||||||
|
readOnly
|
||||||
);
|
);
|
||||||
// The EntityKey for any entity that is not found will remain in the batch.
|
// The EntityKey for any entity that is not found will remain in the batch.
|
||||||
// Explicitly remove the EntityKeys for entities that were not found to
|
// Explicitly remove the EntityKeys for entities that were not found to
|
||||||
|
|
|
@ -91,6 +91,11 @@ class PaddedBatchingEntityLoaderBuilder extends BatchingEntityLoaderBuilder {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions) {
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions) {
|
||||||
|
return load( id, optionalObject, session, lockOptions, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions, Boolean readOnly) {
|
||||||
final Serializable[] batch = session.getPersistenceContextInternal()
|
final Serializable[] batch = session.getPersistenceContextInternal()
|
||||||
.getBatchFetchQueue()
|
.getBatchFetchQueue()
|
||||||
.getEntityBatch( persister(), id, batchSizes[0], persister().getEntityMode() );
|
.getEntityBatch( persister(), id, batchSizes[0], persister().getEntityMode() );
|
||||||
|
@ -123,7 +128,7 @@ class PaddedBatchingEntityLoaderBuilder extends BatchingEntityLoaderBuilder {
|
||||||
idsToLoad[i] = id;
|
idsToLoad[i] = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return doBatchLoad( id, loaders[indexToUse], session, idsToLoad, optionalObject, lockOptions );
|
return doBatchLoad( id, loaders[indexToUse], session, idsToLoad, optionalObject, lockOptions, readOnly );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,10 @@ public interface UniqueEntityLoader {
|
||||||
@Deprecated
|
@Deprecated
|
||||||
Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session) throws HibernateException;
|
Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session) throws HibernateException;
|
||||||
|
|
||||||
|
default Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, Boolean readOnly) throws HibernateException {
|
||||||
|
return load( id, optionalObject, session );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load an entity instance by id. If <tt>optionalObject</tt> is supplied (non-<tt>null</tt>,
|
* Load an entity instance by id. If <tt>optionalObject</tt> is supplied (non-<tt>null</tt>,
|
||||||
* the entity state is loaded into that object instance instead of instantiating a new one.
|
* the entity state is loaded into that object instance instead of instantiating a new one.
|
||||||
|
@ -47,4 +51,13 @@ public interface UniqueEntityLoader {
|
||||||
Object optionalObject,
|
Object optionalObject,
|
||||||
SharedSessionContractImplementor session,
|
SharedSessionContractImplementor session,
|
||||||
LockOptions lockOptions);
|
LockOptions lockOptions);
|
||||||
|
|
||||||
|
default Object load(
|
||||||
|
Serializable id,
|
||||||
|
Object optionalObject,
|
||||||
|
SharedSessionContractImplementor session,
|
||||||
|
LockOptions lockOptions,
|
||||||
|
Boolean readOnly) {
|
||||||
|
return load( id, optionalObject, session, lockOptions );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,8 +139,20 @@ public abstract class AbstractLoadPlanBasedEntityLoader extends AbstractLoadPlan
|
||||||
final String optionalEntityName,
|
final String optionalEntityName,
|
||||||
final Serializable optionalId,
|
final Serializable optionalId,
|
||||||
final EntityPersister persister,
|
final EntityPersister persister,
|
||||||
LockOptions lockOptions) throws HibernateException {
|
final LockOptions lockOptions) throws HibernateException {
|
||||||
|
return loadEntityBatch( session, ids, idType, optionalObject, optionalEntityName, optionalId, persister, lockOptions, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
public final List loadEntityBatch(
|
||||||
|
final SharedSessionContractImplementor session,
|
||||||
|
final Serializable[] ids,
|
||||||
|
final Type idType,
|
||||||
|
final Object optionalObject,
|
||||||
|
final String optionalEntityName,
|
||||||
|
final Serializable optionalId,
|
||||||
|
final EntityPersister persister,
|
||||||
|
final LockOptions lockOptions,
|
||||||
|
final Boolean readOnly) throws HibernateException {
|
||||||
if ( log.isDebugEnabled() ) {
|
if ( log.isDebugEnabled() ) {
|
||||||
log.debugf( "Batch loading entity: %s", MessageHelper.infoString( persister, ids, getFactory() ) );
|
log.debugf( "Batch loading entity: %s", MessageHelper.infoString( persister, ids, getFactory() ) );
|
||||||
}
|
}
|
||||||
|
@ -153,7 +165,9 @@ public abstract class AbstractLoadPlanBasedEntityLoader extends AbstractLoadPlan
|
||||||
qp.setPositionalParameterTypes( types );
|
qp.setPositionalParameterTypes( types );
|
||||||
qp.setPositionalParameterValues( ids );
|
qp.setPositionalParameterValues( ids );
|
||||||
qp.setLockOptions( lockOptions );
|
qp.setLockOptions( lockOptions );
|
||||||
|
if ( readOnly != null ) {
|
||||||
|
qp.setReadOnly( readOnly );
|
||||||
|
}
|
||||||
result = executeLoad(
|
result = executeLoad(
|
||||||
session,
|
session,
|
||||||
qp,
|
qp,
|
||||||
|
@ -178,11 +192,21 @@ public abstract class AbstractLoadPlanBasedEntityLoader extends AbstractLoadPlan
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session) throws HibernateException {
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session) throws HibernateException {
|
||||||
return load( id, optionalObject, session, LockOptions.NONE );
|
return load( id, optionalObject, session, (Boolean) null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, Boolean readOnly) throws HibernateException {
|
||||||
|
return load( id, optionalObject, session, LockOptions.NONE, readOnly );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions) {
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions) {
|
||||||
|
return load( id, optionalObject, session, lockOptions, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions, Boolean readOnly) {
|
||||||
|
|
||||||
final Object result;
|
final Object result;
|
||||||
try {
|
try {
|
||||||
|
@ -193,7 +217,9 @@ public abstract class AbstractLoadPlanBasedEntityLoader extends AbstractLoadPlan
|
||||||
qp.setOptionalEntityName( entityPersister.getEntityName() );
|
qp.setOptionalEntityName( entityPersister.getEntityName() );
|
||||||
qp.setOptionalId( id );
|
qp.setOptionalId( id );
|
||||||
qp.setLockOptions( lockOptions );
|
qp.setLockOptions( lockOptions );
|
||||||
|
if ( readOnly != null ) {
|
||||||
|
qp.setReadOnly( readOnly );
|
||||||
|
}
|
||||||
final List results = executeLoad(
|
final List results = executeLoad(
|
||||||
session,
|
session,
|
||||||
qp,
|
qp,
|
||||||
|
|
|
@ -49,7 +49,7 @@ public abstract class BatchingEntityLoader implements UniqueEntityLoader {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session) {
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session) {
|
||||||
return load( id, optionalObject, session, LockOptions.NONE );
|
return load( id, optionalObject, session, LockOptions.NONE, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected QueryParameters buildQueryParameters(
|
protected QueryParameters buildQueryParameters(
|
||||||
|
|
|
@ -94,6 +94,11 @@ public class LegacyBatchingEntityLoaderBuilder extends AbstractBatchingEntityLoa
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions) {
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions) {
|
||||||
|
return load( id, optionalObject, session, lockOptions, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions, Boolean readOnly) {
|
||||||
final Serializable[] batch = session.getPersistenceContextInternal()
|
final Serializable[] batch = session.getPersistenceContextInternal()
|
||||||
.getBatchFetchQueue()
|
.getBatchFetchQueue()
|
||||||
.getEntityBatch( persister(), id, batchSizes[0], persister().getEntityMode() );
|
.getEntityBatch( persister(), id, batchSizes[0], persister().getEntityMode() );
|
||||||
|
@ -112,7 +117,8 @@ public class LegacyBatchingEntityLoaderBuilder extends AbstractBatchingEntityLoa
|
||||||
persister().getEntityName(),
|
persister().getEntityName(),
|
||||||
id,
|
id,
|
||||||
persister(),
|
persister(),
|
||||||
lockOptions
|
lockOptions,
|
||||||
|
readOnly
|
||||||
);
|
);
|
||||||
// The EntityKey for any entity that is not found will remain in the batch.
|
// The EntityKey for any entity that is not found will remain in the batch.
|
||||||
// Explicitly remove the EntityKeys for entities that were not found to
|
// Explicitly remove the EntityKeys for entities that were not found to
|
||||||
|
|
|
@ -4370,13 +4370,22 @@ public abstract class AbstractEntityPersister
|
||||||
*/
|
*/
|
||||||
public Object load(Serializable id, Object optionalObject, LockOptions lockOptions, SharedSessionContractImplementor session)
|
public Object load(Serializable id, Object optionalObject, LockOptions lockOptions, SharedSessionContractImplementor session)
|
||||||
throws HibernateException {
|
throws HibernateException {
|
||||||
|
return doLoad( id, optionalObject, lockOptions, session, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object load(Serializable id, Object optionalObject, LockOptions lockOptions, SharedSessionContractImplementor session, Boolean readOnly)
|
||||||
|
throws HibernateException {
|
||||||
|
return doLoad( id, optionalObject, lockOptions, session, readOnly );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object doLoad(Serializable id, Object optionalObject, LockOptions lockOptions, SharedSessionContractImplementor session, Boolean readOnly)
|
||||||
|
throws HibernateException {
|
||||||
if ( LOG.isTraceEnabled() ) {
|
if ( LOG.isTraceEnabled() ) {
|
||||||
LOG.tracev( "Fetching entity: {0}", MessageHelper.infoString( this, id, getFactory() ) );
|
LOG.tracev( "Fetching entity: {0}", MessageHelper.infoString( this, id, getFactory() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
final UniqueEntityLoader loader = getAppropriateLoader( lockOptions, session );
|
final UniqueEntityLoader loader = getAppropriateLoader( lockOptions, session );
|
||||||
return loader.load( id, optionalObject, session, lockOptions );
|
return loader.load( id, optionalObject, session, lockOptions, readOnly );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -376,12 +376,22 @@ public interface EntityPersister extends EntityDefinition {
|
||||||
Object load(Serializable id, Object optionalObject, LockMode lockMode, SharedSessionContractImplementor session)
|
Object load(Serializable id, Object optionalObject, LockMode lockMode, SharedSessionContractImplementor session)
|
||||||
throws HibernateException;
|
throws HibernateException;
|
||||||
|
|
||||||
|
default Object load(Serializable id, Object optionalObject, LockMode lockMode, SharedSessionContractImplementor session, Boolean readOnly)
|
||||||
|
throws HibernateException {
|
||||||
|
return load( id, optionalObject, lockMode, session );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load an instance of the persistent class.
|
* Load an instance of the persistent class.
|
||||||
*/
|
*/
|
||||||
Object load(Serializable id, Object optionalObject, LockOptions lockOptions, SharedSessionContractImplementor session)
|
Object load(Serializable id, Object optionalObject, LockOptions lockOptions, SharedSessionContractImplementor session)
|
||||||
throws HibernateException;
|
throws HibernateException;
|
||||||
|
|
||||||
|
default Object load(Serializable id, Object optionalObject, LockOptions lockOptions, SharedSessionContractImplementor session, Boolean readOnly)
|
||||||
|
throws HibernateException {
|
||||||
|
return load( id, optionalObject, lockOptions, session );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a load of multiple entities (of this type) by identifier simultaneously.
|
* Performs a load of multiple entities (of this type) by identifier simultaneously.
|
||||||
*
|
*
|
||||||
|
@ -546,7 +556,7 @@ public interface EntityPersister extends EntityDefinition {
|
||||||
* Does this class have a natural id cache
|
* Does this class have a natural id cache
|
||||||
*/
|
*/
|
||||||
boolean hasNaturalIdCache();
|
boolean hasNaturalIdCache();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the NaturalId cache (optional operation)
|
* Get the NaturalId cache (optional operation)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -48,15 +48,25 @@ public final class NamedQueryLoader implements UniqueEntityLoader {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions) {
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions) {
|
||||||
|
return load( id, optionalObject, session, (Boolean) null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, LockOptions lockOptions, Boolean readOnly) {
|
||||||
if ( lockOptions != null ) {
|
if ( lockOptions != null ) {
|
||||||
LOG.debug( "Ignoring lock-options passed to named query loader" );
|
LOG.debug( "Ignoring lock-options passed to named query loader" );
|
||||||
}
|
}
|
||||||
return load( id, optionalObject, session );
|
return load( id, optionalObject, session, readOnly );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session) {
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session) {
|
||||||
LOG.debugf( "Loading entity: %s using named query: %s", persister.getEntityName(), queryName );
|
return load( id, optionalObject, session, (Boolean) null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object load(Serializable id, Object optionalObject, SharedSessionContractImplementor session, Boolean readOnly) {
|
||||||
|
LOG.debugf("Loading entity: %s using named query: %s", persister.getEntityName(), queryName);
|
||||||
|
|
||||||
// IMPL NOTE: essentially we perform the named query (which loads the entity into the PC), and then
|
// IMPL NOTE: essentially we perform the named query (which loads the entity into the PC), and then
|
||||||
// do an internal lookup of the entity from the PC.
|
// do an internal lookup of the entity from the PC.
|
||||||
|
@ -73,6 +83,9 @@ public final class NamedQueryLoader implements UniqueEntityLoader {
|
||||||
query.setOptionalEntityName( persister.getEntityName() );
|
query.setOptionalEntityName( persister.getEntityName() );
|
||||||
query.setOptionalObject( optionalObject );
|
query.setOptionalObject( optionalObject );
|
||||||
query.setFlushMode( FlushMode.MANUAL );
|
query.setFlushMode( FlushMode.MANUAL );
|
||||||
|
if ( readOnly != null ) {
|
||||||
|
query.setReadOnly( readOnly );
|
||||||
|
}
|
||||||
query.list();
|
query.list();
|
||||||
|
|
||||||
// now look up the object we are really interested in!
|
// now look up the object we are really interested in!
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.hibernate.Session;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.jpa.AvailableSettings;
|
import org.hibernate.jpa.AvailableSettings;
|
||||||
import org.hibernate.jpa.HibernateEntityManagerFactory;
|
import org.hibernate.jpa.HibernateEntityManagerFactory;
|
||||||
|
import org.hibernate.jpa.QueryHints;
|
||||||
import org.hibernate.stat.Statistics;
|
import org.hibernate.stat.Statistics;
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -488,6 +489,49 @@ public class EntityManagerTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue( jiraKey = "HHH-11958" )
|
||||||
|
public void testReadonlyHibernateQueryHint() {
|
||||||
|
|
||||||
|
EntityManager em = getOrCreateEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
Wallet w = new Wallet();
|
||||||
|
w.setBrand("Lacoste");
|
||||||
|
w.setModel("Minimic");
|
||||||
|
w.setSerial("0324");
|
||||||
|
em.persist(w);
|
||||||
|
try {
|
||||||
|
em.getTransaction().commit();
|
||||||
|
} finally {
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
em = getOrCreateEntityManager();
|
||||||
|
Map<String, Object> hints = new HashMap<>();
|
||||||
|
hints.put(QueryHints.HINT_READONLY, true);
|
||||||
|
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
Wallet fetchedWallet = em.find(Wallet.class, w.getSerial(), hints);
|
||||||
|
fetchedWallet.setBrand("Givenchy");
|
||||||
|
|
||||||
|
try {
|
||||||
|
em.getTransaction().commit();
|
||||||
|
} finally {
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
em = getOrCreateEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
fetchedWallet = em.find(Wallet.class, w.getSerial());
|
||||||
|
try {
|
||||||
|
em.getTransaction().commit();
|
||||||
|
assertEquals("Lacoste", fetchedWallet.getBrand());
|
||||||
|
} finally {
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class MyObject {
|
private static class MyObject {
|
||||||
public int value;
|
public int value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -264,7 +264,7 @@ public class PersisterClassProviderTest {
|
||||||
public boolean hasNaturalIdentifier() {
|
public boolean hasNaturalIdentifier() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getNaturalIdentifierProperties() {
|
public int[] getNaturalIdentifierProperties() {
|
||||||
return new int[0];
|
return new int[0];
|
||||||
|
@ -280,7 +280,7 @@ public class PersisterClassProviderTest {
|
||||||
SharedSessionContractImplementor session) {
|
SharedSessionContractImplementor session) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNaturalIdCache() {
|
public boolean hasNaturalIdCache() {
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in New Issue