HHH-13565 Extract Session properties to avoid eager initialization of Map<String,Object> properties
This commit is contained in:
parent
457e9b61fa
commit
e23e6a73e6
|
@ -6,6 +6,9 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.internal;
|
package org.hibernate.internal;
|
||||||
|
|
||||||
|
import org.hibernate.CacheMode;
|
||||||
|
import org.hibernate.FlushMode;
|
||||||
|
import org.hibernate.LockOptions;
|
||||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
|
@ -29,12 +32,27 @@ import org.hibernate.event.spi.RefreshEventListener;
|
||||||
import org.hibernate.event.spi.ReplicateEventListener;
|
import org.hibernate.event.spi.ReplicateEventListener;
|
||||||
import org.hibernate.event.spi.ResolveNaturalIdEventListener;
|
import org.hibernate.event.spi.ResolveNaturalIdEventListener;
|
||||||
import org.hibernate.event.spi.SaveOrUpdateEventListener;
|
import org.hibernate.event.spi.SaveOrUpdateEventListener;
|
||||||
|
import org.hibernate.jpa.AvailableSettings;
|
||||||
|
import org.hibernate.jpa.QueryHints;
|
||||||
|
import org.hibernate.jpa.internal.util.CacheModeHelper;
|
||||||
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
|
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
|
||||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import javax.persistence.CacheRetrieveMode;
|
||||||
|
import javax.persistence.CacheStoreMode;
|
||||||
|
import javax.persistence.PessimisticLockScope;
|
||||||
|
|
||||||
|
import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_SCOPE;
|
||||||
|
import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_TIMEOUT;
|
||||||
|
import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_RETRIEVE_MODE;
|
||||||
|
import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_STORE_MODE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal component.
|
* Internal component.
|
||||||
*
|
*
|
||||||
|
@ -57,6 +75,11 @@ import java.util.Objects;
|
||||||
*/
|
*/
|
||||||
final class FastSessionServices {
|
final class FastSessionServices {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default session properties
|
||||||
|
*/
|
||||||
|
final Map<String, Object> defaultSessionProperties;
|
||||||
|
|
||||||
// All session events need to be iterated frequently:
|
// All session events need to be iterated frequently:
|
||||||
|
|
||||||
private final Iterable<ClearEventListener> clearEventListeners;
|
private final Iterable<ClearEventListener> clearEventListeners;
|
||||||
|
@ -88,9 +111,12 @@ final class FastSessionServices {
|
||||||
final TransactionCoordinatorBuilder transactionCoordinatorBuilder;
|
final TransactionCoordinatorBuilder transactionCoordinatorBuilder;
|
||||||
final JdbcServices jdbcServices;
|
final JdbcServices jdbcServices;
|
||||||
final boolean isJtaTransactionAccessible;
|
final boolean isJtaTransactionAccessible;
|
||||||
|
final CacheMode initialSessionCacheMode;
|
||||||
|
|
||||||
//Private fields:
|
//Private fields:
|
||||||
private final Dialect dialect;
|
private final Dialect dialect;
|
||||||
|
private final CacheStoreMode defaultCacheStoreMode;
|
||||||
|
private final CacheRetrieveMode defaultCacheRetrieveMode;
|
||||||
|
|
||||||
FastSessionServices(SessionFactoryImpl sf) {
|
FastSessionServices(SessionFactoryImpl sf) {
|
||||||
Objects.requireNonNull( sf );
|
Objects.requireNonNull( sf );
|
||||||
|
@ -132,6 +158,11 @@ final class FastSessionServices {
|
||||||
this.jdbcServices = sr.getService( JdbcServices.class );
|
this.jdbcServices = sr.getService( JdbcServices.class );
|
||||||
|
|
||||||
this.isJtaTransactionAccessible = isTransactionAccessible( sf, transactionCoordinatorBuilder );
|
this.isJtaTransactionAccessible = isTransactionAccessible( sf, transactionCoordinatorBuilder );
|
||||||
|
|
||||||
|
this.defaultSessionProperties = initializeDefaultSessionProperties( sf );
|
||||||
|
this.defaultCacheStoreMode = determineCacheStoreMode( defaultSessionProperties );
|
||||||
|
this.defaultCacheRetrieveMode = determineCacheRetrieveMode( defaultSessionProperties );
|
||||||
|
this.initialSessionCacheMode = CacheModeHelper.interpretCacheMode( defaultCacheStoreMode, defaultCacheRetrieveMode );
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterable<ClearEventListener> getClearEventListeners() {
|
Iterable<ClearEventListener> getClearEventListeners() {
|
||||||
|
@ -230,4 +261,67 @@ final class FastSessionServices {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Map<String, Object> initializeDefaultSessionProperties(SessionFactoryImpl sf) {
|
||||||
|
HashMap<String,Object> p = new HashMap<>();
|
||||||
|
|
||||||
|
//Static defaults:
|
||||||
|
p.putIfAbsent( AvailableSettings.FLUSH_MODE, FlushMode.AUTO.name() );
|
||||||
|
p.putIfAbsent( JPA_LOCK_SCOPE, PessimisticLockScope.EXTENDED.name() );
|
||||||
|
p.putIfAbsent( JPA_LOCK_TIMEOUT, LockOptions.WAIT_FOREVER );
|
||||||
|
p.putIfAbsent( JPA_SHARED_CACHE_RETRIEVE_MODE, CacheModeHelper.DEFAULT_RETRIEVE_MODE );
|
||||||
|
p.putIfAbsent( JPA_SHARED_CACHE_STORE_MODE, CacheModeHelper.DEFAULT_STORE_MODE );
|
||||||
|
|
||||||
|
//Defaults defined by SessionFactory configuration:
|
||||||
|
final String[] ENTITY_MANAGER_SPECIFIC_PROPERTIES = {
|
||||||
|
JPA_LOCK_SCOPE,
|
||||||
|
JPA_LOCK_TIMEOUT,
|
||||||
|
AvailableSettings.FLUSH_MODE,
|
||||||
|
JPA_SHARED_CACHE_RETRIEVE_MODE,
|
||||||
|
JPA_SHARED_CACHE_STORE_MODE,
|
||||||
|
QueryHints.SPEC_HINT_TIMEOUT
|
||||||
|
};
|
||||||
|
final Map<String, Object> properties = sf.getProperties();
|
||||||
|
for ( String key : ENTITY_MANAGER_SPECIFIC_PROPERTIES ) {
|
||||||
|
if ( properties.containsKey( key ) ) {
|
||||||
|
p.put( key, properties.get( key ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableMap( p );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param properties the Session properties
|
||||||
|
* @return either the CacheStoreMode as defined in the Session specific properties, or as defined in the
|
||||||
|
* properties shared across all sessions (the defaults).
|
||||||
|
*/
|
||||||
|
CacheStoreMode getCacheStoreMode(final Map<String, Object> properties) {
|
||||||
|
if ( properties == null ) {
|
||||||
|
return this.defaultCacheStoreMode;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return determineCacheStoreMode( properties );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param properties the Session properties
|
||||||
|
* @return either the CacheRetrieveMode as defined in the Session specific properties, or as defined in the
|
||||||
|
* properties shared across all sessions (the defaults).
|
||||||
|
*/
|
||||||
|
CacheRetrieveMode getCacheRetrieveMode(Map<String, Object> properties) {
|
||||||
|
if ( properties == null ) {
|
||||||
|
return this.defaultCacheRetrieveMode;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return determineCacheRetrieveMode( properties );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CacheRetrieveMode determineCacheRetrieveMode(Map<String, Object> settings) {
|
||||||
|
return ( CacheRetrieveMode ) settings.get( JPA_SHARED_CACHE_RETRIEVE_MODE );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CacheStoreMode determineCacheStoreMode(Map<String, Object> settings) {
|
||||||
|
return ( CacheStoreMode ) settings.get( JPA_SHARED_CACHE_STORE_MODE );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,23 +192,15 @@ import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_STORE_MODE;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
* @author Brett Meyer
|
* @author Brett Meyer
|
||||||
* @author Chris Cranford
|
* @author Chris Cranford
|
||||||
|
* @author Sanne Grinovero
|
||||||
*/
|
*/
|
||||||
public final class SessionImpl
|
public final class SessionImpl
|
||||||
extends AbstractSessionImpl
|
extends AbstractSessionImpl
|
||||||
implements EventSource, SessionImplementor, HibernateEntityManagerImplementor {
|
implements EventSource, SessionImplementor, HibernateEntityManagerImplementor {
|
||||||
private static final EntityManagerMessageLogger log = HEMLogging.messageLogger( SessionImpl.class );
|
private static final EntityManagerMessageLogger log = HEMLogging.messageLogger( SessionImpl.class );
|
||||||
|
|
||||||
|
// Defaults to null which means the properties are the default - as defined in FastSessionServices#defaultSessionProperties
|
||||||
private static final String[] ENTITY_MANAGER_SPECIFIC_PROPERTIES = {
|
private Map<String, Object> properties;
|
||||||
JPA_LOCK_SCOPE,
|
|
||||||
JPA_LOCK_TIMEOUT,
|
|
||||||
AvailableSettings.FLUSH_MODE,
|
|
||||||
JPA_SHARED_CACHE_RETRIEVE_MODE,
|
|
||||||
JPA_SHARED_CACHE_STORE_MODE,
|
|
||||||
QueryHints.SPEC_HINT_TIMEOUT
|
|
||||||
};
|
|
||||||
|
|
||||||
private Map<String, Object> properties = new HashMap<>();
|
|
||||||
|
|
||||||
private transient ActionQueue actionQueue;
|
private transient ActionQueue actionQueue;
|
||||||
private transient StatefulPersistenceContext persistenceContext;
|
private transient StatefulPersistenceContext persistenceContext;
|
||||||
|
@ -260,67 +252,38 @@ public final class SessionImpl
|
||||||
statistics.openSession();
|
statistics.openSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setLockOptions( this.properties == null ? fastSessionServices.defaultSessionProperties : this.properties, this.lockOptions );
|
||||||
|
getSession().setCacheMode( fastSessionServices.initialSessionCacheMode );
|
||||||
|
|
||||||
// NOTE : pulse() already handles auto-join-ability correctly
|
// NOTE : pulse() already handles auto-join-ability correctly
|
||||||
getTransactionCoordinator().pulse();
|
getTransactionCoordinator().pulse();
|
||||||
|
|
||||||
setDefaultProperties();
|
|
||||||
applyProperties();
|
|
||||||
|
|
||||||
if ( log.isTraceEnabled() ) {
|
if ( log.isTraceEnabled() ) {
|
||||||
log.tracef( "Opened Session [%s] at timestamp: %s", getSessionIdentifier(), getTimestamp() );
|
log.tracef( "Opened Session [%s] at timestamp: %s", getSessionIdentifier(), getTimestamp() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setDefaultProperties() {
|
|
||||||
properties.putIfAbsent( AvailableSettings.FLUSH_MODE, getHibernateFlushMode().name() );
|
|
||||||
properties.putIfAbsent( JPA_LOCK_SCOPE, PessimisticLockScope.EXTENDED.name() );
|
|
||||||
properties.putIfAbsent( JPA_LOCK_TIMEOUT, LockOptions.WAIT_FOREVER );
|
|
||||||
properties.putIfAbsent( JPA_SHARED_CACHE_RETRIEVE_MODE, CacheModeHelper.DEFAULT_RETRIEVE_MODE );
|
|
||||||
properties.putIfAbsent( JPA_SHARED_CACHE_STORE_MODE, CacheModeHelper.DEFAULT_STORE_MODE );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void applyProperties() {
|
|
||||||
applyEntityManagerSpecificProperties();
|
|
||||||
setHibernateFlushMode( ConfigurationHelper.getFlushMode( properties.get( AvailableSettings.FLUSH_MODE ), FlushMode.AUTO ) );
|
|
||||||
setLockOptions( this.properties, this.lockOptions );
|
|
||||||
getSession().setCacheMode(
|
|
||||||
CacheModeHelper.interpretCacheMode(
|
|
||||||
currentCacheStoreMode(),
|
|
||||||
currentCacheRetrieveMode()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyEntityManagerSpecificProperties() {
|
|
||||||
final Map<String, Object> properties = getFactory().getProperties();
|
|
||||||
for ( String key : ENTITY_MANAGER_SPECIFIC_PROPERTIES ) {
|
|
||||||
if ( properties.containsKey( key ) ) {
|
|
||||||
this.properties.put( key, properties.get( key ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void applyQuerySettingsAndHints(Query query) {
|
protected void applyQuerySettingsAndHints(Query query) {
|
||||||
if ( lockOptions.getLockMode() != LockMode.NONE ) {
|
if ( lockOptions.getLockMode() != LockMode.NONE ) {
|
||||||
query.setLockMode( getLockMode( lockOptions.getLockMode() ) );
|
query.setLockMode( getLockMode( lockOptions.getLockMode() ) );
|
||||||
}
|
}
|
||||||
final Object queryTimeout;
|
final Object queryTimeout;
|
||||||
if ( ( queryTimeout = properties.get( QueryHints.SPEC_HINT_TIMEOUT ) ) != null ) {
|
if ( ( queryTimeout = getSessionProperty( QueryHints.SPEC_HINT_TIMEOUT ) ) != null ) {
|
||||||
query.setHint( QueryHints.SPEC_HINT_TIMEOUT, queryTimeout );
|
query.setHint( QueryHints.SPEC_HINT_TIMEOUT, queryTimeout );
|
||||||
}
|
}
|
||||||
final Object lockTimeout;
|
final Object lockTimeout;
|
||||||
if ( ( lockTimeout = properties.get( JPA_LOCK_TIMEOUT ) ) != null ) {
|
if ( ( lockTimeout = getSessionProperty( JPA_LOCK_TIMEOUT ) ) != null ) {
|
||||||
query.setHint( JPA_LOCK_TIMEOUT, lockTimeout );
|
query.setHint( JPA_LOCK_TIMEOUT, lockTimeout );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private CacheRetrieveMode currentCacheRetrieveMode() {
|
private Object getSessionProperty(final String name) {
|
||||||
return determineCacheRetrieveMode( properties );
|
if ( properties == null ) {
|
||||||
|
return fastSessionServices.defaultSessionProperties.get( name );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return properties.get( name );
|
||||||
}
|
}
|
||||||
|
|
||||||
private CacheStoreMode currentCacheStoreMode() {
|
|
||||||
return determineCacheStoreMode( properties );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -3519,20 +3482,20 @@ public final class SessionImpl
|
||||||
}
|
}
|
||||||
if ( retrieveMode == null ) {
|
if ( retrieveMode == null ) {
|
||||||
// use the EM setting
|
// use the EM setting
|
||||||
retrieveMode = determineCacheRetrieveMode( this.properties );
|
retrieveMode = fastSessionServices.getCacheRetrieveMode( this.properties );
|
||||||
}
|
}
|
||||||
if ( storeMode == null ) {
|
if ( storeMode == null ) {
|
||||||
// use the EM setting
|
// use the EM setting
|
||||||
storeMode = determineCacheStoreMode( this.properties );
|
storeMode = fastSessionServices.getCacheStoreMode( this.properties );
|
||||||
}
|
}
|
||||||
return CacheModeHelper.interpretCacheMode( storeMode, retrieveMode );
|
return CacheModeHelper.interpretCacheMode( storeMode, retrieveMode );
|
||||||
}
|
}
|
||||||
|
|
||||||
private CacheRetrieveMode determineCacheRetrieveMode(Map<String, Object> settings) {
|
private static CacheRetrieveMode determineCacheRetrieveMode(Map<String, Object> settings) {
|
||||||
return ( CacheRetrieveMode ) settings.get( JPA_SHARED_CACHE_RETRIEVE_MODE );
|
return ( CacheRetrieveMode ) settings.get( JPA_SHARED_CACHE_RETRIEVE_MODE );
|
||||||
}
|
}
|
||||||
|
|
||||||
private CacheStoreMode determineCacheStoreMode(Map<String, Object> settings) {
|
private static CacheStoreMode determineCacheStoreMode(Map<String, Object> settings) {
|
||||||
return ( CacheStoreMode ) settings.get( JPA_SHARED_CACHE_STORE_MODE );
|
return ( CacheStoreMode ) settings.get( JPA_SHARED_CACHE_STORE_MODE );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3662,12 +3625,48 @@ public final class SessionImpl
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( propertyName == null ) {
|
||||||
|
log.warnf( "Property having key null is illegal; value won't be set." );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Store property for future reference:
|
||||||
|
|
||||||
|
if ( properties == null ) {
|
||||||
|
properties = computeCurrentSessionProperties();
|
||||||
|
}
|
||||||
properties.put( propertyName, value );
|
properties.put( propertyName, value );
|
||||||
applyProperties();
|
|
||||||
|
//now actually update settings, if it's any of these which have a direct impact on this Session state:
|
||||||
|
|
||||||
|
if ( AvailableSettings.FLUSH_MODE.equals( propertyName ) ) {
|
||||||
|
setHibernateFlushMode( ConfigurationHelper.getFlushMode( value, FlushMode.AUTO ) );
|
||||||
|
}
|
||||||
|
else if ( JPA_LOCK_SCOPE.equals( propertyName ) || JPA_LOCK_TIMEOUT.equals( propertyName ) ) {
|
||||||
|
setLockOptions( properties, this.lockOptions );
|
||||||
|
}
|
||||||
|
else if ( JPA_SHARED_CACHE_RETRIEVE_MODE.equals( propertyName ) || JPA_SHARED_CACHE_STORE_MODE.equals( propertyName ) ) {
|
||||||
|
getSession().setCacheMode(
|
||||||
|
CacheModeHelper.interpretCacheMode(
|
||||||
|
determineCacheStoreMode( properties ),
|
||||||
|
determineCacheRetrieveMode( properties )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> computeCurrentSessionProperties() {
|
||||||
|
final HashMap<String, Object> map = new HashMap<>( fastSessionServices.defaultSessionProperties );
|
||||||
|
//The FLUSH_MODE is always set at Session creation time, so it needs special treatment to not eagerly initialize this Map:
|
||||||
|
map.put( AvailableSettings.FLUSH_MODE, getHibernateFlushMode().name() );
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> getProperties() {
|
public Map<String, Object> getProperties() {
|
||||||
|
if ( properties == null ) {
|
||||||
|
properties = computeCurrentSessionProperties();
|
||||||
|
}
|
||||||
return Collections.unmodifiableMap( properties );
|
return Collections.unmodifiableMap( properties );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue