HHH-6974 Adding hooks into NaturalIdRegionAccessStrategy
Created NaturalIdCacheKey to encapsulate the key for caching a naturalid Adding hooks into NaturalIdRegionAccessStrategy from StatefulPersistenceContext for load/insert/update/delete events on entities
This commit is contained in:
parent
c473520585
commit
ef22e31068
147
hibernate-core/src/main/java/org/hibernate/cache/spi/NaturalIdCacheKey.java
vendored
Normal file
147
hibernate-core/src/main/java/org/hibernate/cache/spi/NaturalIdCacheKey.java
vendored
Normal file
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Allows multiple entity classes / collection roles to be
|
||||
* stored in the same cache region. Also allows for composite
|
||||
* keys which do not properly implement equals()/hashCode().
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class NaturalIdCacheKey implements Serializable {
|
||||
private final Serializable[] naturalId;
|
||||
private final Type[] types;
|
||||
private final String entityName;
|
||||
private final String tenantId;
|
||||
private final int hashCode;
|
||||
private final String toString;
|
||||
|
||||
/**
|
||||
* Construct a new key for a collection or entity instance.
|
||||
* Note that an entity name should always be the root entity
|
||||
* name, not a subclass entity name.
|
||||
*
|
||||
* @param naturalId The naturalId associated with the cached data
|
||||
* @param types The Hibernate type mappings
|
||||
* @param entityOrRoleName The entity name.
|
||||
* @param tenantId The tenant identifier associated this data.
|
||||
* @param factory The session factory for which we are caching
|
||||
*/
|
||||
public NaturalIdCacheKey(
|
||||
final Serializable[] naturalId,
|
||||
final Type[] types,
|
||||
final String entityOrRoleName,
|
||||
final String tenantId,
|
||||
final SessionFactoryImplementor factory) {
|
||||
|
||||
this.naturalId = naturalId;
|
||||
this.types = types;
|
||||
this.entityName = entityOrRoleName;
|
||||
this.tenantId = tenantId;
|
||||
|
||||
this.hashCode = this.generateHashCode( this.naturalId, this.types, factory );
|
||||
this.toString = entityOrRoleName + "##NaturalId" + Arrays.toString( this.naturalId );
|
||||
}
|
||||
|
||||
private int generateHashCode(final Serializable[] naturalId, final Type[] types,
|
||||
final SessionFactoryImplementor factory) {
|
||||
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ( ( entityName == null ) ? 0 : entityName.hashCode() );
|
||||
result = prime * result + ( ( tenantId == null ) ? 0 : tenantId.hashCode() );
|
||||
for ( int i = 0; i < naturalId.length; i++ ) {
|
||||
result = prime * result + types[i].getHashCode( naturalId[i], factory );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// Mainly for OSCache
|
||||
return this.toString;
|
||||
}
|
||||
|
||||
public Serializable[] getNaturalId() {
|
||||
return naturalId;
|
||||
}
|
||||
|
||||
public Type[] getTypes() {
|
||||
return types;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if ( this == obj )
|
||||
return true;
|
||||
if ( obj == null )
|
||||
return false;
|
||||
if ( getClass() != obj.getClass() )
|
||||
return false;
|
||||
NaturalIdCacheKey other = (NaturalIdCacheKey) obj;
|
||||
if (this.hashCode != other.hashCode) {
|
||||
//Short circuit on hashCode, if they aren't equal there is no chance the keys are equal
|
||||
return false;
|
||||
}
|
||||
if ( entityName == null ) {
|
||||
if ( other.entityName != null )
|
||||
return false;
|
||||
}
|
||||
else if ( !entityName.equals( other.entityName ) )
|
||||
return false;
|
||||
if ( !Arrays.equals( naturalId, other.naturalId ) )
|
||||
return false;
|
||||
if ( tenantId == null ) {
|
||||
if ( other.tenantId != null )
|
||||
return false;
|
||||
}
|
||||
else if ( !tenantId.equals( other.tenantId ) )
|
||||
return false;
|
||||
|
||||
for ( int i = 0; i < naturalId.length; i++ ) {
|
||||
if ( !types[i].isEqual( naturalId[i], other.naturalId[i] ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getEntityOrRoleName() {
|
||||
return entityName;
|
||||
}
|
||||
|
||||
}
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
package org.hibernate.cache.spi.access;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.NaturalIdRegion;
|
||||
|
||||
/**
|
||||
|
@ -34,12 +35,16 @@ import org.hibernate.cache.spi.NaturalIdRegion;
|
|||
* There is another usage pattern that is used to invalidate entries
|
||||
* after performing "bulk" HQL/SQL operations:
|
||||
* {@link #lockRegion} -> {@link #removeAll} -> {@link #unlockRegion}
|
||||
* <p/>
|
||||
* NaturalIds are not versioned so null will always be passed to the version parameter for
|
||||
* {@link #putFromLoad(Object, Object, long, Object)}, {@link #putFromLoad(Object, Object, long, Object, boolean)},
|
||||
* and {@link #lockItem(Object, Object)}
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
* @author Eric Dalquist
|
||||
*/
|
||||
public interface NaturalIdRegionAccessStrategy extends RegionAccessStrategy{
|
||||
public interface NaturalIdRegionAccessStrategy extends RegionAccessStrategy {
|
||||
|
||||
/**
|
||||
* Get the wrapped naturalId cache region
|
||||
|
@ -47,4 +52,53 @@ public interface NaturalIdRegionAccessStrategy extends RegionAccessStrategy{
|
|||
* @return The underlying region
|
||||
*/
|
||||
public NaturalIdRegion getRegion();
|
||||
|
||||
/**
|
||||
* Called after an item has been inserted (before the transaction completes),
|
||||
* instead of calling evict().
|
||||
* This method is used by "synchronous" concurrency strategies.
|
||||
*
|
||||
* @param key The item key
|
||||
* @param value The item
|
||||
* @return Were the contents of the cache actual changed by this operation?
|
||||
* @throws CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
public boolean insert(Object key, Object value) throws CacheException;
|
||||
|
||||
/**
|
||||
* Called after an item has been inserted (after the transaction completes),
|
||||
* instead of calling release().
|
||||
* This method is used by "asynchronous" concurrency strategies.
|
||||
*
|
||||
* @param key The item key
|
||||
* @param value The item
|
||||
* @return Were the contents of the cache actual changed by this operation?
|
||||
* @throws CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
public boolean afterInsert(Object key, Object value) throws CacheException;
|
||||
|
||||
/**
|
||||
* Called after an item has been updated (before the transaction completes),
|
||||
* instead of calling evict(). This method is used by "synchronous" concurrency
|
||||
* strategies.
|
||||
*
|
||||
* @param key The item key
|
||||
* @param value The item
|
||||
* @return Were the contents of the cache actual changed by this operation?
|
||||
* @throws CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
public boolean update(Object key, Object value) throws CacheException;
|
||||
|
||||
/**
|
||||
* Called after an item has been updated (after the transaction completes),
|
||||
* instead of calling release(). This method is used by "asynchronous"
|
||||
* concurrency strategies.
|
||||
*
|
||||
* @param key The item key
|
||||
* @param value The item
|
||||
* @param lock The lock previously obtained from {@link #lockItem}
|
||||
* @return Were the contents of the cache actual changed by this operation?
|
||||
* @throws CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
public boolean afterUpdate(Object key, Object value, SoftLock lock) throws CacheException;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import java.io.ObjectInputStream;
|
|||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
|
@ -41,8 +40,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
|
||||
import org.apache.commons.collections.map.AbstractReferenceMap;
|
||||
import org.apache.commons.collections.map.ReferenceMap;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.HibernateException;
|
||||
|
@ -51,6 +48,10 @@ import org.hibernate.MappingException;
|
|||
import org.hibernate.NonUniqueObjectException;
|
||||
import org.hibernate.PersistentObjectException;
|
||||
import org.hibernate.TransientObjectException;
|
||||
import org.hibernate.action.spi.AfterTransactionCompletionProcess;
|
||||
import org.hibernate.cache.spi.NaturalIdCacheKey;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.loading.internal.LoadContexts;
|
||||
import org.hibernate.engine.spi.AssociationKey;
|
||||
|
@ -63,6 +64,7 @@ import org.hibernate.engine.spi.EntityUniqueKey;
|
|||
import org.hibernate.engine.spi.PersistenceContext;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.engine.spi.Status;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.MarkerObject;
|
||||
import org.hibernate.internal.util.collections.IdentityMap;
|
||||
|
@ -72,6 +74,8 @@ import org.hibernate.pretty.MessageHelper;
|
|||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.proxy.LazyInitializer;
|
||||
import org.hibernate.tuple.ElementWrapper;
|
||||
import org.hibernate.type.Type;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* A <strong>stateful</strong> implementation of the {@link PersistenceContext} contract meaning that we maintain this
|
||||
|
@ -327,7 +331,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
if ( persister.getEntityMetamodel().hasImmutableNaturalId() ) {
|
||||
// an immutable natural-id is not retrieved during a normal database-snapshot operation...
|
||||
final Object[] dbValue = persister.getNaturalIdentifierSnapshot( id, session );
|
||||
cacheNaturalIdResolution( persister, id, dbValue );
|
||||
cacheNaturalIdResolution( persister, id, dbValue, CachedNaturalIdValueSource.LOAD );
|
||||
return dbValue;
|
||||
}
|
||||
else {
|
||||
|
@ -343,7 +347,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
for ( int i = 0; i < props.length; i++ ) {
|
||||
naturalIdSnapshotSubSet[i] = entitySnapshot[ props[i] ];
|
||||
}
|
||||
cacheNaturalIdResolution( persister, id, naturalIdSnapshotSubSet );
|
||||
cacheNaturalIdResolution( persister, id, naturalIdSnapshotSubSet, CachedNaturalIdValueSource.LOAD );
|
||||
return naturalIdSnapshotSubSet;
|
||||
}
|
||||
}
|
||||
|
@ -1707,56 +1711,67 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
return;
|
||||
}
|
||||
|
||||
// extract the natural id values
|
||||
final int[] naturalIdPropertyIndexes = persister.getNaturalIdentifierProperties();
|
||||
final Object[] naturalIdValues = new Object[ naturalIdPropertyIndexes.length ];
|
||||
int i = 0;
|
||||
for ( int naturalIdPropertyIndex : naturalIdPropertyIndexes ) {
|
||||
naturalIdValues[i++] = entityEntry.getLoadedState()[ naturalIdPropertyIndex ];
|
||||
}
|
||||
final Object[] naturalIdValues = getNaturalIdValues( entityEntry, persister );
|
||||
|
||||
// re-cache
|
||||
cacheNaturalIdResolution( persister, entityEntry.getId(), naturalIdValues );
|
||||
cacheNaturalIdResolution( persister, entityEntry.getId(), naturalIdValues, CachedNaturalIdValueSource.UPDATE );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadedStateDeletedNotification(EntityEntry entityEntry) {
|
||||
final EntityPersister persister = entityEntry.getPersister();
|
||||
if ( ! persister.hasNaturalIdentifier() ) {
|
||||
// nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
final Object[] naturalIdValues = getNaturalIdValues( entityEntry, persister );
|
||||
|
||||
// evict from cache
|
||||
evictNaturalIdResolution( persister, entityEntry.getId(), naturalIdValues );
|
||||
}
|
||||
|
||||
private class NaturalId {
|
||||
private final EntityPersister persister;
|
||||
private final Object[] values;
|
||||
|
||||
private NaturalId(EntityPersister persister, Object[] values) {
|
||||
this.persister = persister;
|
||||
this.values = values;
|
||||
@Override
|
||||
public void loadedStateInsertedNotification(EntityEntry entityEntry) {
|
||||
final EntityPersister persister = entityEntry.getPersister();
|
||||
if ( ! persister.hasNaturalIdentifier() ) {
|
||||
// nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
public EntityPersister getPersister() {
|
||||
return persister;
|
||||
final Object[] naturalIdValues = getNaturalIdValues( entityEntry, persister );
|
||||
|
||||
// cache
|
||||
cacheNaturalIdResolution( persister, entityEntry.getId(), naturalIdValues, CachedNaturalIdValueSource.INSERT );
|
||||
}
|
||||
|
||||
private Object[] getNaturalIdValues(EntityEntry entityEntry, EntityPersister persister) {
|
||||
final int[] naturalIdPropertyIndexes = persister.getNaturalIdentifierProperties();
|
||||
final Object[] naturalIdValues = new Object[naturalIdPropertyIndexes.length];
|
||||
|
||||
final Object[] loadedState = entityEntry.getLoadedState();
|
||||
for ( int i = 0; i < naturalIdPropertyIndexes.length; i++ ) {
|
||||
naturalIdValues[i] = loadedState[naturalIdPropertyIndexes[i]];
|
||||
}
|
||||
|
||||
public Object[] getValues() {
|
||||
return values;
|
||||
return naturalIdValues;
|
||||
}
|
||||
|
||||
private NaturalIdCacheKey getNaturalIdCacheKey(Object[] naturalIdValues, EntityPersister persister) {
|
||||
final int[] naturalIdPropertyIndexes = persister.getNaturalIdentifierProperties();
|
||||
|
||||
final Serializable[] naturalIdKeyValues = new Serializable[naturalIdPropertyIndexes.length];
|
||||
final Type[] naturalIdTypes = new Type[naturalIdPropertyIndexes.length];
|
||||
|
||||
final Type[] propertyTypes = persister.getPropertyTypes();
|
||||
|
||||
for ( int i = 0; i < naturalIdPropertyIndexes.length; i++ ) {
|
||||
naturalIdTypes[i] = propertyTypes[naturalIdPropertyIndexes[i]];
|
||||
naturalIdKeyValues[i] = naturalIdTypes[i].disassemble( naturalIdValues[i], session, null );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if ( this == other ) {
|
||||
return true;
|
||||
}
|
||||
if ( other == null || getClass() != other.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final NaturalId that = (NaturalId) other;
|
||||
return persister.equals( that.persister )
|
||||
&& Arrays.equals( values, that.values );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = persister.hashCode();
|
||||
result = 31 * result + Arrays.hashCode( values );
|
||||
return result;
|
||||
}
|
||||
return new NaturalIdCacheKey( naturalIdKeyValues, naturalIdTypes, persister.getEntityName(),
|
||||
session.getTenantIdentifier(), session.getFactory() );
|
||||
}
|
||||
|
||||
private class NaturalIdResolutionCache implements Serializable {
|
||||
|
@ -1770,8 +1785,8 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
return persister;
|
||||
}
|
||||
|
||||
private Map<Serializable,NaturalId> pkToNaturalIdMap = new ConcurrentHashMap<Serializable, NaturalId>();
|
||||
private Map<NaturalId,Serializable> naturalIdToPkMap = new ConcurrentHashMap<NaturalId,Serializable>();
|
||||
private Map<Serializable,NaturalIdCacheKey> pkToNaturalIdMap = new ConcurrentHashMap<Serializable, NaturalIdCacheKey>();
|
||||
private Map<NaturalIdCacheKey,Serializable> naturalIdToPkMap = new ConcurrentHashMap<NaturalIdCacheKey,Serializable>();
|
||||
}
|
||||
|
||||
private Map<EntityPersister,NaturalIdResolutionCache> naturalIdResolutionCacheMap
|
||||
|
@ -1785,8 +1800,19 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
return null;
|
||||
}
|
||||
else {
|
||||
final NaturalId naturalId = entityNaturalIdResolutionCache.pkToNaturalIdMap.get( pk );
|
||||
return naturalId == null ? null : naturalId.getValues();
|
||||
final NaturalIdCacheKey naturalIdCacheKey = entityNaturalIdResolutionCache.pkToNaturalIdMap.get( pk );
|
||||
if (naturalIdCacheKey == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Serializable[] naturalIdKeyValues = naturalIdCacheKey.getNaturalId();
|
||||
final Type[] types = naturalIdCacheKey.getTypes();
|
||||
Object[] naturalIdValues = new Object[naturalIdKeyValues.length];
|
||||
for (int i = 0; i < naturalIdKeyValues.length; i++) {
|
||||
naturalIdValues[i] = types[i].assemble( naturalIdKeyValues[i], session, null );
|
||||
}
|
||||
|
||||
return naturalIdValues;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1800,17 +1826,19 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
}
|
||||
|
||||
final NaturalIdResolutionCache entityNaturalIdResolutionCache = naturalIdResolutionCacheMap.get( persister );
|
||||
final NaturalIdCacheKey naturalIdCacheKey = getNaturalIdCacheKey( naturalIdValues, persister );
|
||||
if ( entityNaturalIdResolutionCache == null ) {
|
||||
return null;
|
||||
final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy = persister
|
||||
.getNaturalIdCacheAccessStrategy();
|
||||
return (Serializable) naturalIdCacheAccessStrategy.get( naturalIdCacheKey, session.getTimestamp() );
|
||||
}
|
||||
else {
|
||||
final NaturalId naturalId = new NaturalId( persister, naturalIdValues );
|
||||
return entityNaturalIdResolutionCache.naturalIdToPkMap.get( naturalId );
|
||||
return entityNaturalIdResolutionCache.naturalIdToPkMap.get( naturalIdCacheKey );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void cacheNaturalIdResolution(EntityPersister persister, Serializable pk, Object[] naturalIdValues) {
|
||||
public void cacheNaturalIdResolution(EntityPersister persister, final Serializable pk, Object[] naturalIdValues, CachedNaturalIdValueSource valueSource ) {
|
||||
if ( ! persister.hasNaturalIdentifier() ) {
|
||||
throw new IllegalArgumentException( "Entity did not define a natural-id" );
|
||||
}
|
||||
|
@ -1824,8 +1852,66 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
naturalIdResolutionCacheMap.put( persister, entityNaturalIdResolutionCache );
|
||||
}
|
||||
|
||||
final NaturalId naturalId = new NaturalId( persister, naturalIdValues );
|
||||
entityNaturalIdResolutionCache.pkToNaturalIdMap.put( pk, naturalId );
|
||||
entityNaturalIdResolutionCache.naturalIdToPkMap.put( naturalId, pk );
|
||||
final NaturalIdCacheKey naturalIdCacheKey = getNaturalIdCacheKey( naturalIdValues, persister );
|
||||
|
||||
entityNaturalIdResolutionCache.pkToNaturalIdMap.put( pk, naturalIdCacheKey );
|
||||
entityNaturalIdResolutionCache.naturalIdToPkMap.put( naturalIdCacheKey, pk );
|
||||
|
||||
final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy = persister.getNaturalIdCacheAccessStrategy();
|
||||
switch ( valueSource ) {
|
||||
case LOAD: {
|
||||
naturalIdCacheAccessStrategy.putFromLoad( naturalIdCacheKey, pk, session.getTimestamp(), null );
|
||||
break;
|
||||
}
|
||||
case INSERT: {
|
||||
naturalIdCacheAccessStrategy.insert( naturalIdCacheKey, pk );
|
||||
|
||||
( (EventSource) this.session ).getActionQueue().registerProcess( new AfterTransactionCompletionProcess() {
|
||||
@Override
|
||||
public void doAfterTransactionCompletion(boolean success, SessionImplementor session) {
|
||||
naturalIdCacheAccessStrategy.afterInsert( naturalIdCacheKey, pk );
|
||||
}
|
||||
} );
|
||||
|
||||
break;
|
||||
}
|
||||
case UPDATE: {
|
||||
final SoftLock lock = naturalIdCacheAccessStrategy.lockItem( naturalIdCacheKey, null );
|
||||
|
||||
naturalIdCacheAccessStrategy.update( naturalIdCacheKey, pk );
|
||||
|
||||
( (EventSource) this.session ).getActionQueue().registerProcess( new AfterTransactionCompletionProcess() {
|
||||
@Override
|
||||
public void doAfterTransactionCompletion(boolean success, SessionImplementor session) {
|
||||
naturalIdCacheAccessStrategy.afterUpdate( naturalIdCacheKey, pk, lock );
|
||||
}
|
||||
} );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictNaturalIdResolution(EntityPersister persister, final Serializable pk, Object[] naturalIdValues ) {
|
||||
if ( ! persister.hasNaturalIdentifier() ) {
|
||||
throw new IllegalArgumentException( "Entity did not define a natural-id" );
|
||||
}
|
||||
if ( persister.getNaturalIdentifierProperties().length != naturalIdValues.length ) {
|
||||
throw new IllegalArgumentException( "Mismatch between expected number of natural-id values and found." );
|
||||
}
|
||||
|
||||
NaturalIdResolutionCache entityNaturalIdResolutionCache = naturalIdResolutionCacheMap.get( persister );
|
||||
if ( entityNaturalIdResolutionCache == null ) {
|
||||
entityNaturalIdResolutionCache = new NaturalIdResolutionCache( persister );
|
||||
naturalIdResolutionCacheMap.put( persister, entityNaturalIdResolutionCache );
|
||||
}
|
||||
|
||||
final NaturalIdCacheKey naturalIdCacheKey = getNaturalIdCacheKey( naturalIdValues, persister );
|
||||
entityNaturalIdResolutionCache.pkToNaturalIdMap.remove( pk ); //Should I compare the value returned here with the naturalIdCacheKey parameter?
|
||||
entityNaturalIdResolutionCache.naturalIdToPkMap.remove( naturalIdCacheKey );
|
||||
|
||||
final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy = persister.getNaturalIdCacheAccessStrategy();
|
||||
naturalIdCacheAccessStrategy.evict( naturalIdCacheKey );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -252,6 +252,8 @@ public final class EntityEntry implements Serializable {
|
|||
previousStatus = status;
|
||||
status = Status.GONE;
|
||||
existsInDatabase = false;
|
||||
|
||||
notifyLoadedStateDeleted();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -260,6 +262,8 @@ public final class EntityEntry implements Serializable {
|
|||
*/
|
||||
public void postInsert() {
|
||||
existsInDatabase = true;
|
||||
|
||||
notifyLoadedStateInserted();
|
||||
}
|
||||
|
||||
public boolean isNullifiable(boolean earlyInsert, SessionImplementor session) {
|
||||
|
@ -377,6 +381,22 @@ public final class EntityEntry implements Serializable {
|
|||
|
||||
persistenceContext.loadedStateUpdatedNotification( this );
|
||||
}
|
||||
|
||||
private void notifyLoadedStateInserted() {
|
||||
if ( persistenceContext == null ) {
|
||||
throw new HibernateException( "PersistenceContext was null on attempt to insert loaded state" );
|
||||
}
|
||||
|
||||
persistenceContext.loadedStateInsertedNotification( this );
|
||||
}
|
||||
|
||||
private void notifyLoadedStateDeleted() {
|
||||
if ( persistenceContext == null ) {
|
||||
throw new HibernateException( "PersistenceContext was null on attempt to delete loaded state" );
|
||||
}
|
||||
|
||||
persistenceContext.loadedStateDeletedNotification( this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom serialization routine used during serialization of a
|
||||
|
|
|
@ -684,10 +684,25 @@ public interface PersistenceContext {
|
|||
public boolean wasInsertedDuringTransaction(EntityPersister persister, Serializable id);
|
||||
|
||||
public void loadedStateUpdatedNotification(EntityEntry entityEntry);
|
||||
|
||||
public void loadedStateInsertedNotification(EntityEntry entityEntry);
|
||||
|
||||
public void loadedStateDeletedNotification(EntityEntry entityEntry);
|
||||
|
||||
public Object[] findCachedNaturalId(EntityPersister persister, Serializable pk);
|
||||
|
||||
public Serializable findCachedNaturalIdResolution(EntityPersister persister, Object[] naturalId);
|
||||
|
||||
public void cacheNaturalIdResolution(EntityPersister persister, Serializable pk, Object[] naturalId);
|
||||
/**
|
||||
* The type of action the cache call is originating from
|
||||
*/
|
||||
public enum CachedNaturalIdValueSource {
|
||||
LOAD,
|
||||
INSERT,
|
||||
UPDATE
|
||||
}
|
||||
|
||||
public void cacheNaturalIdResolution(EntityPersister persister, Serializable pk, Object[] naturalId, CachedNaturalIdValueSource valueSource);
|
||||
|
||||
public void evictNaturalIdResolution(EntityPersister persister, final Serializable pk, Object[] naturalIdValues );
|
||||
}
|
||||
|
|
|
@ -26,10 +26,7 @@ package org.hibernate.event.internal;
|
|||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cache.spi.CacheKey;
|
||||
import org.hibernate.cache.spi.entry.CacheEntry;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.engine.spi.PersistenceContext.CachedNaturalIdValueSource;
|
||||
import org.hibernate.event.spi.ResolveNaturalIdEvent;
|
||||
import org.hibernate.event.spi.ResolveNaturalIdEventListener;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
@ -97,19 +94,6 @@ public class DefaultResolveNaturalIdEventListener
|
|||
return entityId;
|
||||
}
|
||||
|
||||
entityId = loadFromSecondLevelCache( event );
|
||||
if ( entityId != null ) {
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.trace(
|
||||
"Resolved object in second-level cache: " +
|
||||
MessageHelper.infoString(
|
||||
persister, event.getNaturalIdValues(), event.getSession().getFactory()
|
||||
)
|
||||
);
|
||||
}
|
||||
return entityId;
|
||||
}
|
||||
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.trace(
|
||||
"Object not resolved in any cache: " +
|
||||
|
@ -136,48 +120,6 @@ public class DefaultResolveNaturalIdEventListener
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to load the entity from the second-level cache.
|
||||
*
|
||||
* @param event The event
|
||||
*
|
||||
* @return The entity from the second-level cache, or null.
|
||||
*/
|
||||
protected Serializable loadFromSecondLevelCache(final ResolveNaturalIdEvent event) {
|
||||
// final SessionImplementor source = event.getSession();
|
||||
//
|
||||
// EntityPersister persister = event.getEntityPersister();
|
||||
//
|
||||
// final boolean useCache = persister.hasCache() && source.getCacheMode().isGetEnabled();
|
||||
//
|
||||
// if ( useCache ) {
|
||||
//
|
||||
// final SessionFactoryImplementor factory = source.getFactory();
|
||||
//
|
||||
// final CacheKey ck = source.generateCacheKey( event.getNaturalIdValues(), persister.getIdentifierType(),
|
||||
// persister.getRootEntityName() );
|
||||
// Object ce = persister.getCacheAccessStrategy().get( ck, source.getTimestamp() );
|
||||
// if ( factory.getStatistics().isStatisticsEnabled() ) {
|
||||
// if ( ce == null ) {
|
||||
// factory.getStatisticsImplementor().secondLevelCacheMiss(
|
||||
// persister.getCacheAccessStrategy().getRegion().getName() );
|
||||
// }
|
||||
// else {
|
||||
// factory.getStatisticsImplementor().secondLevelCacheHit(
|
||||
// persister.getCacheAccessStrategy().getRegion().getName() );
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if ( ce != null ) {
|
||||
// CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure().destructure( ce, factory );
|
||||
//
|
||||
// // Entity was found in second-level cache...
|
||||
// return assembleCacheEntry( entry, event.getEntityId(), persister, event );
|
||||
// }
|
||||
// }
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the process of loading an entity from the configured
|
||||
* underlying datasource.
|
||||
|
@ -195,7 +137,8 @@ public class DefaultResolveNaturalIdEventListener
|
|||
event.getSession().getPersistenceContext().cacheNaturalIdResolution(
|
||||
event.getEntityPersister(),
|
||||
pk,
|
||||
event.getOrderedNaturalIdValues()
|
||||
event.getOrderedNaturalIdValues(),
|
||||
CachedNaturalIdValueSource.LOAD
|
||||
);
|
||||
return pk;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.hibernate.ScrollableResults;
|
|||
import org.hibernate.SessionException;
|
||||
import org.hibernate.SharedSessionContract;
|
||||
import org.hibernate.cache.spi.CacheKey;
|
||||
import org.hibernate.cache.spi.NaturalIdCacheKey;
|
||||
import org.hibernate.engine.jdbc.LobCreationContext;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
|
||||
import org.hibernate.engine.query.spi.HQLQueryPlan;
|
||||
|
|
|
@ -350,26 +350,29 @@ public final class SessionFactoryImpl
|
|||
allCacheRegions.put( cacheRegionName, entityRegion );
|
||||
}
|
||||
}
|
||||
EntityPersister cp = serviceRegistry.getService( PersisterFactory.class ).createEntityPersister(
|
||||
model,
|
||||
accessStrategy,
|
||||
this,
|
||||
mapping
|
||||
);
|
||||
entityPersisters.put( model.getEntityName(), cp );
|
||||
classMeta.put( model.getEntityName(), cp.getClassMetadata() );
|
||||
|
||||
if ( cp.hasNaturalIdentifier() && model.getNaturalIdCacheRegionName() != null ) {
|
||||
NaturalIdRegionAccessStrategy naturalIdAccessStrategy = null;
|
||||
if ( model.hasNaturalId() && model.getNaturalIdCacheRegionName() != null ) {
|
||||
final String naturalIdCacheRegionName = cacheRegionPrefix + model.getNaturalIdCacheRegionName();
|
||||
NaturalIdRegionAccessStrategy naturalIdAccessStrategy = ( NaturalIdRegionAccessStrategy ) entityAccessStrategies.get( naturalIdCacheRegionName );
|
||||
naturalIdAccessStrategy = ( NaturalIdRegionAccessStrategy ) entityAccessStrategies.get( naturalIdCacheRegionName );
|
||||
|
||||
if ( naturalIdAccessStrategy == null && settings.isSecondLevelCacheEnabled() ) {
|
||||
final NaturalIdRegion naturalIdRegion = settings.getRegionFactory().buildNaturalIdRegion( naturalIdCacheRegionName, properties, CacheDataDescriptionImpl.decode( cp ) );
|
||||
final NaturalIdRegion naturalIdRegion = settings.getRegionFactory().buildNaturalIdRegion( naturalIdCacheRegionName, properties, CacheDataDescriptionImpl.decode( model ) );
|
||||
naturalIdAccessStrategy = naturalIdRegion.buildAccessStrategy( settings.getRegionFactory().getDefaultAccessType() );
|
||||
entityAccessStrategies.put( naturalIdCacheRegionName, naturalIdAccessStrategy );
|
||||
allCacheRegions.put( naturalIdCacheRegionName, naturalIdRegion );
|
||||
}
|
||||
}
|
||||
|
||||
EntityPersister cp = serviceRegistry.getService( PersisterFactory.class ).createEntityPersister(
|
||||
model,
|
||||
accessStrategy,
|
||||
naturalIdAccessStrategy,
|
||||
this,
|
||||
mapping
|
||||
);
|
||||
entityPersisters.put( model.getEntityName(), cp );
|
||||
classMeta.put( model.getEntityName(), cp.getClassMetadata() );
|
||||
}
|
||||
this.classMetadata = Collections.unmodifiableMap(classMeta);
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ import org.hibernate.bytecode.instrumentation.spi.LazyPropertyInitializer;
|
|||
import org.hibernate.bytecode.spi.EntityInstrumentationMetadata;
|
||||
import org.hibernate.cache.spi.CacheKey;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.entry.CacheEntry;
|
||||
import org.hibernate.cache.spi.entry.CacheEntryStructure;
|
||||
import org.hibernate.cache.spi.entry.StructuredCacheEntry;
|
||||
|
@ -140,6 +141,7 @@ public abstract class AbstractEntityPersister
|
|||
// moved up from AbstractEntityPersister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
private final SessionFactoryImplementor factory;
|
||||
private final EntityRegionAccessStrategy cacheAccessStrategy;
|
||||
private final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy;
|
||||
private final boolean isLazyPropertiesCacheable;
|
||||
private final CacheEntryStructure cacheEntryStructure;
|
||||
private final EntityMetamodel entityMetamodel;
|
||||
|
@ -485,11 +487,13 @@ public abstract class AbstractEntityPersister
|
|||
public AbstractEntityPersister(
|
||||
final PersistentClass persistentClass,
|
||||
final EntityRegionAccessStrategy cacheAccessStrategy,
|
||||
final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy,
|
||||
final SessionFactoryImplementor factory) throws HibernateException {
|
||||
|
||||
// moved up from AbstractEntityPersister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
this.factory = factory;
|
||||
this.cacheAccessStrategy = cacheAccessStrategy;
|
||||
this.naturalIdRegionAccessStrategy = naturalIdRegionAccessStrategy;
|
||||
isLazyPropertiesCacheable = persistentClass.isLazyPropertiesCacheable();
|
||||
this.cacheEntryStructure = factory.getSettings().isStructuredCacheEntriesEnabled() ?
|
||||
(CacheEntryStructure) new StructuredCacheEntry(this) :
|
||||
|
@ -770,9 +774,11 @@ public abstract class AbstractEntityPersister
|
|||
public AbstractEntityPersister(
|
||||
final EntityBinding entityBinding,
|
||||
final EntityRegionAccessStrategy cacheAccessStrategy,
|
||||
final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy,
|
||||
final SessionFactoryImplementor factory) throws HibernateException {
|
||||
this.factory = factory;
|
||||
this.cacheAccessStrategy = cacheAccessStrategy;
|
||||
this.naturalIdRegionAccessStrategy = naturalIdRegionAccessStrategy;
|
||||
this.isLazyPropertiesCacheable =
|
||||
entityBinding.getHierarchyDetails().getCaching() == null ?
|
||||
false :
|
||||
|
@ -3895,6 +3901,10 @@ public abstract class AbstractEntityPersister
|
|||
public CacheEntryStructure getCacheEntryStructure() {
|
||||
return cacheEntryStructure;
|
||||
}
|
||||
|
||||
public NaturalIdRegionAccessStrategy getNaturalIdCacheAccessStrategy() {
|
||||
return naturalIdRegionAccessStrategy;
|
||||
}
|
||||
|
||||
public Comparator getVersionComparator() {
|
||||
return isVersioned() ? getVersionType().getComparator() : null;
|
||||
|
|
|
@ -31,10 +31,10 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.NaturalId;
|
||||
import org.hibernate.bytecode.spi.EntityInstrumentationMetadata;
|
||||
import org.hibernate.cache.spi.OptimisticCacheSource;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.entry.CacheEntryStructure;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -474,6 +474,11 @@ public interface EntityPersister extends OptimisticCacheSource {
|
|||
* Get the cache structure
|
||||
*/
|
||||
public CacheEntryStructure getCacheEntryStructure();
|
||||
|
||||
/**
|
||||
* Get the NaturalId cache (optional operation)
|
||||
*/
|
||||
public NaturalIdRegionAccessStrategy getNaturalIdCacheAccessStrategy();
|
||||
|
||||
/**
|
||||
* Get the user-visible metadata for the class (optional operation)
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.engine.OptimisticLockStyle;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
|
@ -121,10 +122,11 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
public JoinedSubclassEntityPersister(
|
||||
final PersistentClass persistentClass,
|
||||
final EntityRegionAccessStrategy cacheAccessStrategy,
|
||||
final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy,
|
||||
final SessionFactoryImplementor factory,
|
||||
final Mapping mapping) throws HibernateException {
|
||||
|
||||
super( persistentClass, cacheAccessStrategy, factory );
|
||||
super( persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory );
|
||||
|
||||
// DISCRIMINATOR
|
||||
|
||||
|
@ -505,9 +507,10 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
public JoinedSubclassEntityPersister(
|
||||
final EntityBinding entityBinding,
|
||||
final EntityRegionAccessStrategy cacheAccessStrategy,
|
||||
final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy,
|
||||
final SessionFactoryImplementor factory,
|
||||
final Mapping mapping) throws HibernateException {
|
||||
super( entityBinding, cacheAccessStrategy, factory );
|
||||
super( entityBinding, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory );
|
||||
// TODO: implement!!! initializing final fields to null to make compiler happy
|
||||
tableSpan = -1;
|
||||
tableNames = null;
|
||||
|
|
|
@ -33,6 +33,7 @@ import java.util.Map;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -136,10 +137,11 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
public SingleTableEntityPersister(
|
||||
final PersistentClass persistentClass,
|
||||
final EntityRegionAccessStrategy cacheAccessStrategy,
|
||||
final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy,
|
||||
final SessionFactoryImplementor factory,
|
||||
final Mapping mapping) throws HibernateException {
|
||||
|
||||
super( persistentClass, cacheAccessStrategy, factory );
|
||||
super( persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory );
|
||||
|
||||
// CLASS + TABLE
|
||||
|
||||
|
@ -451,10 +453,11 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
public SingleTableEntityPersister(
|
||||
final EntityBinding entityBinding,
|
||||
final EntityRegionAccessStrategy cacheAccessStrategy,
|
||||
final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy,
|
||||
final SessionFactoryImplementor factory,
|
||||
final Mapping mapping) throws HibernateException {
|
||||
|
||||
super( entityBinding, cacheAccessStrategy, factory );
|
||||
super( entityBinding, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory );
|
||||
|
||||
// CLASS + TABLE
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
|
@ -82,10 +83,11 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
|||
public UnionSubclassEntityPersister(
|
||||
final PersistentClass persistentClass,
|
||||
final EntityRegionAccessStrategy cacheAccessStrategy,
|
||||
final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy,
|
||||
final SessionFactoryImplementor factory,
|
||||
final Mapping mapping) throws HibernateException {
|
||||
|
||||
super( persistentClass, cacheAccessStrategy, factory );
|
||||
super( persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory );
|
||||
|
||||
if ( getIdentifierGenerator() instanceof IdentityGenerator ) {
|
||||
throw new MappingException(
|
||||
|
@ -241,9 +243,10 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
|||
public UnionSubclassEntityPersister(
|
||||
final EntityBinding entityBinding,
|
||||
final EntityRegionAccessStrategy cacheAccessStrategy,
|
||||
final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy,
|
||||
final SessionFactoryImplementor factory,
|
||||
final Mapping mapping) throws HibernateException {
|
||||
super(entityBinding, cacheAccessStrategy, factory );
|
||||
super(entityBinding, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory );
|
||||
// TODO: implement!!! initializing final fields to null to make compiler happy.
|
||||
subquery = null;
|
||||
tableName = null;
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -77,6 +78,7 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi
|
|||
public static final Class[] ENTITY_PERSISTER_CONSTRUCTOR_ARGS_NEW = new Class[] {
|
||||
EntityBinding.class,
|
||||
EntityRegionAccessStrategy.class,
|
||||
NaturalIdRegionAccessStrategy.class,
|
||||
SessionFactoryImplementor.class,
|
||||
Mapping.class
|
||||
};
|
||||
|
@ -122,13 +124,14 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi
|
|||
public EntityPersister createEntityPersister(
|
||||
PersistentClass metadata,
|
||||
EntityRegionAccessStrategy cacheAccessStrategy,
|
||||
NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy,
|
||||
SessionFactoryImplementor factory,
|
||||
Mapping cfg) {
|
||||
Class<? extends EntityPersister> persisterClass = metadata.getEntityPersisterClass();
|
||||
if ( persisterClass == null ) {
|
||||
persisterClass = serviceRegistry.getService( PersisterClassResolver.class ).getEntityPersisterClass( metadata );
|
||||
}
|
||||
return create( persisterClass, ENTITY_PERSISTER_CONSTRUCTOR_ARGS, metadata, cacheAccessStrategy, factory, cfg );
|
||||
return create( persisterClass, ENTITY_PERSISTER_CONSTRUCTOR_ARGS, metadata, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory, cfg );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -141,7 +144,7 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi
|
|||
if ( persisterClass == null ) {
|
||||
persisterClass = serviceRegistry.getService( PersisterClassResolver.class ).getEntityPersisterClass( metadata );
|
||||
}
|
||||
return create( persisterClass, ENTITY_PERSISTER_CONSTRUCTOR_ARGS_NEW, metadata, cacheAccessStrategy, factory, cfg );
|
||||
return create( persisterClass, ENTITY_PERSISTER_CONSTRUCTOR_ARGS_NEW, metadata, cacheAccessStrategy, null, factory, cfg );
|
||||
}
|
||||
|
||||
// TODO: change metadata arg type to EntityBinding when new metadata is integrated
|
||||
|
@ -150,12 +153,13 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi
|
|||
Class[] persisterConstructorArgs,
|
||||
Object metadata,
|
||||
EntityRegionAccessStrategy cacheAccessStrategy,
|
||||
NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy,
|
||||
SessionFactoryImplementor factory,
|
||||
Mapping cfg) throws HibernateException {
|
||||
try {
|
||||
Constructor<? extends EntityPersister> constructor = persisterClass.getConstructor( persisterConstructorArgs );
|
||||
try {
|
||||
return constructor.newInstance( metadata, cacheAccessStrategy, factory, cfg );
|
||||
return constructor.newInstance( metadata, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory, cfg );
|
||||
}
|
||||
catch (MappingException e) {
|
||||
throw e;
|
||||
|
|
|
@ -26,6 +26,7 @@ package org.hibernate.persister.spi;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -69,6 +70,7 @@ public interface PersisterFactory extends Service {
|
|||
public EntityPersister createEntityPersister(
|
||||
PersistentClass model,
|
||||
EntityRegionAccessStrategy cacheAccessStrategy,
|
||||
NaturalIdRegionAccessStrategy naturalIdAccessStrategy,
|
||||
SessionFactoryImplementor factory,
|
||||
Mapping cfg) throws HibernateException;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.hibernate.test.annotations.persister;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
|
@ -11,7 +12,8 @@ import org.hibernate.persister.entity.SingleTableEntityPersister;
|
|||
*/
|
||||
public class EntityPersister extends SingleTableEntityPersister {
|
||||
public EntityPersister(PersistentClass persistentClass, EntityRegionAccessStrategy cache,
|
||||
SessionFactoryImplementor factory, Mapping cfg) throws HibernateException {
|
||||
super( persistentClass, cache, factory, cfg );
|
||||
NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy,
|
||||
SessionFactoryImplementor factory, Mapping cfg) throws HibernateException {
|
||||
super( persistentClass, cache, naturalIdRegionAccessStrategy, factory, cfg );
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@ import org.hibernate.MappingException;
|
|||
import org.hibernate.bytecode.spi.EntityInstrumentationMetadata;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.entry.CacheEntryStructure;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
|
@ -381,6 +382,11 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
|
|||
public EntityRegionAccessStrategy getCacheAccessStrategy() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NaturalIdRegionAccessStrategy getNaturalIdCacheAccessStrategy() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CacheEntryStructure getCacheEntryStructure() {
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.hibernate.LockOptions;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.bytecode.spi.EntityInstrumentationMetadata;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.entry.CacheEntryStructure;
|
||||
import org.hibernate.cache.spi.entry.UnstructuredCacheEntry;
|
||||
import org.hibernate.engine.internal.TwoPhaseLoad;
|
||||
|
@ -441,6 +442,10 @@ public class CustomPersister implements EntityPersister {
|
|||
public EntityRegionAccessStrategy getCacheAccessStrategy() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public NaturalIdRegionAccessStrategy getNaturalIdCacheAccessStrategy() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getRootEntityName() {
|
||||
return "CUSTOMS";
|
||||
|
|
Loading…
Reference in New Issue