cache the @NaturalId loaders
and clean up some of the other loader caching code
This commit is contained in:
parent
e0ee9f5b0a
commit
3a24c700fc
|
@ -257,6 +257,7 @@ public abstract class AbstractEntityPersister
|
||||||
private final EntityLoaderLazyCollection loaders = new EntityLoaderLazyCollection();
|
private final EntityLoaderLazyCollection loaders = new EntityLoaderLazyCollection();
|
||||||
|
|
||||||
private volatile Map<String,EntityLoader> uniqueKeyLoaders;
|
private volatile Map<String,EntityLoader> uniqueKeyLoaders;
|
||||||
|
private volatile Map<LockMode,EntityLoader> naturalIdLoaders;
|
||||||
|
|
||||||
// SQL strings
|
// SQL strings
|
||||||
private String sqlVersionSelectString;
|
private String sqlVersionSelectString;
|
||||||
|
@ -2478,40 +2479,56 @@ public abstract class AbstractEntityPersister
|
||||||
String propertyName,
|
String propertyName,
|
||||||
Object uniqueKey,
|
Object uniqueKey,
|
||||||
SharedSessionContractImplementor session) throws HibernateException {
|
SharedSessionContractImplementor session) throws HibernateException {
|
||||||
return getAppropriateUniqueKeyLoader( propertyName, session ).loadByUniqueKey( session, uniqueKey );
|
return getAppropriateUniqueKeyLoader( propertyName, session )
|
||||||
|
.loadByUniqueKey( session, uniqueKey );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object loadByNaturalId(
|
public Object loadByNaturalId(
|
||||||
Object[] naturalIdValues,
|
Object[] naturalIdValues,
|
||||||
LockOptions lockOptions,
|
LockOptions lockOptions,
|
||||||
SharedSessionContractImplementor session) throws HibernateException {
|
SharedSessionContractImplementor session) throws HibernateException {
|
||||||
//TODO: cache this
|
return getAppropriateNaturalIdLoader( determineValueNullness( naturalIdValues ), lockOptions, session )
|
||||||
return new EntityLoader(
|
.loadByUniqueKey( session, naturalIdValues );
|
||||||
this,
|
|
||||||
determineValueNullness( naturalIdValues ),
|
|
||||||
1,
|
|
||||||
lockOptions,
|
|
||||||
getFactory(),
|
|
||||||
session.getLoadQueryInfluencers()
|
|
||||||
).loadByUniqueKey( session, naturalIdValues );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private EntityLoader getAppropriateUniqueKeyLoader(String propertyName, SharedSessionContractImplementor session) {
|
private EntityLoader getAppropriateNaturalIdLoader(
|
||||||
final boolean useStaticLoader = !session.getLoadQueryInfluencers().hasEnabledFilters()
|
boolean[] valueNullness,
|
||||||
&& !session.getLoadQueryInfluencers().hasEnabledFetchProfiles()
|
LockOptions lockOptions,
|
||||||
&& propertyName.indexOf( '.' ) < 0; //ugly little workaround for fact that createUniqueKeyLoaders() does not handle component properties
|
SharedSessionContractImplementor session) {
|
||||||
|
LoadQueryInfluencers loadQueryInfluencers = session.getLoadQueryInfluencers();
|
||||||
if ( useStaticLoader ) {
|
return useStaticNaturalIdLoader( valueNullness, lockOptions, loadQueryInfluencers )
|
||||||
final Map<String, EntityLoader> uniqueKeyLoaders = this.uniqueKeyLoaders;
|
? naturalIdLoaders.get( lockOptions.getLockMode() ) :
|
||||||
return uniqueKeyLoaders == null ? null : uniqueKeyLoaders.get( propertyName );
|
createNaturalIdLoader( valueNullness, lockOptions, loadQueryInfluencers );
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return createUniqueKeyLoader(
|
private boolean useStaticNaturalIdLoader(
|
||||||
|
boolean[] valueNullness,
|
||||||
|
LockOptions lockOptions,
|
||||||
|
LoadQueryInfluencers loadQueryInfluencers) {
|
||||||
|
return lockOptions.getTimeOut() == LockOptions.WAIT_FOREVER
|
||||||
|
&& ArrayHelper.isAllFalse( valueNullness )
|
||||||
|
&& !loadQueryInfluencers.hasEnabledFilters()
|
||||||
|
&& !loadQueryInfluencers.hasEnabledFetchProfiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
private EntityLoader getAppropriateUniqueKeyLoader(
|
||||||
|
String propertyName,
|
||||||
|
SharedSessionContractImplementor session) {
|
||||||
|
LoadQueryInfluencers loadQueryInfluencers = session.getLoadQueryInfluencers();
|
||||||
|
return useStaticUniqueKeyLoader( propertyName, loadQueryInfluencers )
|
||||||
|
? uniqueKeyLoaders.get( propertyName )
|
||||||
|
: createUniqueKeyLoader(
|
||||||
propertyMapping.toType( propertyName ),
|
propertyMapping.toType( propertyName ),
|
||||||
propertyMapping.toColumns( propertyName ),
|
propertyMapping.toColumns( propertyName ),
|
||||||
session.getLoadQueryInfluencers()
|
loadQueryInfluencers
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean useStaticUniqueKeyLoader(String propertyName, LoadQueryInfluencers loadQueryInfluencers) {
|
||||||
|
return !loadQueryInfluencers.hasEnabledFilters()
|
||||||
|
&& !loadQueryInfluencers.hasEnabledFetchProfiles()
|
||||||
|
//ugly little workaround for fact that createUniqueKeyLoaders() does not handle component properties
|
||||||
|
&& propertyName.indexOf( '.' ) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPropertyIndex(String propertyName) {
|
public int getPropertyIndex(String propertyName) {
|
||||||
|
@ -2521,10 +2538,10 @@ public abstract class AbstractEntityPersister
|
||||||
protected void createUniqueKeyLoaders() throws MappingException {
|
protected void createUniqueKeyLoaders() throws MappingException {
|
||||||
Type[] propertyTypes = getPropertyTypes();
|
Type[] propertyTypes = getPropertyTypes();
|
||||||
String[] propertyNames = getPropertyNames();
|
String[] propertyNames = getPropertyNames();
|
||||||
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
|
for ( int i = 0; i < propertyUniqueness.length; i++ ) {
|
||||||
if ( propertyUniqueness[i] ) {
|
if ( propertyUniqueness[i] ) {
|
||||||
if ( uniqueKeyLoaders == null ) {
|
if ( uniqueKeyLoaders == null ) {
|
||||||
this.uniqueKeyLoaders = new HashMap<>();
|
uniqueKeyLoaders = new HashMap<>();
|
||||||
}
|
}
|
||||||
//don't need filters for the static loaders
|
//don't need filters for the static loaders
|
||||||
uniqueKeyLoaders.put(
|
uniqueKeyLoaders.put(
|
||||||
|
@ -2538,6 +2555,9 @@ public abstract class AbstractEntityPersister
|
||||||
//TODO: create uk loaders for component properties
|
//TODO: create uk loaders for component properties
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ( uniqueKeyLoaders == null ) {
|
||||||
|
uniqueKeyLoaders = Collections.emptyMap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private EntityLoader createUniqueKeyLoader(
|
private EntityLoader createUniqueKeyLoader(
|
||||||
|
@ -2559,6 +2579,40 @@ public abstract class AbstractEntityPersister
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void createNaturalIdLoaders() throws MappingException {
|
||||||
|
if ( hasNaturalIdentifier() ) {
|
||||||
|
naturalIdLoaders = new HashMap<>();
|
||||||
|
boolean[] valueNullness = new boolean[ getNaturalIdentifierProperties().length ];
|
||||||
|
for ( LockMode lockMode : LockMode.values() ) {
|
||||||
|
naturalIdLoaders.put(
|
||||||
|
lockMode,
|
||||||
|
createNaturalIdLoader(
|
||||||
|
valueNullness,
|
||||||
|
new LockOptions(lockMode),
|
||||||
|
LoadQueryInfluencers.NONE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
naturalIdLoaders = Collections.emptyMap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private EntityLoader createNaturalIdLoader(
|
||||||
|
boolean[] valueNullness,
|
||||||
|
LockOptions lockOptions,
|
||||||
|
LoadQueryInfluencers loadQueryInfluencers) {
|
||||||
|
return new EntityLoader(
|
||||||
|
this,
|
||||||
|
valueNullness,
|
||||||
|
1,
|
||||||
|
lockOptions,
|
||||||
|
getFactory(),
|
||||||
|
loadQueryInfluencers
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
protected String getSQLWhereString(String alias) {
|
protected String getSQLWhereString(String alias) {
|
||||||
return StringHelper.replace( sqlWhereStringTemplate, Template.TEMPLATE, alias );
|
return StringHelper.replace( sqlWhereStringTemplate, Template.TEMPLATE, alias );
|
||||||
}
|
}
|
||||||
|
@ -4356,6 +4410,7 @@ public abstract class AbstractEntityPersister
|
||||||
|
|
||||||
createLoaders();
|
createLoaders();
|
||||||
createUniqueKeyLoaders();
|
createUniqueKeyLoaders();
|
||||||
|
createNaturalIdLoaders();
|
||||||
createQueryLoader();
|
createQueryLoader();
|
||||||
|
|
||||||
doPostInstantiate();
|
doPostInstantiate();
|
||||||
|
@ -4570,35 +4625,34 @@ public abstract class AbstractEntityPersister
|
||||||
// regardless of any other consideration
|
// regardless of any other consideration
|
||||||
return queryLoader;
|
return queryLoader;
|
||||||
}
|
}
|
||||||
else if ( isAffectedByEnabledFilters( session ) ) {
|
else {
|
||||||
|
LoadQueryInfluencers loadQueryInfluencers = session.getLoadQueryInfluencers();
|
||||||
|
if ( isAffectedByEnabledFilters( session ) ) {
|
||||||
// because filters affect the rows returned (because they add
|
// because filters affect the rows returned (because they add
|
||||||
// restrictions) these need to be next in precedence
|
// restrictions) these need to be next in precedence
|
||||||
return createEntityLoader( lockOptions, session.getLoadQueryInfluencers() );
|
return createEntityLoader( lockOptions, loadQueryInfluencers );
|
||||||
}
|
}
|
||||||
else if ( session.getLoadQueryInfluencers().getInternalFetchProfile() != null && LockMode.UPGRADE.greaterThan(
|
else if ( loadQueryInfluencers.getInternalFetchProfile() != null
|
||||||
lockOptions.getLockMode()
|
&& LockMode.UPGRADE.greaterThan( lockOptions.getLockMode() ) ) {
|
||||||
) ) {
|
|
||||||
// Next, we consider whether an 'internal' fetch profile has been set.
|
// Next, we consider whether an 'internal' fetch profile has been set.
|
||||||
// This indicates a special fetch profile Hibernate needs applied
|
// This indicates a special fetch profile Hibernate needs applied
|
||||||
// (for its merge loading process e.g.).
|
// (for its merge loading process e.g.).
|
||||||
final String internalFetchProfile = session.getLoadQueryInfluencers().getInternalFetchProfile();
|
return getLoaderByString( loadQueryInfluencers.getInternalFetchProfile() );
|
||||||
return getLoaderByString( internalFetchProfile );
|
|
||||||
}
|
}
|
||||||
else if ( isAffectedByEnabledFetchProfiles( session ) ) {
|
else if ( isAffectedByEnabledFetchProfiles( session )
|
||||||
|
|| isAffectedByEntityGraph( session ) ) {
|
||||||
// If the session has associated influencers we need to adjust the
|
// If the session has associated influencers we need to adjust the
|
||||||
// SQL query used for loading based on those influencers
|
// SQL query used for loading based on those influencers
|
||||||
return createEntityLoader( lockOptions, session.getLoadQueryInfluencers() );
|
return createEntityLoader( lockOptions, loadQueryInfluencers );
|
||||||
}
|
|
||||||
else if ( isAffectedByEntityGraph( session ) ) {
|
|
||||||
return createEntityLoader( lockOptions, session.getLoadQueryInfluencers() );
|
|
||||||
}
|
}
|
||||||
else if ( lockOptions.getTimeOut() != LockOptions.WAIT_FOREVER ) {
|
else if ( lockOptions.getTimeOut() != LockOptions.WAIT_FOREVER ) {
|
||||||
return createEntityLoader( lockOptions, session.getLoadQueryInfluencers() );
|
return createEntityLoader( lockOptions, loadQueryInfluencers );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return getLoaderByLockMode( lockOptions.getLockMode() );
|
return getLoaderByLockMode( lockOptions.getLockMode() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private UniqueEntityLoader getLoaderByString(String internalFetchProfile) {
|
private UniqueEntityLoader getLoaderByString(String internalFetchProfile) {
|
||||||
if ( "merge".equals( internalFetchProfile ) ) {
|
if ( "merge".equals( internalFetchProfile ) ) {
|
||||||
|
|
Loading…
Reference in New Issue