HHH-11356 - Adjust the 2nd-Cache SPIs to better reflect supported uses
HHH-12323 - Update Statistics API and SPI based on changes to 2nd level caching changes
This commit is contained in:
parent
24a078732c
commit
f432ecea68
|
@ -26,10 +26,9 @@ import org.hibernate.cache.ehcache.EhCacheRegionFactory;
|
|||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.jpa.QueryHints;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.stat.SecondLevelCacheStatistics;
|
||||
import org.hibernate.stat.CacheRegionStatistics;
|
||||
import org.hibernate.stat.Statistics;
|
||||
|
||||
import org.hibernate.testing.FailureExpected;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -188,8 +187,8 @@ public class SecondLevelCacheTest extends BaseEntityManagerFunctionalTestCase {
|
|||
Session session = entityManager.unwrap( Session.class );
|
||||
//tag::caching-statistics-example[]
|
||||
Statistics statistics = session.getSessionFactory().getStatistics();
|
||||
SecondLevelCacheStatistics secondLevelCacheStatistics =
|
||||
statistics.getSecondLevelCacheStatistics( "query.cache.person" );
|
||||
CacheRegionStatistics secondLevelCacheStatistics =
|
||||
statistics.getDomainDataRegionStatistics( "query.cache.person" );
|
||||
long hitCount = secondLevelCacheStatistics.getHitCount();
|
||||
long missCount = secondLevelCacheStatistics.getMissCount();
|
||||
double hitRatio = (double) hitCount / ( hitCount + missCount );
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.userguide.persister;
|
|||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.persister.collection.OneToManyPersister;
|
||||
import org.hibernate.persister.spi.PersisterCreationContext;
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
package org.hibernate.userguide.persister;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.persister.entity.SingleTableEntityPersister;
|
||||
import org.hibernate.persister.spi.PersisterCreationContext;
|
||||
|
|
|
@ -18,6 +18,7 @@ import java.io.Serializable;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@SuppressWarnings( {"UnusedDeclaration"})
|
||||
public interface Cache extends javax.persistence.Cache {
|
||||
/**
|
||||
* Access to the SessionFactory this Cache is bound to.
|
||||
|
@ -26,6 +27,11 @@ public interface Cache extends javax.persistence.Cache {
|
|||
*/
|
||||
SessionFactory getSessionFactory();
|
||||
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Entity data
|
||||
|
||||
/**
|
||||
* Determine whether the cache contains data for the given entity "instance".
|
||||
* <p/>
|
||||
|
@ -58,59 +64,83 @@ public interface Cache extends javax.persistence.Cache {
|
|||
*
|
||||
* @param entityClass The entity class.
|
||||
* @param identifier The entity identifier
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
void evictEntity(Class entityClass, Serializable identifier);
|
||||
void evictEntityData(Class entityClass, Serializable identifier);
|
||||
|
||||
/**
|
||||
* Evicts the entity data for a particular entity "instance".
|
||||
*
|
||||
* @param entityName The entity name.
|
||||
* @param identifier The entity identifier
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
void evictEntity(String entityName, Serializable identifier);
|
||||
void evictEntityData(String entityName, Serializable identifier);
|
||||
|
||||
/**
|
||||
* Evicts all entity data from the given region (i.e. for all entities of
|
||||
* type).
|
||||
*
|
||||
* @param entityClass The entity class.
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
void evictEntityRegion(Class entityClass);
|
||||
void evictEntityData(Class entityClass);
|
||||
|
||||
/**
|
||||
* Evicts all entity data from the given region (i.e. for all entities of
|
||||
* type).
|
||||
*
|
||||
* @param entityName The entity name.
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
void evictEntityRegion(String entityName);
|
||||
void evictEntityData(String entityName);
|
||||
|
||||
/**
|
||||
* Evict data from all entity regions.
|
||||
*/
|
||||
void evictEntityRegions();
|
||||
|
||||
/**
|
||||
* Evicts all naturalId data from the given region (i.e. for all entities of
|
||||
* type).
|
||||
*
|
||||
* @param naturalIdClass The naturalId class.
|
||||
* @since 5.3
|
||||
*/
|
||||
@SuppressWarnings( {"UnusedDeclaration"})
|
||||
void evictNaturalIdRegion(Class naturalIdClass);
|
||||
void evictEntityData();
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Natural-id data
|
||||
|
||||
|
||||
/**
|
||||
* Evicts all naturalId data from the given region (i.e. for all entities of
|
||||
* type).
|
||||
* Evict cached data for the given entity's natural-id
|
||||
*
|
||||
* @param naturalIdName The naturalId name.
|
||||
* @param entityClass The entity class.
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
void evictNaturalIdRegion(String naturalIdName);
|
||||
void evictNaturalIdData(Class entityClass);
|
||||
|
||||
/**
|
||||
* Evict data from all naturalId regions.
|
||||
* Evict cached data for the given entity's natural-id
|
||||
*
|
||||
* @param entityName The entity name.
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
void evictNaturalIdRegions();
|
||||
void evictNaturalIdData(String entityName);
|
||||
|
||||
/**
|
||||
* Evict cached data for all natural-ids (for all entities)
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
void evictNaturalIdData();
|
||||
|
||||
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Collection data
|
||||
|
||||
/**
|
||||
* Determine whether the cache contains data for the given collection.
|
||||
|
@ -128,26 +158,38 @@ public interface Cache extends javax.persistence.Cache {
|
|||
@SuppressWarnings( {"UnusedDeclaration"})
|
||||
boolean containsCollection(String role, Serializable ownerIdentifier);
|
||||
|
||||
|
||||
/**
|
||||
* Evicts the cache data for the given identified collection instance.
|
||||
* Evicts the cache data for the given identified collection "instance"
|
||||
*
|
||||
* @param role The "collection role" (in form [owner-entity-name].[collection-property-name]).
|
||||
* @param ownerIdentifier The identifier of the owning entity
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
void evictCollection(String role, Serializable ownerIdentifier);
|
||||
void evictCollectionData(String role, Serializable ownerIdentifier);
|
||||
|
||||
/**
|
||||
* Evicts all entity data from the given region (i.e. evicts cached data
|
||||
* for all of the specified collection role).
|
||||
* Evicts cached data for the given collection role
|
||||
*
|
||||
* @param role The "collection role" (in form [owner-entity-name].[collection-property-name]).
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
void evictCollectionRegion(String role);
|
||||
void evictCollectionData(String role);
|
||||
|
||||
/**
|
||||
* Evict data from all collection regions.
|
||||
* Evict cache data for all collections
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
void evictCollectionRegions();
|
||||
void evictCollectionData();
|
||||
|
||||
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Query result data
|
||||
|
||||
/**
|
||||
* Determine whether the cache contains data for the given query.
|
||||
|
@ -159,7 +201,6 @@ public interface Cache extends javax.persistence.Cache {
|
|||
*
|
||||
* @return True if the underlying cache contains corresponding data; false otherwise.
|
||||
*/
|
||||
@SuppressWarnings( {"UnusedDeclaration"})
|
||||
boolean containsQuery(String regionName);
|
||||
|
||||
/**
|
||||
|
@ -178,9 +219,181 @@ public interface Cache extends javax.persistence.Cache {
|
|||
* Evict data from all query regions.
|
||||
*/
|
||||
void evictQueryRegions();
|
||||
|
||||
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Misc
|
||||
|
||||
/**
|
||||
* Evict all data from the cache.
|
||||
* Evict all data from the named cache region
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
void evictAllRegions();
|
||||
void evictRegion(String regionName);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @apiNote Hibernate impl - we only evict entity data here in keeping
|
||||
* with the JPA intent (JPA only defines caching for entity data). For
|
||||
* evicting all cache regions (collections, natural-ids and query results),
|
||||
* use {@link #evictAllRegions} instead.
|
||||
*/
|
||||
@Override
|
||||
default void evictAll() {
|
||||
// Evict only the "JPA cache", which is purely defined as the entity regions.
|
||||
evictEntityData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Evict data from all cache regions.
|
||||
*/
|
||||
default void evictAllRegions() {
|
||||
evictEntityData();
|
||||
evictNaturalIdData();
|
||||
evictCollectionData();
|
||||
evictDefaultQueryRegion();
|
||||
evictQueryRegions();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Deprecations (5.3)
|
||||
|
||||
/**
|
||||
* Evicts the entity data for a particular entity "instance".
|
||||
*
|
||||
* @param entityClass The entity class.
|
||||
* @param identifier The entity identifier
|
||||
*
|
||||
* @deprecated Use {@link Cache#evictEntityData(Class, Serializable)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
default void evictEntity(Class entityClass, Serializable identifier) {
|
||||
evictEntityData( entityClass, identifier );
|
||||
}
|
||||
|
||||
/**
|
||||
* Evicts the entity data for a particular entity "instance".
|
||||
*
|
||||
* @param entityName The entity name.
|
||||
* @param identifier The entity identifier
|
||||
*
|
||||
* @deprecated Use {@link Cache#evictEntityData(String, Serializable)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
default void evictEntity(String entityName, Serializable identifier) {
|
||||
evictEntityData( entityName, identifier );
|
||||
}
|
||||
|
||||
/**
|
||||
* Evicts all entity data from the given region (i.e. for all entities of
|
||||
* type).
|
||||
*
|
||||
* @param entityClass The entity class.
|
||||
*
|
||||
* @deprecated Use {@link Cache#evictEntityData(Class)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
default void evictEntityRegion(Class entityClass) {
|
||||
evictEntityData( entityClass );
|
||||
}
|
||||
|
||||
/**
|
||||
* Evicts all entity data from the given region (i.e. for all entities of
|
||||
* type).
|
||||
*
|
||||
* @param entityName The entity name.
|
||||
*
|
||||
* @deprecated Use {@link Cache#evictEntityData(String)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
default void evictEntityRegion(String entityName) {
|
||||
evictEntityData( entityName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Evict data from all entity regions.
|
||||
*
|
||||
* @deprecated Use {@link Cache#evictEntityData()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
default void evictEntityRegions() {
|
||||
evictEntityData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Evicts all naturalId data from the given region (i.e. for all entities of
|
||||
* type).
|
||||
*
|
||||
* @param entityClass The entity class.
|
||||
*
|
||||
* @deprecated Use {@link Cache#evictNaturalIdData(Class)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
default void evictNaturalIdRegion(Class entityClass) {
|
||||
evictNaturalIdData( entityClass );
|
||||
}
|
||||
|
||||
/**
|
||||
* Evicts all naturalId data from the given region (i.e. for all entities of
|
||||
* type).
|
||||
*
|
||||
* @param entityName The entity name.
|
||||
*
|
||||
* @deprecated Use {@link Cache#evictNaturalIdData(String)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
default void evictNaturalIdRegion(String entityName) {
|
||||
evictNaturalIdData( entityName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Evict data from all naturalId regions.
|
||||
*
|
||||
* @deprecated Use {@link Cache#evictNaturalIdData()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
default void evictNaturalIdRegions() {
|
||||
evictNaturalIdData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Evicts the cache data for the given identified collection instance.
|
||||
*
|
||||
* @param role The "collection role" (in form [owner-entity-name].[collection-property-name]).
|
||||
* @param ownerIdentifier The identifier of the owning entity
|
||||
*
|
||||
* @deprecated Use {@link Cache#evictCollectionData(String, Serializable)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
default void evictCollection(String role, Serializable ownerIdentifier) {
|
||||
evictCollectionData( role, ownerIdentifier );
|
||||
}
|
||||
|
||||
/**
|
||||
* Evicts all entity data from the given region (i.e. evicts cached data
|
||||
* for all of the specified collection role).
|
||||
*
|
||||
* @param role The "collection role" (in form [owner-entity-name].[collection-property-name]).
|
||||
*
|
||||
* @deprecated Use {@link Cache#evictCollectionData(String)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
default void evictCollectionRegion(String role) {
|
||||
evictCollectionData( role );
|
||||
}
|
||||
|
||||
/**
|
||||
* Evict data from all collection regions.
|
||||
*
|
||||
* @deprecated Use {@link Cache#evictCollectionData()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
default void evictCollectionRegions() {
|
||||
evictCollectionData();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,9 +16,9 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.action.spi.AfterTransactionCompletionProcess;
|
||||
import org.hibernate.action.spi.BeforeTransactionCompletionProcess;
|
||||
import org.hibernate.action.spi.Executable;
|
||||
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.access.CollectionDataAccess;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
@ -62,10 +62,15 @@ public class BulkOperationCleanupAction implements Executable, Serializable {
|
|||
spacesList.addAll( Arrays.asList( (String[]) persister.getQuerySpaces() ) );
|
||||
|
||||
if ( persister.canWriteToCache() ) {
|
||||
entityCleanups.add( new EntityCleanup( persister.getCacheAccessStrategy() ) );
|
||||
final EntityDataAccess entityDataAccess = factory.getCache()
|
||||
.getEntityRegionAccess( persister.getNavigableRole() );
|
||||
if ( entityDataAccess != null ) {
|
||||
entityCleanups.add( new EntityCleanup( entityDataAccess ) );
|
||||
} entityCleanups.add( new EntityCleanup( entityDataAccess ) );
|
||||
}
|
||||
|
||||
if ( persister.hasNaturalIdentifier() && persister.hasNaturalIdCache() ) {
|
||||
naturalIdCleanups.add( new NaturalIdCleanup( persister.getNaturalIdCacheAccessStrategy() ) );
|
||||
naturalIdCleanups.add( new NaturalIdCleanup( factory.getCache().getNaturalIdRegionAccess( persister.getNavigableRole() ) ) );
|
||||
}
|
||||
|
||||
final Set<String> roles = factory.getMetamodel().getCollectionRolesByEntityParticipant( persister.getEntityName() );
|
||||
|
@ -73,7 +78,7 @@ public class BulkOperationCleanupAction implements Executable, Serializable {
|
|||
for ( String role : roles ) {
|
||||
final CollectionPersister collectionPersister = factory.getMetamodel().collectionPersister( role );
|
||||
if ( collectionPersister.hasCache() ) {
|
||||
collectionCleanups.add( new CollectionCleanup( collectionPersister.getCacheAccessStrategy() ) );
|
||||
collectionCleanups.add( new CollectionCleanup( factory.getCache().getCollectionRegionAccess( collectionPersister.getNavigableRole() ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -200,10 +205,10 @@ public class BulkOperationCleanupAction implements Executable, Serializable {
|
|||
}
|
||||
|
||||
private static class EntityCleanup implements Serializable {
|
||||
private final EntityRegionAccessStrategy cacheAccess;
|
||||
private final EntityDataAccess cacheAccess;
|
||||
private final SoftLock cacheLock;
|
||||
|
||||
private EntityCleanup(EntityRegionAccessStrategy cacheAccess) {
|
||||
private EntityCleanup(EntityDataAccess cacheAccess) {
|
||||
this.cacheAccess = cacheAccess;
|
||||
this.cacheLock = cacheAccess.lockRegion();
|
||||
cacheAccess.removeAll();
|
||||
|
@ -215,10 +220,10 @@ public class BulkOperationCleanupAction implements Executable, Serializable {
|
|||
}
|
||||
|
||||
private static class CollectionCleanup implements Serializable {
|
||||
private final CollectionRegionAccessStrategy cacheAccess;
|
||||
private final CollectionDataAccess cacheAccess;
|
||||
private final SoftLock cacheLock;
|
||||
|
||||
private CollectionCleanup(CollectionRegionAccessStrategy cacheAccess) {
|
||||
private CollectionCleanup(CollectionDataAccess cacheAccess) {
|
||||
this.cacheAccess = cacheAccess;
|
||||
this.cacheLock = cacheAccess.lockRegion();
|
||||
cacheAccess.removeAll();
|
||||
|
@ -230,10 +235,10 @@ public class BulkOperationCleanupAction implements Executable, Serializable {
|
|||
}
|
||||
|
||||
private static class NaturalIdCleanup implements Serializable {
|
||||
private final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy;
|
||||
private final NaturalIdDataAccess naturalIdCacheAccessStrategy;
|
||||
private final SoftLock cacheLock;
|
||||
|
||||
public NaturalIdCleanup(NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy) {
|
||||
public NaturalIdCleanup(NaturalIdDataAccess naturalIdCacheAccessStrategy) {
|
||||
this.naturalIdCacheAccessStrategy = naturalIdCacheAccessStrategy;
|
||||
this.cacheLock = naturalIdCacheAccessStrategy.lockRegion();
|
||||
naturalIdCacheAccessStrategy.removeAll();
|
||||
|
|
|
@ -12,7 +12,7 @@ import org.hibernate.action.spi.AfterTransactionCompletionProcess;
|
|||
import org.hibernate.action.spi.BeforeTransactionCompletionProcess;
|
||||
import org.hibernate.action.spi.Executable;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
@ -76,7 +76,7 @@ public abstract class CollectionAction implements Executable, Serializable, Comp
|
|||
// bidirectional association and it is one of the earlier entity actions which actually updates
|
||||
// the database (this action is responsible for second-level cache invalidation only)
|
||||
if ( persister.hasCache() ) {
|
||||
final CollectionRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||
final CollectionDataAccess cache = persister.getCacheAccessStrategy();
|
||||
final Object ck = cache.generateCacheKey(
|
||||
key,
|
||||
persister,
|
||||
|
@ -129,7 +129,7 @@ public abstract class CollectionAction implements Executable, Serializable, Comp
|
|||
|
||||
protected final void evict() throws CacheException {
|
||||
if ( persister.hasCache() ) {
|
||||
final CollectionRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||
final CollectionDataAccess cache = persister.getCacheAccessStrategy();
|
||||
final Object ck = cache.generateCacheKey(
|
||||
key,
|
||||
persister,
|
||||
|
@ -173,7 +173,7 @@ public abstract class CollectionAction implements Executable, Serializable, Comp
|
|||
|
||||
@Override
|
||||
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) {
|
||||
final CollectionRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||
final CollectionDataAccess cache = persister.getCacheAccessStrategy();
|
||||
final Object ck = cache.generateCacheKey(
|
||||
key,
|
||||
persister,
|
||||
|
|
|
@ -10,7 +10,7 @@ import java.io.Serializable;
|
|||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.engine.spi.EntityEntry;
|
||||
import org.hibernate.engine.spi.PersistenceContext;
|
||||
|
@ -87,7 +87,7 @@ public class EntityDeleteAction extends EntityAction {
|
|||
|
||||
final Object ck;
|
||||
if ( persister.canWriteToCache() ) {
|
||||
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
||||
ck = cache.generateCacheKey( id, persister, session.getFactory(), session.getTenantIdentifier() );
|
||||
lock = cache.lockItem( session, ck, version );
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ public class EntityDeleteAction extends EntityAction {
|
|||
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) throws HibernateException {
|
||||
EntityPersister entityPersister = getPersister();
|
||||
if ( entityPersister.canWriteToCache() ) {
|
||||
EntityRegionAccessStrategy cache = entityPersister.getCacheAccessStrategy();
|
||||
EntityDataAccess cache = entityPersister.getCacheAccessStrategy();
|
||||
final Object ck = cache.generateCacheKey(
|
||||
getId(),
|
||||
entityPersister,
|
||||
|
|
|
@ -102,7 +102,7 @@ public final class EntityIdentityInsertAction extends AbstractEntityInsertAction
|
|||
postInsert();
|
||||
|
||||
if ( session.getFactory().getStatistics().isStatisticsEnabled() && !isVeto() ) {
|
||||
session.getFactory().getStatisticsImplementor().insertEntity( getPersister().getEntityName() );
|
||||
session.getFactory().getStatistics().insertEntity( getPersister().getEntityName() );
|
||||
}
|
||||
|
||||
markExecuted();
|
||||
|
|
|
@ -10,7 +10,7 @@ import java.io.Serializable;
|
|||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.cache.spi.entry.CacheEntry;
|
||||
import org.hibernate.engine.internal.Versioning;
|
||||
import org.hibernate.engine.spi.EntityEntry;
|
||||
|
@ -116,7 +116,7 @@ public final class EntityInsertAction extends AbstractEntityInsertAction {
|
|||
session
|
||||
);
|
||||
cacheEntry = persister.getCacheEntryStructure().structure( ce );
|
||||
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
||||
final Object ck = cache.generateCacheKey( id, persister, factory, session.getTenantIdentifier() );
|
||||
|
||||
final boolean put = cacheInsert( persister, ck );
|
||||
|
@ -211,20 +211,20 @@ public final class EntityInsertAction extends AbstractEntityInsertAction {
|
|||
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) throws HibernateException {
|
||||
final EntityPersister persister = getPersister();
|
||||
if ( success && isCachePutEnabled( persister, getSession() ) ) {
|
||||
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
||||
SessionFactoryImplementor sessionFactoryImplementor = session.getFactory();
|
||||
final Object ck = cache.generateCacheKey( getId(), persister, sessionFactoryImplementor, session.getTenantIdentifier() );
|
||||
final boolean put = cacheAfterInsert( cache, ck );
|
||||
|
||||
if ( put && sessionFactoryImplementor.getStatistics().isStatisticsEnabled() ) {
|
||||
sessionFactoryImplementor.getStatisticsImplementor()
|
||||
sessionFactoryImplementor.getStatistics()
|
||||
.secondLevelCachePut( cache.getRegion().getName() );
|
||||
}
|
||||
}
|
||||
postCommitInsert( success );
|
||||
}
|
||||
|
||||
private boolean cacheAfterInsert(EntityRegionAccessStrategy cache, Object ck) {
|
||||
private boolean cacheAfterInsert(EntityDataAccess cache, Object ck) {
|
||||
SharedSessionContractImplementor session = getSession();
|
||||
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
|
||||
try {
|
||||
|
|
|
@ -11,7 +11,7 @@ import java.io.Serializable;
|
|||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.cache.spi.entry.CacheEntry;
|
||||
import org.hibernate.engine.internal.Versioning;
|
||||
|
@ -128,7 +128,7 @@ public final class EntityUpdateAction extends EntityAction {
|
|||
|
||||
final Object ck;
|
||||
if ( persister.canWriteToCache() ) {
|
||||
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
||||
ck = cache.generateCacheKey(
|
||||
id,
|
||||
persister,
|
||||
|
@ -311,7 +311,7 @@ public final class EntityUpdateAction extends EntityAction {
|
|||
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) throws CacheException {
|
||||
final EntityPersister persister = getPersister();
|
||||
if ( persister.canWriteToCache() ) {
|
||||
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
||||
final Object ck = cache.generateCacheKey(
|
||||
getId(),
|
||||
persister,
|
||||
|
@ -337,7 +337,7 @@ public final class EntityUpdateAction extends EntityAction {
|
|||
postCommitUpdate( success );
|
||||
}
|
||||
|
||||
private boolean cacheAfterUpdate(EntityRegionAccessStrategy cache, Object ck) {
|
||||
private boolean cacheAfterUpdate(EntityDataAccess cache, Object ck) {
|
||||
final SharedSessionContractImplementor session = getSession();
|
||||
SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
|
||||
try {
|
||||
|
|
|
@ -15,7 +15,7 @@ import org.hibernate.MultiTenancyStrategy;
|
|||
import org.hibernate.NullPrecedence;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.SessionFactoryObserver;
|
||||
import org.hibernate.cache.spi.QueryCacheFactory;
|
||||
import org.hibernate.cache.spi.TimestampsRegionAccessFactory;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
|
@ -491,7 +491,7 @@ public interface SessionFactoryBuilder {
|
|||
*
|
||||
* @see org.hibernate.cfg.AvailableSettings#QUERY_CACHE_FACTORY
|
||||
*/
|
||||
SessionFactoryBuilder applyQueryCacheFactory(QueryCacheFactory factory);
|
||||
SessionFactoryBuilder applyTimestampsRegionAccessFactory(TimestampsRegionAccessFactory factory);
|
||||
|
||||
/**
|
||||
* Apply a prefix to prepended to all cache region names for this SessionFactory.
|
||||
|
|
|
@ -38,7 +38,7 @@ import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
|||
import org.hibernate.boot.model.TypeDefinition;
|
||||
import org.hibernate.boot.model.convert.internal.AttributeConverterManager;
|
||||
import org.hibernate.boot.model.convert.internal.ClassBasedConverterDescriptor;
|
||||
import org.hibernate.boot.model.convert.internal.InstanceBasedConverterDescriptor;
|
||||
import org.hibernate.boot.model.convert.spi.ConverterAutoApplyHandler;
|
||||
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.model.naming.ImplicitForeignKeyNameSource;
|
||||
|
@ -50,13 +50,13 @@ import org.hibernate.boot.model.relational.ExportableProducer;
|
|||
import org.hibernate.boot.model.relational.Namespace;
|
||||
import org.hibernate.boot.model.source.internal.ImplicitColumnNamingSecondPass;
|
||||
import org.hibernate.boot.model.source.spi.LocalMetadataBuildingContext;
|
||||
import org.hibernate.boot.model.convert.spi.ConverterAutoApplyHandler;
|
||||
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.boot.spi.MetadataBuildingOptions;
|
||||
import org.hibernate.boot.spi.NaturalIdUniqueKeyBinder;
|
||||
import org.hibernate.cache.cfg.internal.DomainDataRegionConfigImpl.Builder;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cfg.AnnotatedClassType;
|
||||
import org.hibernate.cfg.AttributeConverterDefinition;
|
||||
import org.hibernate.cfg.CopyIdentifierComponentSecondPass;
|
||||
import org.hibernate.cfg.CreateKeySecondPass;
|
||||
import org.hibernate.cfg.FkSecondPass;
|
||||
|
@ -143,6 +143,8 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
|
|||
private final Map<String, FetchProfile> fetchProfileMap = new HashMap<String, FetchProfile>();
|
||||
private final Map<String, IdentifierGeneratorDefinition> idGeneratorDefinitionMap = new HashMap<String, IdentifierGeneratorDefinition>();
|
||||
|
||||
private final Map<String, Builder> regionConfigBuilders = new ConcurrentHashMap<>();
|
||||
|
||||
private Map<String, SQLFunction> sqlFunctionMap;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -276,8 +278,28 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
|
|||
throw new DuplicateMappingException( DuplicateMappingException.Type.ENTITY, entityName );
|
||||
}
|
||||
entityBindingMap.put( entityName, persistentClass );
|
||||
|
||||
final AccessType accessType = AccessType.fromExternalName( persistentClass.getCacheConcurrencyStrategy() );
|
||||
if ( accessType != null ) {
|
||||
if ( persistentClass.isCached() ) {
|
||||
locateCacheRegionConfigBuilder( persistentClass.getRootClass().getCacheRegionName() ).addEntityConfig(
|
||||
persistentClass,
|
||||
accessType
|
||||
);
|
||||
}
|
||||
|
||||
if ( persistentClass.hasNaturalId() && persistentClass.getNaturalIdCacheRegionName() != null ) {
|
||||
locateCacheRegionConfigBuilder( persistentClass.getNaturalIdCacheRegionName() ).addNaturalIdConfig(
|
||||
(RootClass) persistentClass,
|
||||
accessType
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Builder locateCacheRegionConfigBuilder(String regionName) {
|
||||
return regionConfigBuilders.computeIfAbsent( regionName, Builder::new );
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Collection handling
|
||||
|
@ -299,6 +321,14 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
|
|||
throw new DuplicateMappingException( DuplicateMappingException.Type.COLLECTION, collectionRole );
|
||||
}
|
||||
collectionBindingMap.put( collectionRole, collection );
|
||||
|
||||
final AccessType accessType = AccessType.fromExternalName( collection.getCacheConcurrencyStrategy() );
|
||||
if ( accessType != null ) {
|
||||
locateCacheRegionConfigBuilder( collection.getCacheConcurrencyStrategy() ).addCollectionConfig(
|
||||
collection,
|
||||
accessType
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -2213,6 +2243,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
|
|||
sqlResultSetMappingMap,
|
||||
namedEntityGraphMap,
|
||||
sqlFunctionMap,
|
||||
regionConfigBuilders.values(),
|
||||
getDatabase()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
|||
import org.hibernate.boot.spi.MetadataBuildingOptions;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.boot.spi.SessionFactoryBuilderFactory;
|
||||
import org.hibernate.cache.cfg.internal.DomainDataRegionConfigImpl;
|
||||
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
||||
import org.hibernate.cfg.annotations.NamedProcedureCallDefinition;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
|
@ -77,6 +78,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
|||
private final Map<String, ResultSetMappingDefinition> sqlResultSetMappingMap;
|
||||
private final Map<String, NamedEntityGraphDefinition> namedEntityGraphMap;
|
||||
private final Map<String, SQLFunction> sqlFunctionMap;
|
||||
private final java.util.Collection<DomainDataRegionConfigImpl.Builder> cacheRegionConfigBuilders;
|
||||
private final Database database;
|
||||
|
||||
public MetadataImpl(
|
||||
|
@ -98,6 +100,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
|||
Map<String, ResultSetMappingDefinition> sqlResultSetMappingMap,
|
||||
Map<String, NamedEntityGraphDefinition> namedEntityGraphMap,
|
||||
Map<String, SQLFunction> sqlFunctionMap,
|
||||
java.util.Collection<DomainDataRegionConfigImpl.Builder> cacheRegionConfigBuilders,
|
||||
Database database) {
|
||||
this.uuid = uuid;
|
||||
this.metadataBuildingOptions = metadataBuildingOptions;
|
||||
|
@ -117,6 +120,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
|||
this.sqlResultSetMappingMap = sqlResultSetMappingMap;
|
||||
this.namedEntityGraphMap = namedEntityGraphMap;
|
||||
this.sqlFunctionMap = sqlFunctionMap;
|
||||
this.cacheRegionConfigBuilders = cacheRegionConfigBuilders;
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.hibernate.boot.TempTableDdlTransactionHandling;
|
|||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.boot.spi.SessionFactoryBuilderImplementor;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.cache.spi.QueryCacheFactory;
|
||||
import org.hibernate.cache.spi.TimestampsRegionAccessFactory;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
|
@ -283,8 +283,8 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
|||
}
|
||||
|
||||
@Override
|
||||
public SessionFactoryBuilder applyQueryCacheFactory(QueryCacheFactory factory) {
|
||||
this.optionsBuilder.applyQueryCacheFactory( factory );
|
||||
public SessionFactoryBuilder applyTimestampsRegionAccessFactory(TimestampsRegionAccessFactory factory) {
|
||||
this.optionsBuilder.applyTimestampsRegionAccessFactory( factory );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,9 +32,9 @@ import org.hibernate.boot.TempTableDdlTransactionHandling;
|
|||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.selector.spi.StrategySelector;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.cache.internal.StandardQueryCacheFactory;
|
||||
import org.hibernate.cache.spi.QueryCacheFactory;
|
||||
import org.hibernate.cache.internal.StandardTimestampsRegionAccessFactory;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cache.spi.TimestampsRegionAccessFactory;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.BaselineSessionEventsListenerBuilder;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
|
@ -197,7 +197,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
|||
// Caching
|
||||
private boolean secondLevelCacheEnabled;
|
||||
private boolean queryCacheEnabled;
|
||||
private QueryCacheFactory queryCacheFactory;
|
||||
private TimestampsRegionAccessFactory timestampsCacheFactory;
|
||||
private String cacheRegionPrefix;
|
||||
private boolean minimalPutsEnabled;
|
||||
private boolean structuredCacheEntriesEnabled;
|
||||
|
@ -331,10 +331,10 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
|||
|
||||
this.secondLevelCacheEnabled = cfgService.getSetting( USE_SECOND_LEVEL_CACHE, BOOLEAN, true );
|
||||
this.queryCacheEnabled = cfgService.getSetting( USE_QUERY_CACHE, BOOLEAN, false );
|
||||
this.queryCacheFactory = strategySelector.resolveDefaultableStrategy(
|
||||
QueryCacheFactory.class,
|
||||
this.timestampsCacheFactory = strategySelector.resolveDefaultableStrategy(
|
||||
TimestampsRegionAccessFactory.class,
|
||||
configurationSettings.get( QUERY_CACHE_FACTORY ),
|
||||
StandardQueryCacheFactory.INSTANCE
|
||||
StandardTimestampsRegionAccessFactory.INSTANCE
|
||||
);
|
||||
this.cacheRegionPrefix = ConfigurationHelper.extractPropertyValue(
|
||||
CACHE_REGION_PREFIX,
|
||||
|
@ -804,8 +804,8 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
|||
}
|
||||
|
||||
@Override
|
||||
public QueryCacheFactory getQueryCacheFactory() {
|
||||
return queryCacheFactory;
|
||||
public TimestampsRegionAccessFactory getTimestampsRegionAccessFactory() {
|
||||
return timestampsCacheFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1102,8 +1102,8 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
|||
this.queryCacheEnabled = enabled;
|
||||
}
|
||||
|
||||
public void applyQueryCacheFactory(QueryCacheFactory factory) {
|
||||
this.queryCacheFactory = factory;
|
||||
public void applyTimestampsRegionAccessFactory(TimestampsRegionAccessFactory factory) {
|
||||
this.timestampsCacheFactory = factory;
|
||||
}
|
||||
|
||||
public void applyCacheRegionPrefix(String prefix) {
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.boot.SessionFactoryBuilder;
|
|||
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
||||
import org.hibernate.boot.model.TypeDefinition;
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.cache.cfg.internal.DomainDataRegionConfigImpl;
|
||||
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
||||
import org.hibernate.cfg.annotations.NamedProcedureCallDefinition;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
|
|
|
@ -17,7 +17,7 @@ import org.hibernate.SessionFactory;
|
|||
import org.hibernate.SessionFactoryObserver;
|
||||
import org.hibernate.boot.SessionFactoryBuilder;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.cache.spi.QueryCacheFactory;
|
||||
import org.hibernate.cache.spi.TimestampsRegionAccessFactory;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
|
@ -279,8 +279,8 @@ public abstract class AbstractDelegatingSessionFactoryBuilder<T extends SessionF
|
|||
}
|
||||
|
||||
@Override
|
||||
public T applyQueryCacheFactory(QueryCacheFactory factory) {
|
||||
delegate.applyQueryCacheFactory( factory );
|
||||
public SessionFactoryBuilder applyTimestampsRegionAccessFactory(TimestampsRegionAccessFactory factory) {
|
||||
delegate.applyTimestampsRegionAccessFactory( factory );
|
||||
return getThis();
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import org.hibernate.SessionFactoryObserver;
|
|||
import org.hibernate.boot.SchemaAutoTooling;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.cache.spi.QueryCacheFactory;
|
||||
import org.hibernate.cache.spi.TimestampsRegionAccessFactory;
|
||||
import org.hibernate.cfg.BaselineSessionEventsListenerBuilder;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
|
@ -252,8 +252,8 @@ public class AbstractDelegatingSessionFactoryOptions implements SessionFactoryOp
|
|||
}
|
||||
|
||||
@Override
|
||||
public QueryCacheFactory getQueryCacheFactory() {
|
||||
return delegate.getQueryCacheFactory();
|
||||
public TimestampsRegionAccessFactory getTimestampsRegionAccessFactory() {
|
||||
return delegate.getTimestampsRegionAccessFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,10 +6,12 @@
|
|||
*/
|
||||
package org.hibernate.boot.spi;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.cache.cfg.internal.DomainDataRegionConfigImpl;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.internal.SessionFactoryImpl;
|
||||
import org.hibernate.mapping.MappedSuperclass;
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
*/
|
||||
package org.hibernate.boot.spi;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.ConnectionReleaseMode;
|
||||
import org.hibernate.CustomEntityDirtinessStrategy;
|
||||
import org.hibernate.EntityMode;
|
||||
|
@ -18,7 +22,7 @@ import org.hibernate.SessionFactoryObserver;
|
|||
import org.hibernate.boot.SchemaAutoTooling;
|
||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.cache.spi.QueryCacheFactory;
|
||||
import org.hibernate.cache.spi.TimestampsRegionAccessFactory;
|
||||
import org.hibernate.cfg.BaselineSessionEventsListenerBuilder;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
|
@ -31,10 +35,6 @@ import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
|
|||
import org.hibernate.resource.jdbc.spi.StatementInspector;
|
||||
import org.hibernate.tuple.entity.EntityTuplizerFactory;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Aggregator of special options used to build the SessionFactory.
|
||||
*
|
||||
|
@ -182,7 +182,7 @@ public interface SessionFactoryOptions {
|
|||
|
||||
boolean isQueryCacheEnabled();
|
||||
|
||||
QueryCacheFactory getQueryCacheFactory();
|
||||
TimestampsRegionAccessFactory getTimestampsRegionAccessFactory();
|
||||
|
||||
String getCacheRegionPrefix();
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.cfg.internal;
|
||||
|
||||
import org.hibernate.cache.cfg.spi.DomainDataCachingConfig;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractDomainDataCachingConfig implements DomainDataCachingConfig {
|
||||
private final AccessType accessType;
|
||||
|
||||
public AbstractDomainDataCachingConfig(AccessType accessType) {
|
||||
this.accessType = accessType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessType getAccessType() {
|
||||
return accessType;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.cfg.internal;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.hibernate.cache.cfg.spi.CollectionDataCachingConfig;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.type.VersionType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CollectionDataCachingConfigImpl
|
||||
extends AbstractDomainDataCachingConfig
|
||||
implements CollectionDataCachingConfig {
|
||||
private final Collection collectionDescriptor;
|
||||
private final NavigableRole navigableRole;
|
||||
|
||||
public CollectionDataCachingConfigImpl(
|
||||
Collection collectionDescriptor,
|
||||
AccessType accessType) {
|
||||
super( accessType );
|
||||
this.collectionDescriptor = collectionDescriptor;
|
||||
this.navigableRole = new NavigableRole( collectionDescriptor.getRole() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return collectionDescriptor.isMutable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersioned() {
|
||||
return collectionDescriptor.getOwner().isVersioned();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comparator getOwnerVersionComparator() {
|
||||
if ( !isVersioned() ) {
|
||||
return null;
|
||||
}
|
||||
return ( (VersionType) collectionDescriptor.getOwner().getVersion().getType() ).getComparator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return navigableRole;
|
||||
}
|
||||
}
|
163
hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/DomainDataRegionConfigImpl.java
vendored
Normal file
163
hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/DomainDataRegionConfigImpl.java
vendored
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.cfg.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.cache.cfg.spi.CollectionDataCachingConfig;
|
||||
import org.hibernate.cache.cfg.spi.DomainDataCachingConfig;
|
||||
import org.hibernate.cache.cfg.spi.DomainDataRegionConfig;
|
||||
import org.hibernate.cache.cfg.spi.EntityDataCachingConfig;
|
||||
import org.hibernate.cache.cfg.spi.NaturalIdDataCachingConfig;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.RootClass;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.type.VersionType;
|
||||
|
||||
/**
|
||||
* DomainDataRegionConfig implementation
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DomainDataRegionConfigImpl implements DomainDataRegionConfig {
|
||||
private final String regionName;
|
||||
|
||||
private final List<EntityDataCachingConfig> entityConfigs;
|
||||
private final List<NaturalIdDataCachingConfig> naturalIdConfigs;
|
||||
private final List<CollectionDataCachingConfig> collectionConfigs;
|
||||
|
||||
private DomainDataRegionConfigImpl(
|
||||
String regionName,
|
||||
List<EntityDataCachingConfig> entityConfigs,
|
||||
List<NaturalIdDataCachingConfig> naturalIdConfigs,
|
||||
List<CollectionDataCachingConfig> collectionConfigs) {
|
||||
this.regionName = regionName;
|
||||
this.entityConfigs = entityConfigs;
|
||||
this.naturalIdConfigs = naturalIdConfigs;
|
||||
this.collectionConfigs = collectionConfigs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRegionName() {
|
||||
return regionName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EntityDataCachingConfig> getEntityCaching() {
|
||||
return entityConfigs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NaturalIdDataCachingConfig> getNaturalIdCaching() {
|
||||
return naturalIdConfigs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CollectionDataCachingConfig> getCollectionCaching() {
|
||||
return collectionConfigs;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final String regionName;
|
||||
|
||||
private Map<NavigableRole,EntityDataCachingConfigImpl> entityConfigsByRootName;
|
||||
private List<NaturalIdDataCachingConfig> naturalIdConfigs;
|
||||
private List<CollectionDataCachingConfig> collectionConfigs;
|
||||
|
||||
public Builder(String regionName) {
|
||||
this.regionName = regionName;
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedReturnValue")
|
||||
public Builder addEntityConfig(PersistentClass bootEntityDescriptor, AccessType accessType) {
|
||||
if ( entityConfigsByRootName == null ) {
|
||||
entityConfigsByRootName = new HashMap<>();
|
||||
}
|
||||
|
||||
// todo (5.3) : this is another place where having `BootstrapContext` / `TypeConfiguration` helps
|
||||
// would allow us to delay the attempt to resolve the comparator (usual timing issues wrt Type resolution)
|
||||
final NavigableRole rootEntityName = new NavigableRole( bootEntityDescriptor.getRootClass().getEntityName() );
|
||||
final EntityDataCachingConfigImpl entityDataCachingConfig = entityConfigsByRootName.computeIfAbsent(
|
||||
rootEntityName,
|
||||
x -> new EntityDataCachingConfigImpl(
|
||||
rootEntityName,
|
||||
bootEntityDescriptor.isVersioned()
|
||||
? (Supplier<Comparator>) () -> ( (VersionType) bootEntityDescriptor.getVersion().getType() ).getComparator()
|
||||
: null,
|
||||
bootEntityDescriptor.isMutable(),
|
||||
accessType
|
||||
)
|
||||
);
|
||||
|
||||
if ( bootEntityDescriptor == bootEntityDescriptor.getRootClass() ) {
|
||||
entityDataCachingConfig.addCachedType( rootEntityName );
|
||||
}
|
||||
else {
|
||||
entityDataCachingConfig.addCachedType( new NavigableRole( bootEntityDescriptor.getEntityName() ) );
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// todo (6.0) : `EntityPersister` and `CollectionPersister` references here should be replaces with `EntityHierarchy` and `PersistentCollectionDescriptor`
|
||||
//
|
||||
// todo : although ^^, couldn't this just be the boot-time model? Is there a specific need for it to be the run-time model?
|
||||
// that would alleviate the difference between 5.3 and 6.0 from the SPI POV
|
||||
|
||||
@SuppressWarnings("UnusedReturnValue")
|
||||
public Builder addNaturalIdConfig(RootClass rootEntityDescriptor, AccessType accessType) {
|
||||
if ( naturalIdConfigs == null ) {
|
||||
naturalIdConfigs = new ArrayList<>();
|
||||
}
|
||||
|
||||
naturalIdConfigs.add( new NaturalIdDataCachingConfigImpl( rootEntityDescriptor, accessType ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedReturnValue")
|
||||
public Builder addCollectionConfig(Collection collectionDescriptor, AccessType accessType) {
|
||||
if ( collectionConfigs == null ) {
|
||||
collectionConfigs = new ArrayList<>();
|
||||
}
|
||||
|
||||
collectionConfigs.add( new CollectionDataCachingConfigImpl( collectionDescriptor, accessType ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
public DomainDataRegionConfigImpl build() {
|
||||
return new DomainDataRegionConfigImpl(
|
||||
regionName,
|
||||
finalize( entityConfigsByRootName ),
|
||||
finalize( naturalIdConfigs ),
|
||||
finalize( collectionConfigs )
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends DomainDataCachingConfig> List<T> finalize(Map configs) {
|
||||
return configs == null
|
||||
? Collections.emptyList()
|
||||
: Collections.unmodifiableList( new ArrayList( configs.values() ) );
|
||||
}
|
||||
|
||||
private <T extends DomainDataCachingConfig> List<T> finalize(List<T> configs) {
|
||||
return configs == null
|
||||
? Collections.emptyList()
|
||||
: Collections.unmodifiableList( configs );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
71
hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/EntityDataCachingConfigImpl.java
vendored
Normal file
71
hibernate-core/src/main/java/org/hibernate/cache/cfg/internal/EntityDataCachingConfigImpl.java
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.cfg.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.cache.cfg.spi.EntityDataCachingConfig;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityDataCachingConfigImpl
|
||||
extends AbstractDomainDataCachingConfig
|
||||
implements EntityDataCachingConfig {
|
||||
private final NavigableRole navigableRole;
|
||||
private final Supplier<Comparator> versionComparatorAccess;
|
||||
private final boolean isEntityMutable;
|
||||
|
||||
private final Set<NavigableRole> cachedTypes = new HashSet<>();
|
||||
|
||||
public EntityDataCachingConfigImpl(
|
||||
NavigableRole rootEntityName,
|
||||
Supplier<Comparator> versionComparatorAccess,
|
||||
boolean isEntityMutable,
|
||||
AccessType accessType) {
|
||||
super( accessType );
|
||||
this.navigableRole = rootEntityName;
|
||||
this.versionComparatorAccess = versionComparatorAccess;
|
||||
this.isEntityMutable = isEntityMutable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Supplier<Comparator> getVersionComparatorAccess() {
|
||||
return versionComparatorAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return isEntityMutable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersioned() {
|
||||
return getVersionComparatorAccess() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return navigableRole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<NavigableRole> getCachedTypes() {
|
||||
return cachedTypes;
|
||||
}
|
||||
|
||||
public void addCachedType(NavigableRole typeRole) {
|
||||
cachedTypes.add( typeRole );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.cfg.internal;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.hibernate.cache.cfg.spi.NaturalIdDataCachingConfig;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.RootClass;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NaturalIdDataCachingConfigImpl
|
||||
extends AbstractDomainDataCachingConfig
|
||||
implements NaturalIdDataCachingConfig {
|
||||
private final RootClass rootEntityDescriptor;
|
||||
private final NavigableRole navigableRole;
|
||||
private final boolean mutable;
|
||||
|
||||
public NaturalIdDataCachingConfigImpl(
|
||||
RootClass rootEntityDescriptor,
|
||||
AccessType accessType) {
|
||||
super( accessType );
|
||||
this.rootEntityDescriptor = rootEntityDescriptor;
|
||||
this.navigableRole = new NavigableRole( rootEntityDescriptor.getEntityName() );
|
||||
|
||||
// sucks that we need to do this here. persister does the same "calculation"
|
||||
this.mutable = hasAnyMutableNaturalIdProps();
|
||||
}
|
||||
|
||||
private boolean hasAnyMutableNaturalIdProps() {
|
||||
final Iterator itr = rootEntityDescriptor.getDeclaredPropertyIterator();
|
||||
while ( itr.hasNext() ) {
|
||||
final Property prop = (Property) itr.next();
|
||||
if ( prop.isNaturalIdentifier() && prop.isUpdateable() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableRole getNavigableRole() {
|
||||
return navigableRole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return mutable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersioned() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* Package used to model various aspects of caching configuration
|
||||
*/
|
||||
package org.hibernate.cache.cfg;
|
22
hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/CollectionDataCachingConfig.java
vendored
Normal file
22
hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/CollectionDataCachingConfig.java
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.cfg.spi;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Specialized DomainDataCachingConfig describing the requested
|
||||
* caching config for a particular persistent collection's data
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface CollectionDataCachingConfig extends DomainDataCachingConfig {
|
||||
/**
|
||||
* The comparator to be used with the owning entity's version (if it has one).
|
||||
*/
|
||||
Comparator getOwnerVersionComparator();
|
||||
}
|
38
hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/DomainDataCachingConfig.java
vendored
Normal file
38
hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/DomainDataCachingConfig.java
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.cfg.spi;
|
||||
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
|
||||
/**
|
||||
* Configuration for a specific type of data to be stored in the
|
||||
* region
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DomainDataCachingConfig {
|
||||
/**
|
||||
* The requested AccessType
|
||||
*/
|
||||
AccessType getAccessType();
|
||||
|
||||
/**
|
||||
* Is the data marked as being mutable?
|
||||
*/
|
||||
boolean isMutable();
|
||||
|
||||
/**
|
||||
* Is the data to be cached considered versioned?
|
||||
*/
|
||||
boolean isVersioned();
|
||||
|
||||
/**
|
||||
* The {@link NavigableRole} of the thing to be cached
|
||||
*/
|
||||
NavigableRole getNavigableRole();
|
||||
}
|
35
hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/DomainDataRegionBuildingContext.java
vendored
Normal file
35
hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/DomainDataRegionBuildingContext.java
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.cfg.spi;
|
||||
|
||||
import org.hibernate.cache.spi.CacheKeysFactory;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
||||
/**
|
||||
* A "parameter object" for {@link RegionFactory#buildDomainDataRegion}
|
||||
* calls, giving it access to information it needs.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DomainDataRegionBuildingContext {
|
||||
/**
|
||||
* The CacheKeyFactory explicitly specified as part of the
|
||||
* bootstrap by the user, by some "container", etc.
|
||||
*
|
||||
* If this method returns a non-null value, it is expected
|
||||
* that RegionFactory implementors will use to be its
|
||||
* CacheKeyFactory and return it when asked later.
|
||||
*/
|
||||
CacheKeysFactory getEnforcedCacheKeysFactory();
|
||||
|
||||
/**
|
||||
* Access to the SessionFactory for which a Region is
|
||||
* being built.
|
||||
*/
|
||||
SessionFactoryImplementor getSessionFactory();
|
||||
}
|
33
hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/DomainDataRegionConfig.java
vendored
Normal file
33
hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/DomainDataRegionConfig.java
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.cfg.spi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Configuration for a named region for caching domain data
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DomainDataRegionConfig {
|
||||
String getRegionName();
|
||||
|
||||
/**
|
||||
* Retrieve the list of all entity to be stored in this region
|
||||
*/
|
||||
List<EntityDataCachingConfig> getEntityCaching();
|
||||
|
||||
/**
|
||||
* Retrieve the list of all natural-id data to be stored in this region
|
||||
*/
|
||||
List<NaturalIdDataCachingConfig> getNaturalIdCaching();
|
||||
|
||||
/**
|
||||
* Retrieve the list of all collection data to be stored in this region
|
||||
*/
|
||||
List<CollectionDataCachingConfig> getCollectionCaching();
|
||||
}
|
47
hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/EntityDataCachingConfig.java
vendored
Normal file
47
hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/EntityDataCachingConfig.java
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.cfg.spi;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
|
||||
/**
|
||||
* Specialized DomainDataCachingConfig describing the requested
|
||||
* caching config for a particular entity hierarchy's state data
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface EntityDataCachingConfig extends DomainDataCachingConfig {
|
||||
/**
|
||||
* Mainly here to allow optimization of not having to know the
|
||||
* actual comparator instance to use here yet. If this method
|
||||
* returns {@code true}, then users can safely assume that
|
||||
* accessing {@link #getVersionComparatorAccess()} will
|
||||
* not produce a null Comparator later
|
||||
*
|
||||
*/
|
||||
boolean isVersioned();
|
||||
|
||||
/**
|
||||
* Access to the comparator to be used with the entity's
|
||||
* version. If the entity is not versioned, then this method
|
||||
* returns {@code null}.
|
||||
*/
|
||||
Supplier<Comparator> getVersionComparatorAccess();
|
||||
|
||||
/**
|
||||
* The list of specific subclasses of the root that are actually
|
||||
* written to cache.
|
||||
*/
|
||||
Set<NavigableRole> getCachedTypes();
|
||||
|
||||
// todo (5.3) : what else is needed here?
|
||||
}
|
16
hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/NaturalIdDataCachingConfig.java
vendored
Normal file
16
hibernate-core/src/main/java/org/hibernate/cache/cfg/spi/NaturalIdDataCachingConfig.java
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.cfg.spi;
|
||||
|
||||
/**
|
||||
* Specialized DomainDataCachingConfig describing the requested
|
||||
* caching config for the natural-id data of a particular entity (hierarchy)
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface NaturalIdDataCachingConfig extends DomainDataCachingConfig {
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.cache.internal;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.VersionType;
|
||||
import org.hibernate.type.descriptor.java.IncomparableComparator;
|
||||
|
||||
/**
|
||||
* Standard CacheDataDescription implementation.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CacheDataDescriptionImpl implements CacheDataDescription {
|
||||
private final boolean mutable;
|
||||
private final boolean versioned;
|
||||
private final Comparator versionComparator;
|
||||
private final Type keyType;
|
||||
|
||||
/**
|
||||
* Constructs a CacheDataDescriptionImpl instance. Generally speaking, code should use one of the
|
||||
* overloaded {@link #decode} methods rather than direct instantiation.
|
||||
* @param mutable Is the described data mutable?
|
||||
* @param versioned Is the described data versioned?
|
||||
* @param versionComparator The described data's version value comparator (if versioned).
|
||||
* @param keyType
|
||||
*/
|
||||
public CacheDataDescriptionImpl(boolean mutable, boolean versioned, Comparator versionComparator, Type keyType) {
|
||||
this.mutable = mutable;
|
||||
this.versioned = versioned;
|
||||
this.versionComparator = versionComparator;
|
||||
if ( versioned &&
|
||||
( versionComparator == null || IncomparableComparator.class.isInstance( versionComparator ) ) ) {
|
||||
throw new IllegalArgumentException(
|
||||
"versionComparator must not be null or an instance of " + IncomparableComparator.class.getName()
|
||||
);
|
||||
}
|
||||
this.keyType = keyType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return mutable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersioned() {
|
||||
return versioned;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comparator getVersionComparator() {
|
||||
return versionComparator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getKeyType() {
|
||||
return keyType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a CacheDataDescriptionImpl from the mapping model of an entity class.
|
||||
*
|
||||
* @param model The mapping model.
|
||||
*
|
||||
* @return The constructed CacheDataDescriptionImpl
|
||||
*/
|
||||
public static CacheDataDescriptionImpl decode(PersistentClass model) {
|
||||
return new CacheDataDescriptionImpl(
|
||||
model.isMutable(),
|
||||
model.isVersioned(),
|
||||
model.isVersioned()
|
||||
? ( (VersionType) model.getVersion().getType() ).getComparator()
|
||||
: null,
|
||||
model.getIdentifier().getType()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a CacheDataDescriptionImpl from the mapping model of a collection
|
||||
*
|
||||
* @param model The mapping model.
|
||||
*
|
||||
* @return The constructed CacheDataDescriptionImpl
|
||||
*/
|
||||
public static CacheDataDescriptionImpl decode(Collection model) {
|
||||
return new CacheDataDescriptionImpl(
|
||||
model.isMutable(),
|
||||
model.getOwner().isVersioned(),
|
||||
model.getOwner().isVersioned()
|
||||
? ( (VersionType) model.getOwner().getVersion().getType() ).getComparator()
|
||||
: null,
|
||||
model.getKey().getType()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -194,5 +194,7 @@ public class CollectionCacheInvalidator
|
|||
beforeExecutions();
|
||||
return getAfterTransactionCompletionProcess();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
230
hibernate-core/src/main/java/org/hibernate/cache/internal/DisabledCaching.java
vendored
Normal file
230
hibernate-core/src/main/java/org/hibernate/cache/internal/DisabledCaching.java
vendored
Normal file
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.cache.cfg.spi.DomainDataRegionConfig;
|
||||
import org.hibernate.cache.spi.CacheImplementor;
|
||||
import org.hibernate.cache.spi.QueryResultRegionAccess;
|
||||
import org.hibernate.cache.spi.Region;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cache.spi.TimestampsRegionAccess;
|
||||
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
|
||||
/**
|
||||
* CacheImplementor implementation for disabled caching
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DisabledCaching implements CacheImplementor {
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
private final RegionFactory regionFactory;
|
||||
|
||||
public DisabledCaching(SessionFactoryImplementor sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
this.regionFactory = sessionFactory.getServiceRegistry().getService( RegionFactory.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionFactoryImplementor getSessionFactory() {
|
||||
return sessionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionFactory getRegionFactory() {
|
||||
return regionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prime(Set<DomainDataRegionConfig> cacheRegionConfigs) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsEntity(Class entityClass, Serializable identifier) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsEntity(String entityName, Serializable identifier) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictEntityData(Class entityClass, Serializable identifier) {
|
||||
// nothing to do
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictEntityData(String entityName, Serializable identifier) {
|
||||
// nothing to do
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictEntityData(Class entityClass) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictEntityData(String entityName) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictEntityData() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictNaturalIdData(Class entityClass) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictNaturalIdData(String entityName) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictNaturalIdData() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsCollection(String role, Serializable ownerIdentifier) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictCollectionData(String role, Serializable ownerIdentifier) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictCollectionData(String role) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictCollectionData() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsQuery(String regionName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictDefaultQueryRegion() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictQueryRegion(String regionName) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictQueryRegions() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictRegion(String regionName) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region getRegion(String fullRegionName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimestampsRegionAccess getTimestampsRegionAccess() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResultRegionAccess getDefaultQueryResultsRegionAccess() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResultRegionAccess getQueryResultsRegionAccess(String regionName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResultRegionAccess getQueryResultsRegionAccessStrictly(String regionName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSecondLevelCacheRegionNames() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getCacheRegionNames() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityDataAccess getEntityRegionAccess(NavigableRole rootEntityName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NaturalIdDataAccess getNaturalIdRegionAccess(NavigableRole rootEntityName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionDataAccess getCollectionRegionAccess(NavigableRole collectionRole) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Class cls, Object primaryKey) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evict(Class cls, Object primaryKey) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evict(Class cls) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T unwrap(Class<T> cls) {
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<NaturalIdDataAccess> getNaturalIdAccessesInRegion(String regionName) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
599
hibernate-core/src/main/java/org/hibernate/cache/internal/EnabledCaching.java
vendored
Normal file
599
hibernate-core/src/main/java/org/hibernate/cache/internal/EnabledCaching.java
vendored
Normal file
|
@ -0,0 +1,599 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cache.cfg.spi.CollectionDataCachingConfig;
|
||||
import org.hibernate.cache.cfg.spi.DomainDataRegionBuildingContext;
|
||||
import org.hibernate.cache.cfg.spi.DomainDataRegionConfig;
|
||||
import org.hibernate.cache.cfg.spi.EntityDataCachingConfig;
|
||||
import org.hibernate.cache.cfg.spi.NaturalIdDataCachingConfig;
|
||||
import org.hibernate.cache.spi.CacheImplementor;
|
||||
import org.hibernate.cache.spi.CacheKeysFactory;
|
||||
import org.hibernate.cache.spi.DomainDataRegion;
|
||||
import org.hibernate.cache.spi.QueryResultRegionAccess;
|
||||
import org.hibernate.cache.spi.QueryResultsRegion;
|
||||
import org.hibernate.cache.spi.Region;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cache.spi.TimestampsRegion;
|
||||
import org.hibernate.cache.spi.TimestampsRegionAccess;
|
||||
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.pretty.MessageHelper;
|
||||
import org.hibernate.type.descriptor.java.StringTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
* @author Strong Liu
|
||||
*/
|
||||
public class EnabledCaching implements CacheImplementor, DomainDataRegionBuildingContext {
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( EnabledCaching.class );
|
||||
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
private final RegionFactory regionFactory;
|
||||
|
||||
private final Map<String,Region> regionsByName = new ConcurrentHashMap<>();
|
||||
|
||||
private final Map<NavigableRole,EntityDataAccess> entityAccessMap = new ConcurrentHashMap<>();
|
||||
private final Map<NavigableRole,NaturalIdDataAccess> naturalIdAccessMap = new ConcurrentHashMap<>();
|
||||
private final Map<NavigableRole,CollectionDataAccess> collectionAccessMap = new ConcurrentHashMap<>();
|
||||
|
||||
private final TimestampsRegionAccess timestampsRegionAccess;
|
||||
|
||||
private final QueryResultRegionAccess defaultQueryResultsRegionAccess;
|
||||
private final Map<String, QueryResultRegionAccess> namedQueryResultsRegionAccess = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
private final Set<String> legacySecondLevelCacheNames = new LinkedHashSet<>();
|
||||
private final Map<String,Set<NaturalIdDataAccess>> legacyNaturalIdAccessesForRegion = new ConcurrentHashMap<>();
|
||||
|
||||
public EnabledCaching(SessionFactoryImplementor sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
|
||||
this.regionFactory = getSessionFactory().getSessionFactoryOptions().getServiceRegistry().getService( RegionFactory.class );
|
||||
|
||||
if ( getSessionFactory().getSessionFactoryOptions().isQueryCacheEnabled() ) {
|
||||
final TimestampsRegion timestampsRegion = regionFactory.buildTimestampsRegion(
|
||||
TimestampsRegion.class.getName(),
|
||||
sessionFactory
|
||||
);
|
||||
timestampsRegionAccess = sessionFactory.getSessionFactoryOptions()
|
||||
.getTimestampsRegionAccessFactory()
|
||||
.buildTimestampsRegionAccess( this, timestampsRegion );
|
||||
|
||||
final QueryResultsRegion queryResultsRegion = regionFactory.buildQueryResultsRegion(
|
||||
QueryResultRegionAccessImpl.class.getName(),
|
||||
sessionFactory
|
||||
);
|
||||
regionsByName.put( queryResultsRegion.getName(), queryResultsRegion );
|
||||
defaultQueryResultsRegionAccess = new QueryResultRegionAccessImpl(
|
||||
queryResultsRegion,
|
||||
timestampsRegionAccess
|
||||
);
|
||||
}
|
||||
else {
|
||||
timestampsRegionAccess = new TimestampsRegionAccessDisabledImpl();
|
||||
defaultQueryResultsRegionAccess = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prime(Set<DomainDataRegionConfig> cacheRegionConfigs) {
|
||||
for ( DomainDataRegionConfig regionConfig : cacheRegionConfigs ) {
|
||||
final DomainDataRegion region = getRegionFactory().buildDomainDataRegion( regionConfig, this );
|
||||
regionsByName.put( region.getName(), region );
|
||||
|
||||
if ( !StringTypeDescriptor.INSTANCE.areEqual( region.getName(), regionConfig.getRegionName() ) ) {
|
||||
throw new HibernateException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Region returned from RegionFactory was named differently than requested name. Expecting `%s`, but found `%s`",
|
||||
regionConfig.getRegionName(),
|
||||
region.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Entity caching
|
||||
|
||||
for ( EntityDataCachingConfig entityAccessConfig : regionConfig.getEntityCaching() ) {
|
||||
final EntityDataAccess entityDataAccess = entityAccessMap.put(
|
||||
entityAccessConfig.getNavigableRole(),
|
||||
region.getEntityDataAccess( entityAccessConfig.getNavigableRole() )
|
||||
);
|
||||
|
||||
legacySecondLevelCacheNames.add(
|
||||
StringHelper.qualifyConditionally(
|
||||
getSessionFactory().getSessionFactoryOptions().getCacheRegionPrefix(),
|
||||
region.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Natural-id caching
|
||||
|
||||
if ( regionConfig.getNaturalIdCaching().isEmpty() ) {
|
||||
legacyNaturalIdAccessesForRegion.put( region.getName(), Collections.emptySet() );
|
||||
}
|
||||
else {
|
||||
final HashSet<NaturalIdDataAccess> accesses = new HashSet<>();
|
||||
|
||||
for ( NaturalIdDataCachingConfig naturalIdAccessConfig : regionConfig.getNaturalIdCaching() ) {
|
||||
final NaturalIdDataAccess naturalIdDataAccess = naturalIdAccessMap.put(
|
||||
naturalIdAccessConfig.getNavigableRole(),
|
||||
region.getNaturalIdDataAccess( naturalIdAccessConfig.getNavigableRole() )
|
||||
);
|
||||
accesses.add( naturalIdDataAccess );
|
||||
}
|
||||
|
||||
legacyNaturalIdAccessesForRegion.put( region.getName(), accesses );
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Collection caching
|
||||
|
||||
for ( CollectionDataCachingConfig collectionAccessConfig : regionConfig.getCollectionCaching() ) {
|
||||
final CollectionDataAccess collectionDataAccess = collectionAccessMap.put(
|
||||
collectionAccessConfig.getNavigableRole(),
|
||||
region.getCollectionDataAccess( collectionAccessConfig.getNavigableRole() )
|
||||
);
|
||||
|
||||
legacySecondLevelCacheNames.add(
|
||||
StringHelper.qualifyConditionally(
|
||||
getSessionFactory().getSessionFactoryOptions().getCacheRegionPrefix(),
|
||||
region.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CacheKeysFactory getEnforcedCacheKeysFactory() {
|
||||
// todo (6.0) : allow configuration of this
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionFactoryImplementor getSessionFactory() {
|
||||
return sessionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionFactory getRegionFactory() {
|
||||
return regionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimestampsRegionAccess getTimestampsRegionAccess() {
|
||||
return timestampsRegionAccess;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Region getRegion(String regionName) {
|
||||
return regionsByName.get( regionName );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Entity data
|
||||
|
||||
@Override
|
||||
public boolean containsEntity(Class entityClass, Serializable identifier) {
|
||||
return containsEntity( entityClass.getName(), identifier );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsEntity(String entityName, Serializable identifier) {
|
||||
final EntityPersister entityDescriptor = sessionFactory.getMetamodel().entityPersister( entityName );
|
||||
final EntityDataAccess cacheAccess = entityDescriptor.getCacheAccessStrategy();
|
||||
if ( cacheAccess == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Object key = cacheAccess.generateCacheKey( identifier, entityDescriptor, sessionFactory, null );
|
||||
return cacheAccess.contains( key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictEntityData(Class entityClass, Serializable identifier) {
|
||||
evictEntityData( entityClass.getName(), identifier );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictEntityData(String entityName, Serializable identifier) {
|
||||
final EntityPersister entityDescriptor = sessionFactory.getMetamodel().entityPersister( entityName );
|
||||
final EntityDataAccess cacheAccess = entityDescriptor.getCacheAccessStrategy();
|
||||
if ( cacheAccess == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debugf(
|
||||
"Evicting second-level cache: %s",
|
||||
MessageHelper.infoString( entityDescriptor, identifier, sessionFactory )
|
||||
);
|
||||
}
|
||||
|
||||
final Object key = cacheAccess.generateCacheKey( identifier, entityDescriptor, sessionFactory, null );
|
||||
cacheAccess.evict( key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictEntityData(Class entityClass) {
|
||||
evictEntityData( entityClass.getName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictEntityData(String entityName) {
|
||||
evictEntityData( getSessionFactory().getMetamodel().entityPersister( entityName ) );
|
||||
}
|
||||
|
||||
protected void evictEntityData(EntityPersister entityDescriptor) {
|
||||
EntityPersister rootEntityDescriptor = entityDescriptor;
|
||||
if ( entityDescriptor.isInherited()
|
||||
&& ! entityDescriptor.getEntityName().equals( entityDescriptor.getRootEntityName() ) ) {
|
||||
rootEntityDescriptor = getSessionFactory().getMetamodel().entityPersister( entityDescriptor.getRootEntityName() );
|
||||
}
|
||||
|
||||
evictEntityData(
|
||||
rootEntityDescriptor.getNavigableRole(),
|
||||
rootEntityDescriptor.getCacheAccessStrategy()
|
||||
);
|
||||
}
|
||||
|
||||
private void evictEntityData(NavigableRole navigableRole, EntityDataAccess cacheAccess) {
|
||||
if ( cacheAccess == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debugf( "Evicting entity cache: %s", navigableRole.getFullPath() );
|
||||
}
|
||||
|
||||
cacheAccess.evictAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictEntityData() {
|
||||
sessionFactory.getMetamodel().entityPersisters().values().forEach( this::evictEntityData );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Natural-id data
|
||||
|
||||
@Override
|
||||
public void evictNaturalIdData(Class entityClass) {
|
||||
evictNaturalIdData( entityClass.getName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictNaturalIdData(String entityName) {
|
||||
evictNaturalIdData(
|
||||
sessionFactory.getMetamodel().entityPersister( entityName )
|
||||
);
|
||||
}
|
||||
|
||||
private void evictNaturalIdData(EntityPersister rootEntityDescriptor) {
|
||||
evictNaturalIdData( rootEntityDescriptor.getNavigableRole(), rootEntityDescriptor.getNaturalIdCacheAccessStrategy() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictNaturalIdData() {
|
||||
naturalIdAccessMap.forEach( this::evictNaturalIdData );
|
||||
}
|
||||
|
||||
private void evictNaturalIdData(NavigableRole rootEntityRole, NaturalIdDataAccess cacheAccess) {
|
||||
if ( cacheAccess == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debugf( "Evicting natural-id cache: %s", rootEntityRole.getFullPath() );
|
||||
}
|
||||
|
||||
cacheAccess.evictAll();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Collection data
|
||||
|
||||
@Override
|
||||
public boolean containsCollection(String role, Serializable ownerIdentifier) {
|
||||
final CollectionPersister collectionDescriptor = sessionFactory.getMetamodel()
|
||||
.collectionPersister( role );
|
||||
|
||||
final CollectionDataAccess cacheAccess = collectionDescriptor.getCacheAccessStrategy();
|
||||
if ( cacheAccess == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Object key = cacheAccess.generateCacheKey( ownerIdentifier, collectionDescriptor, sessionFactory, null );
|
||||
return cacheAccess.contains( key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictCollectionData(String role, Serializable ownerIdentifier) {
|
||||
final CollectionPersister collectionDescriptor = sessionFactory.getMetamodel()
|
||||
.collectionPersister( role );
|
||||
|
||||
final CollectionDataAccess cacheAccess = collectionDescriptor.getCacheAccessStrategy();
|
||||
if ( cacheAccess == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debugf(
|
||||
"Evicting second-level cache: %s",
|
||||
MessageHelper.collectionInfoString( collectionDescriptor, ownerIdentifier, sessionFactory )
|
||||
);
|
||||
}
|
||||
|
||||
final Object key = cacheAccess.generateCacheKey( ownerIdentifier, collectionDescriptor, sessionFactory, null );
|
||||
cacheAccess.evict( key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictCollectionData(String role) {
|
||||
final CollectionPersister collectionDescriptor = sessionFactory.getMetamodel()
|
||||
.collectionPersister( role );
|
||||
|
||||
evictCollectionData( collectionDescriptor );
|
||||
}
|
||||
|
||||
private void evictCollectionData(CollectionPersister collectionDescriptor) {
|
||||
evictCollectionData(
|
||||
collectionDescriptor.getNavigableRole(),
|
||||
collectionDescriptor.getCacheAccessStrategy()
|
||||
);
|
||||
}
|
||||
|
||||
private void evictCollectionData(NavigableRole navigableRole, CollectionDataAccess cacheAccess) {
|
||||
if ( cacheAccess == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debugf( "Evicting second-level cache: %s", navigableRole.getFullPath() );
|
||||
}
|
||||
cacheAccess.evictAll();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictCollectionData() {
|
||||
collectionAccessMap.forEach( this::evictCollectionData );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Query-results data
|
||||
|
||||
@Override
|
||||
public boolean containsQuery(String regionName) {
|
||||
final QueryResultRegionAccess cacheAccess = getQueryResultsRegionAccessStrictly( regionName );
|
||||
return cacheAccess != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictDefaultQueryRegion() {
|
||||
evictQueryResultRegion( defaultQueryResultsRegionAccess );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictQueryRegion(String regionName) {
|
||||
final QueryResultRegionAccess cacheAccess = getQueryResultsRegionAccess( regionName );
|
||||
if ( cacheAccess == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
evictQueryResultRegion( cacheAccess );
|
||||
}
|
||||
|
||||
private void evictQueryResultRegion(QueryResultRegionAccess cacheAccess) {
|
||||
if ( cacheAccess == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debugf( "Evicting query cache, region: %s", cacheAccess.getRegion().getName() );
|
||||
}
|
||||
|
||||
cacheAccess.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictQueryRegions() {
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debug( "Evicting cache of all query regions." );
|
||||
}
|
||||
|
||||
evictQueryResultRegion( defaultQueryResultsRegionAccess );
|
||||
|
||||
for ( QueryResultRegionAccess cacheAccess : namedQueryResultsRegionAccess.values() ) {
|
||||
evictQueryResultRegion( cacheAccess );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResultRegionAccess getDefaultQueryResultsRegionAccess() {
|
||||
return defaultQueryResultsRegionAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResultRegionAccess getQueryResultsRegionAccess(String regionName) throws HibernateException {
|
||||
if ( !getSessionFactory().getSessionFactoryOptions().isQueryCacheEnabled() ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
if ( regionName == null || regionName.equals( getDefaultQueryResultsRegionAccess().getRegion().getName() ) ) {
|
||||
return getDefaultQueryResultsRegionAccess();
|
||||
}
|
||||
|
||||
final QueryResultRegionAccess existing = namedQueryResultsRegionAccess.get( regionName );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
return makeQueryResultsRegionAccess( regionName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResultRegionAccess getQueryResultsRegionAccessStrictly(String regionName) {
|
||||
if ( !getSessionFactory().getSessionFactoryOptions().isQueryCacheEnabled() ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return namedQueryResultsRegionAccess.get( regionName );
|
||||
}
|
||||
|
||||
protected QueryResultRegionAccess makeQueryResultsRegionAccess(String regionName) {
|
||||
final QueryResultsRegion region = (QueryResultsRegion) regionsByName.computeIfAbsent(
|
||||
regionName,
|
||||
this::makeQueryResultsRegion
|
||||
);
|
||||
final QueryResultRegionAccessImpl regionAccess = new QueryResultRegionAccessImpl(
|
||||
region,
|
||||
timestampsRegionAccess
|
||||
);
|
||||
namedQueryResultsRegionAccess.put( regionName, regionAccess );
|
||||
return regionAccess;
|
||||
}
|
||||
|
||||
protected QueryResultsRegion makeQueryResultsRegion(String regionName) {
|
||||
// make sure there is not an existing domain-data region with that name..
|
||||
final Region existing = regionsByName.get( regionName );
|
||||
if ( existing != null ) {
|
||||
if ( !QueryResultsRegion.class.isInstance( existing ) ) {
|
||||
throw new IllegalStateException( "Cannot store both domain-data and query-result-data in the same region [" + regionName );
|
||||
}
|
||||
|
||||
throw new IllegalStateException( "Illegal call to create QueryResultsRegion - one already existed" );
|
||||
}
|
||||
|
||||
return regionFactory.buildQueryResultsRegion( regionName, getSessionFactory() );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Set<String> getCacheRegionNames() {
|
||||
return regionsByName.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evictRegion(String regionName) {
|
||||
getRegion( regionName ).clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T unwrap(Class<T> cls) {
|
||||
if ( org.hibernate.Cache.class.isAssignableFrom( cls ) ) {
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
if ( RegionFactory.class.isAssignableFrom( cls ) ) {
|
||||
return (T) regionFactory;
|
||||
}
|
||||
|
||||
throw new PersistenceException( "Hibernate cannot unwrap Cache as " + cls.getName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
for ( Region region : regionsByName.values() ) {
|
||||
region.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// JPA-defined methods
|
||||
|
||||
@Override
|
||||
public boolean contains(Class cls, Object primaryKey) {
|
||||
// JPA
|
||||
return containsEntity( cls, (Serializable) primaryKey );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evict(Class cls, Object primaryKey) {
|
||||
// JPA call
|
||||
evictEntityData( cls, (Serializable) primaryKey );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evict(Class cls) {
|
||||
// JPA
|
||||
evictEntityData( cls );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Deprecations
|
||||
|
||||
@Override
|
||||
public EntityDataAccess getEntityRegionAccess(NavigableRole rootEntityName) {
|
||||
return entityAccessMap.get( rootEntityName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NaturalIdDataAccess getNaturalIdRegionAccess(NavigableRole rootEntityName) {
|
||||
return naturalIdAccessMap.get( rootEntityName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionDataAccess getCollectionRegionAccess(NavigableRole collectionRole) {
|
||||
return collectionAccessMap.get( collectionRole );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSecondLevelCacheRegionNames() {
|
||||
return ArrayHelper.toStringArray( legacySecondLevelCacheNames );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Set<NaturalIdDataAccess> getNaturalIdAccessesInRegion(String regionName) {
|
||||
return legacyNaturalIdAccessesForRegion.get( regionName );
|
||||
}
|
||||
}
|
|
@ -6,19 +6,21 @@
|
|||
*/
|
||||
package org.hibernate.cache.internal;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.NoCacheRegionFactoryAvailableException;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
import org.hibernate.cache.spi.NaturalIdRegion;
|
||||
import org.hibernate.cache.cfg.spi.DomainDataRegionBuildingContext;
|
||||
import org.hibernate.cache.cfg.spi.DomainDataRegionConfig;
|
||||
import org.hibernate.cache.spi.CacheTransactionSynchronization;
|
||||
import org.hibernate.cache.spi.DomainDataRegion;
|
||||
import org.hibernate.cache.spi.QueryResultsRegion;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cache.spi.TimestampsRegion;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
||||
/**
|
||||
* Factory used if no caching enabled in config...
|
||||
|
@ -38,7 +40,7 @@ public class NoCachingRegionFactory implements RegionFactory {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void start(SessionFactoryOptions settings, Properties properties) throws CacheException {
|
||||
public void start(SessionFactoryOptions settings, Map configValues) throws CacheException {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -61,32 +63,25 @@ public class NoCachingRegionFactory implements RegionFactory {
|
|||
}
|
||||
|
||||
@Override
|
||||
public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata)
|
||||
throws CacheException {
|
||||
public CacheTransactionSynchronization createTransactionContext(SharedSessionContractImplementor session) {
|
||||
return new NoCachingTransactionSynchronizationImpl( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainDataRegion buildDomainDataRegion(
|
||||
DomainDataRegionConfig regionConfig, DomainDataRegionBuildingContext buildingContext) {
|
||||
throw new NoCacheRegionFactoryAvailableException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata)
|
||||
throws CacheException {
|
||||
public QueryResultsRegion buildQueryResultsRegion(
|
||||
String regionName, SessionFactoryImplementor sessionFactory) {
|
||||
throw new NoCacheRegionFactoryAvailableException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionRegion buildCollectionRegion(
|
||||
String regionName,
|
||||
Properties properties,
|
||||
CacheDataDescription metadata) throws CacheException {
|
||||
throw new NoCacheRegionFactoryAvailableException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException {
|
||||
throw new NoCacheRegionFactoryAvailableException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException {
|
||||
public TimestampsRegion buildTimestampsRegion(
|
||||
String regionName, SessionFactoryImplementor sessionFactory) {
|
||||
throw new NoCacheRegionFactoryAvailableException();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.internal;
|
||||
|
||||
import org.hibernate.cache.spi.AbstractCacheTransactionSynchronization;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NoCachingTransactionSynchronizationImpl extends AbstractCacheTransactionSynchronization {
|
||||
public NoCachingTransactionSynchronizationImpl(RegionFactory regionFactory) {
|
||||
super( regionFactory );
|
||||
}
|
||||
}
|
|
@ -1,86 +1,52 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.UnresolvableObjectException;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.QueryCache;
|
||||
import org.hibernate.cache.spi.QueryKey;
|
||||
import org.hibernate.cache.spi.QueryResultRegionAccess;
|
||||
import org.hibernate.cache.spi.QueryResultsRegion;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cache.spi.UpdateTimestampsCache;
|
||||
import org.hibernate.engine.spi.CacheImplementor;
|
||||
import org.hibernate.cache.spi.QuerySpacesHelper;
|
||||
import org.hibernate.cache.spi.TimestampsRegionAccess;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.TypeHelper;
|
||||
|
||||
/**
|
||||
* The standard implementation of the Hibernate QueryCache interface. This
|
||||
* implementation is very good at recognizing stale query results and
|
||||
* and re-running queries when it detects this condition, re-caching the new
|
||||
* results.
|
||||
* The standard implementation of the Hibernate QueryCache interface. Works
|
||||
* hind-in-hand with {@link TimestampsRegionAccess} to help in recognizing
|
||||
* stale query results.
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class StandardQueryCache implements QueryCache {
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( StandardQueryCache.class );
|
||||
public class QueryResultRegionAccessImpl implements QueryResultRegionAccess {
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( QueryResultRegionAccessImpl.class );
|
||||
|
||||
private static final boolean DEBUGGING = LOG.isDebugEnabled();
|
||||
private static final boolean TRACING = LOG.isTraceEnabled();
|
||||
|
||||
private final QueryResultsRegion cacheRegion;
|
||||
private final UpdateTimestampsCache updateTimestampsCache;
|
||||
private final TimestampsRegionAccess timestampsCache;
|
||||
|
||||
/**
|
||||
* Constructs a StandardQueryCache instance
|
||||
*
|
||||
* @param settings The SessionFactory settings.
|
||||
* @param props Any properties
|
||||
* @param updateTimestampsCache The update-timestamps cache to use.
|
||||
* @param regionName The base query cache region name
|
||||
*/
|
||||
public StandardQueryCache(
|
||||
final SessionFactoryOptions settings,
|
||||
final Properties props,
|
||||
final UpdateTimestampsCache updateTimestampsCache,
|
||||
final String regionName) {
|
||||
String regionNameToUse = regionName;
|
||||
if ( regionNameToUse == null ) {
|
||||
regionNameToUse = StandardQueryCache.class.getName();
|
||||
}
|
||||
final String prefix = settings.getCacheRegionPrefix();
|
||||
if ( prefix != null ) {
|
||||
regionNameToUse = prefix + '.' + regionNameToUse;
|
||||
}
|
||||
LOG.startingQueryCache( regionNameToUse );
|
||||
|
||||
this.cacheRegion = settings.getServiceRegistry().getService( RegionFactory.class ).buildQueryResultsRegion(
|
||||
regionNameToUse,
|
||||
props
|
||||
);
|
||||
this.updateTimestampsCache = updateTimestampsCache;
|
||||
}
|
||||
|
||||
public StandardQueryCache(QueryResultsRegion cacheRegion, CacheImplementor cacheManager) {
|
||||
LOG.startingQueryCache( cacheRegion.getName() );
|
||||
QueryResultRegionAccessImpl(
|
||||
QueryResultsRegion cacheRegion,
|
||||
TimestampsRegionAccess timestampsCache) {
|
||||
this.cacheRegion = cacheRegion;
|
||||
this.updateTimestampsCache = cacheManager.getUpdateTimestampsCache();
|
||||
this.timestampsCache = timestampsCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -88,56 +54,46 @@ public class StandardQueryCache implements QueryCache {
|
|||
return cacheRegion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
try {
|
||||
cacheRegion.destroy();
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
LOG.unableToDestroyQueryCache( cacheRegion.getName(), e.getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() throws CacheException {
|
||||
cacheRegion.evictAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public boolean put(
|
||||
final QueryKey key,
|
||||
final List results,
|
||||
final Type[] returnTypes,
|
||||
final List result,
|
||||
final boolean isNaturalKeyLookup,
|
||||
final SharedSessionContractImplementor session) throws HibernateException {
|
||||
if ( isNaturalKeyLookup && result.isEmpty() ) {
|
||||
return false;
|
||||
}
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debugf( "Caching query results in region: %s; timestamp=%s", cacheRegion.getName(), session.getTimestamp() );
|
||||
LOG.debugf( "Caching query results in region: %s; timestamp=%s", cacheRegion.getName(), session.getTransactionStartTimestamp() );
|
||||
}
|
||||
|
||||
final List cacheable = new ArrayList( result.size() + 1 );
|
||||
if ( TRACING ) {
|
||||
logCachedResultDetails( key, null, returnTypes, cacheable );
|
||||
}
|
||||
cacheable.add( session.getTimestamp() );
|
||||
final List resultsCopy = CollectionHelper.arrayList( results.size() );
|
||||
|
||||
final boolean isSingleResult = returnTypes.length == 1;
|
||||
for ( Object aResult : result ) {
|
||||
final Serializable cacheItem = isSingleResult
|
||||
? returnTypes[0].disassemble( aResult, session, null )
|
||||
: TypeHelper.disassemble( (Object[]) aResult, returnTypes, null, session, null );
|
||||
cacheable.add( cacheItem );
|
||||
for ( Object aResult : results ) {
|
||||
final Serializable resultRowForCache;
|
||||
if ( isSingleResult ) {
|
||||
resultRowForCache = returnTypes[0].disassemble( aResult, session, null );
|
||||
}
|
||||
else {
|
||||
resultRowForCache = TypeHelper.disassemble( (Object[]) aResult, returnTypes, null, session, null );
|
||||
}
|
||||
resultsCopy.add( resultRowForCache );
|
||||
if ( TRACING ) {
|
||||
logCachedResultRowDetails( returnTypes, aResult );
|
||||
}
|
||||
}
|
||||
|
||||
if ( TRACING ) {
|
||||
logCachedResultDetails( key, null, returnTypes, resultsCopy );
|
||||
}
|
||||
|
||||
final CacheItem cacheItem = new CacheItem(
|
||||
session.getTransactionStartTimestamp(),
|
||||
resultsCopy
|
||||
);
|
||||
|
||||
try {
|
||||
session.getEventListenerManager().cachePutStart();
|
||||
cacheRegion.put( session, key, cacheable );
|
||||
cacheRegion.getAccess().addToCache( key, cacheItem );
|
||||
}
|
||||
finally {
|
||||
session.getEventListenerManager().cachePutEnd();
|
||||
|
@ -146,123 +102,6 @@ public class StandardQueryCache implements QueryCache {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public List get(
|
||||
final QueryKey key,
|
||||
final Type[] returnTypes,
|
||||
final boolean isNaturalKeyLookup,
|
||||
final Set<Serializable> spaces,
|
||||
final SharedSessionContractImplementor session) throws HibernateException {
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debugf( "Checking cached query results in region: %s", cacheRegion.getName() );
|
||||
}
|
||||
|
||||
final List cacheable = getCachedResults( key, session );
|
||||
if ( TRACING ) {
|
||||
logCachedResultDetails( key, spaces, returnTypes, cacheable );
|
||||
}
|
||||
if ( cacheable == null ) {
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debug( "Query results were not found in cache" );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final Long timestamp = (Long) cacheable.get( 0 );
|
||||
if ( !isNaturalKeyLookup && !isUpToDate( spaces, timestamp, session ) ) {
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debug( "Cached query results were not up-to-date" );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debug( "Returning cached query results" );
|
||||
}
|
||||
final boolean singleResult = returnTypes.length == 1;
|
||||
for ( int i = 1; i < cacheable.size(); i++ ) {
|
||||
if ( singleResult ) {
|
||||
returnTypes[0].beforeAssemble( (Serializable) cacheable.get( i ), session );
|
||||
}
|
||||
else {
|
||||
TypeHelper.beforeAssemble( (Serializable[]) cacheable.get( i ), returnTypes, session );
|
||||
}
|
||||
}
|
||||
|
||||
return assembleCachedResult(key, cacheable, isNaturalKeyLookup, singleResult, returnTypes, session);
|
||||
}
|
||||
|
||||
private List assembleCachedResult(
|
||||
final QueryKey key,
|
||||
final List cacheable,
|
||||
final boolean isNaturalKeyLookup,
|
||||
boolean singleResult,
|
||||
final Type[] returnTypes,
|
||||
final SharedSessionContractImplementor session) throws HibernateException {
|
||||
|
||||
try {
|
||||
final List result = new ArrayList( cacheable.size() - 1 );
|
||||
if ( singleResult ) {
|
||||
for ( int i = 1; i < cacheable.size(); i++ ) {
|
||||
result.add( returnTypes[0].assemble( (Serializable) cacheable.get( i ), session, null ) );
|
||||
}
|
||||
}
|
||||
else {
|
||||
for ( int i = 1; i < cacheable.size(); i++ ) {
|
||||
result.add(
|
||||
TypeHelper.assemble( (Serializable[]) cacheable.get( i ), returnTypes, session, null )
|
||||
);
|
||||
if ( TRACING ) {
|
||||
logCachedResultRowDetails( returnTypes, result.get( i - 1 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch ( RuntimeException ex ) {
|
||||
if ( isNaturalKeyLookup ) {
|
||||
// potentially perform special handling for natural-id look ups.
|
||||
if ( UnresolvableObjectException.class.isInstance( ex )
|
||||
|| EntityNotFoundException.class.isInstance( ex ) ) {
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debug( "Unable to reassemble cached natural-id query result" );
|
||||
}
|
||||
cacheRegion.evict( key );
|
||||
|
||||
// EARLY EXIT !
|
||||
return null;
|
||||
}
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
private List getCachedResults(QueryKey key, SharedSessionContractImplementor session) {
|
||||
List cacheable = null;
|
||||
try {
|
||||
session.getEventListenerManager().cacheGetStart();
|
||||
cacheable = (List) cacheRegion.get( session, key );
|
||||
}
|
||||
finally {
|
||||
session.getEventListenerManager().cacheGetEnd( cacheable != null );
|
||||
}
|
||||
return cacheable;
|
||||
}
|
||||
|
||||
|
||||
protected boolean isUpToDate(Set<Serializable> spaces, Long timestamp, SharedSessionContractImplementor session) {
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debugf( "Checking query spaces are up-to-date: %s", spaces );
|
||||
}
|
||||
return updateTimestampsCache.isUpToDate( spaces, timestamp, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StandardQueryCache(" + cacheRegion.getName() + ')';
|
||||
}
|
||||
|
||||
private static void logCachedResultDetails(QueryKey key, Set querySpaces, Type[] returnTypes, List result) {
|
||||
if ( !TRACING ) {
|
||||
return;
|
||||
|
@ -289,6 +128,102 @@ public class StandardQueryCache implements QueryCache {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List get(
|
||||
QueryKey key,
|
||||
Set<Serializable> spaces,
|
||||
final Type[] returnTypes,
|
||||
SharedSessionContractImplementor session) {
|
||||
return get(
|
||||
key,
|
||||
QuerySpacesHelper.INSTANCE.toStringArray( spaces ),
|
||||
returnTypes,
|
||||
session
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public List get(
|
||||
final QueryKey key,
|
||||
final String[] spaces,
|
||||
final Type[] returnTypes,
|
||||
final SharedSessionContractImplementor session) {
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debugf( "Checking cached query results in region: %s", cacheRegion.getName() );
|
||||
}
|
||||
|
||||
final CacheItem cacheItem = getCachedData( key, session );
|
||||
if ( cacheItem == null ) {
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debug( "Query results were not found in cache" );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( !timestampsCache.isUpToDate( spaces, cacheItem.timestamp, session ) ) {
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debug( "Cached query results were not up-to-date" );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debug( "Returning cached query results" );
|
||||
}
|
||||
|
||||
final boolean singleResult = returnTypes.length == 1;
|
||||
for ( int i = 0; i < cacheItem.results.size(); i++ ) {
|
||||
if ( singleResult ) {
|
||||
returnTypes[0].beforeAssemble( (Serializable) cacheItem.results.get( i ), session );
|
||||
}
|
||||
else {
|
||||
TypeHelper.beforeAssemble( (Serializable[]) cacheItem.results.get( i ), returnTypes, session );
|
||||
}
|
||||
}
|
||||
|
||||
return assembleCachedResult( key, cacheItem.results, singleResult, returnTypes, session );
|
||||
}
|
||||
|
||||
private CacheItem getCachedData(QueryKey key, SharedSessionContractImplementor session) {
|
||||
CacheItem cachedItem = null;
|
||||
try {
|
||||
session.getEventListenerManager().cacheGetStart();
|
||||
cachedItem = (CacheItem) cacheRegion.getAccess().getFromCache( key );
|
||||
}
|
||||
finally {
|
||||
session.getEventListenerManager().cacheGetEnd( cachedItem != null );
|
||||
}
|
||||
return cachedItem;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List assembleCachedResult(
|
||||
final QueryKey key,
|
||||
final List cached,
|
||||
boolean singleResult,
|
||||
final Type[] returnTypes,
|
||||
final SharedSessionContractImplementor session) throws HibernateException {
|
||||
|
||||
final List result = new ArrayList( cached.size() );
|
||||
if ( singleResult ) {
|
||||
for ( Object aCached : cached ) {
|
||||
result.add( returnTypes[0].assemble( (Serializable) aCached, session, null ) );
|
||||
}
|
||||
}
|
||||
else {
|
||||
for ( int i = 0; i < cached.size(); i++ ) {
|
||||
result.add(
|
||||
TypeHelper.assemble( (Serializable[]) cached.get( i ), returnTypes, session, null )
|
||||
);
|
||||
if ( TRACING ) {
|
||||
logCachedResultRowDetails( returnTypes, result.get( i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void logCachedResultRowDetails(Type[] returnTypes, Object result) {
|
||||
logCachedResultRowDetails(
|
||||
returnTypes,
|
||||
|
@ -345,4 +280,24 @@ public class StandardQueryCache implements QueryCache {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "QueryResultsCache(" + cacheRegion.getName() + ')';
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() throws CacheException {
|
||||
cacheRegion.getAccess().clearCache();
|
||||
}
|
||||
|
||||
public static class CacheItem implements Serializable {
|
||||
private final long timestamp;
|
||||
private final List results;
|
||||
|
||||
CacheItem(long timestamp, List results) {
|
||||
this.timestamp = timestamp;
|
||||
this.results = results;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.cache.internal;
|
||||
|
||||
import org.hibernate.cache.spi.QueryCache;
|
||||
import org.hibernate.cache.spi.QueryCacheFactory;
|
||||
import org.hibernate.cache.spi.QueryResultsRegion;
|
||||
import org.hibernate.engine.spi.CacheImplementor;
|
||||
|
||||
/**
|
||||
* Standard Hibernate implementation of the QueryCacheFactory interface. Returns instances of
|
||||
* {@link StandardQueryCache}.
|
||||
*/
|
||||
public class StandardQueryCacheFactory implements QueryCacheFactory {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final StandardQueryCacheFactory INSTANCE = new StandardQueryCacheFactory();
|
||||
|
||||
@Override
|
||||
public QueryCache buildQueryCache(QueryResultsRegion region, CacheImplementor cacheManager) {
|
||||
return new StandardQueryCache( region, cacheManager );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.internal;
|
||||
|
||||
import org.hibernate.cache.spi.CacheImplementor;
|
||||
import org.hibernate.cache.spi.TimestampsRegionAccess;
|
||||
import org.hibernate.cache.spi.TimestampsRegionAccessFactory;
|
||||
import org.hibernate.cache.spi.TimestampsRegion;
|
||||
|
||||
/**
|
||||
* Standard Hibernate implementation of the QueryCacheFactory interface. Returns instances of
|
||||
* {@link QueryResultRegionAccessImpl}.
|
||||
*/
|
||||
public class StandardTimestampsRegionAccessFactory implements TimestampsRegionAccessFactory {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final StandardTimestampsRegionAccessFactory INSTANCE = new StandardTimestampsRegionAccessFactory();
|
||||
|
||||
@Override
|
||||
public TimestampsRegionAccess buildTimestampsRegionAccess(
|
||||
CacheImplementor cacheManager,
|
||||
TimestampsRegion timestampsRegion) {
|
||||
return new TimestampsRegionAccessEnabledImpl( timestampsRegion );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.internal;
|
||||
|
||||
import org.hibernate.cache.spi.TimestampsRegionAccess;
|
||||
import org.hibernate.cache.spi.TimestampsRegion;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* TimestampsRegionAccess implementation for cases where query results caching
|
||||
* (or second level caching overall) is disabled.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class TimestampsRegionAccessDisabledImpl implements TimestampsRegionAccess {
|
||||
private static final Logger log = Logger.getLogger( TimestampsRegionAccessDisabledImpl.class );
|
||||
|
||||
@Override
|
||||
public TimestampsRegion getRegion() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preInvalidate(String[] spaces, SharedSessionContractImplementor session) {
|
||||
log.trace( "TimestampsRegionAccess#preInvalidate - disabled" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate(String[] spaces, SharedSessionContractImplementor session) {
|
||||
log.trace( "TimestampsRegionAccess#invalidate - disabled" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpToDate(
|
||||
String[] spaces,
|
||||
Long timestamp,
|
||||
SharedSessionContractImplementor session) {
|
||||
log.trace( "TimestampsRegionAccess#isUpToDate - disabled" );
|
||||
return false;
|
||||
}
|
||||
}
|
146
hibernate-core/src/main/java/org/hibernate/cache/internal/TimestampsRegionAccessEnabledImpl.java
vendored
Normal file
146
hibernate-core/src/main/java/org/hibernate/cache/internal/TimestampsRegionAccessEnabledImpl.java
vendored
Normal file
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cache.spi.TimestampsRegionAccess;
|
||||
import org.hibernate.cache.spi.TimestampsRegion;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Standard implementation of QuerySpaceStalenessStrategy
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class TimestampsRegionAccessEnabledImpl implements TimestampsRegionAccess {
|
||||
private static final Logger log = Logger.getLogger( TimestampsRegionAccessEnabledImpl.class );
|
||||
private static final boolean DEBUG_ENABLED = log.isDebugEnabled();
|
||||
|
||||
private final TimestampsRegion timestampsRegion;
|
||||
|
||||
public TimestampsRegionAccessEnabledImpl(TimestampsRegion timestampsRegion) {
|
||||
this.timestampsRegion = timestampsRegion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimestampsRegion getRegion() {
|
||||
return timestampsRegion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preInvalidate(
|
||||
String[] spaces,
|
||||
SharedSessionContractImplementor session) {
|
||||
final SessionFactoryImplementor factory = session.getFactory();
|
||||
final RegionFactory regionFactory = factory.getCache().getRegionFactory();
|
||||
|
||||
final boolean stats = factory.getStatistics().isStatisticsEnabled();
|
||||
|
||||
final Long ts = regionFactory.nextTimestamp() + regionFactory.getTimeout();
|
||||
|
||||
for ( Serializable space : spaces ) {
|
||||
if ( DEBUG_ENABLED ) {
|
||||
log.debugf( "Pre-invalidating space [%s], timestamp: %s", space, ts );
|
||||
}
|
||||
|
||||
try {
|
||||
session.getEventListenerManager().cachePutStart();
|
||||
|
||||
//put() has nowait semantics, is this really appropriate?
|
||||
//note that it needs to be async replication, never local or sync
|
||||
timestampsRegion.getAccess().addToCache( space, ts );
|
||||
}
|
||||
finally {
|
||||
session.getEventListenerManager().cachePutEnd();
|
||||
}
|
||||
|
||||
if ( stats ) {
|
||||
factory.getStatistics().updateTimestampsCachePut();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate(
|
||||
String[] spaces,
|
||||
SharedSessionContractImplementor session) {
|
||||
final boolean stats = session.getFactory().getStatistics().isStatisticsEnabled();
|
||||
|
||||
final Long ts = session.getFactory().getCache().getRegionFactory().nextTimestamp();
|
||||
|
||||
for (Serializable space : spaces) {
|
||||
if ( DEBUG_ENABLED ) {
|
||||
log.debugf( "Invalidating space [%s], timestamp: %s", space, ts );
|
||||
}
|
||||
|
||||
try {
|
||||
session.getEventListenerManager().cachePutStart();
|
||||
timestampsRegion.getAccess().addToCache( space, ts );
|
||||
}
|
||||
finally {
|
||||
session.getEventListenerManager().cachePutEnd();
|
||||
|
||||
if ( stats ) {
|
||||
session.getFactory().getStatistics().updateTimestampsCachePut();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpToDate(
|
||||
String[] spaces,
|
||||
Long timestamp,
|
||||
SharedSessionContractImplementor session) {
|
||||
final boolean stats = session.getFactory().getStatistics().isStatisticsEnabled();
|
||||
|
||||
for ( Serializable space : spaces ) {
|
||||
final Long lastUpdate = getLastUpdateTimestampForSpace( space, session );
|
||||
if ( lastUpdate == null ) {
|
||||
// the last update timestamp for the given space was evicted from the
|
||||
// cache or there have been no writes to it since startup
|
||||
if ( stats ) {
|
||||
session.getFactory().getStatistics().updateTimestampsCacheMiss();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( DEBUG_ENABLED ) {
|
||||
log.debugf(
|
||||
"[%s] last update timestamp: %s",
|
||||
space,
|
||||
lastUpdate + ", result set timestamp: " + timestamp
|
||||
);
|
||||
}
|
||||
if ( stats ) {
|
||||
session.getFactory().getStatistics().updateTimestampsCacheHit();
|
||||
}
|
||||
if ( lastUpdate >= timestamp ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private Long getLastUpdateTimestampForSpace(Serializable space, SharedSessionContractImplementor session) {
|
||||
Long ts = null;
|
||||
try {
|
||||
session.getEventListenerManager().cacheGetStart();
|
||||
ts = (Long) timestampsRegion.getAccess().getFromCache( space );
|
||||
}
|
||||
finally {
|
||||
session.getEventListenerManager().cacheGetEnd( ts != null );
|
||||
}
|
||||
return ts;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractCacheTransactionSynchronization implements CacheTransactionSynchronization {
|
||||
private long lastTransactionCompletionTimestamp;
|
||||
private final RegionFactory regionFactory;
|
||||
|
||||
public AbstractCacheTransactionSynchronization(RegionFactory regionFactory) {
|
||||
// prime the timestamp for any non-transactional access - until (if) we
|
||||
// later join a new txn
|
||||
this.lastTransactionCompletionTimestamp = regionFactory.nextTimestamp();
|
||||
this.regionFactory = regionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCurrentTransactionStartTimestamp() {
|
||||
return lastTransactionCompletionTimestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void transactionJoined() {
|
||||
// reset the timestamp
|
||||
this.lastTransactionCompletionTimestamp = regionFactory.nextTimestamp();
|
||||
processTransactionJoin();
|
||||
}
|
||||
|
||||
private void processTransactionJoin() {
|
||||
// by default, nothing to do.
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void transactionCompleting() {
|
||||
processTransactionCompleting();
|
||||
}
|
||||
|
||||
private void processTransactionCompleting() {
|
||||
// by default, nothing to do.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transactionCompleted(boolean successful) {
|
||||
// reset the timestamp for any non-transactional access after this
|
||||
// point - until (if) we later join a new txn
|
||||
// this.lastTransactionCompletionTimestamp = regionFactory.nextTimestamp();
|
||||
|
||||
processTransactionCompleted( successful );
|
||||
}
|
||||
|
||||
private void processTransactionCompleted(boolean successful) {
|
||||
// by default, nothing to do.
|
||||
}
|
||||
}
|
210
hibernate-core/src/main/java/org/hibernate/cache/spi/AbstractDomainDataRegion.java
vendored
Normal file
210
hibernate-core/src/main/java/org/hibernate/cache/spi/AbstractDomainDataRegion.java
vendored
Normal file
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.cfg.spi.CollectionDataCachingConfig;
|
||||
import org.hibernate.cache.cfg.spi.DomainDataRegionBuildingContext;
|
||||
import org.hibernate.cache.cfg.spi.DomainDataRegionConfig;
|
||||
import org.hibernate.cache.cfg.spi.EntityDataCachingConfig;
|
||||
import org.hibernate.cache.cfg.spi.NaturalIdDataCachingConfig;
|
||||
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractDomainDataRegion implements DomainDataRegion {
|
||||
private final String name;
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
private final RegionFactory regionFactory;
|
||||
|
||||
private final Map<NavigableRole,EntityDataAccess> entityDataAccessMap;
|
||||
private final Map<NavigableRole,NaturalIdDataAccess> naturalIdDataAccessMap;
|
||||
private final Map<NavigableRole,CollectionDataAccess> collectionDataAccessMap;
|
||||
|
||||
public AbstractDomainDataRegion(
|
||||
DomainDataRegionConfig regionConfig,
|
||||
RegionFactory regionFactory,
|
||||
DomainDataRegionBuildingContext buildingContext) {
|
||||
this.name = regionConfig.getRegionName();
|
||||
this.sessionFactory = buildingContext.getSessionFactory();
|
||||
this.regionFactory = regionFactory;
|
||||
|
||||
this.entityDataAccessMap = generateEntityDataAccessMap( regionConfig );
|
||||
this.naturalIdDataAccessMap = generateNaturalIdDataAccessMap( regionConfig );
|
||||
this.collectionDataAccessMap = generateCollectionDataAccessMap( regionConfig );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public SessionFactoryImplementor getSessionFactory() {
|
||||
return sessionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionFactory getRegionFactory() {
|
||||
return regionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityDataAccess getEntityDataAccess(NavigableRole rootEntityRole) {
|
||||
final EntityDataAccess access = entityDataAccessMap.get( rootEntityRole );
|
||||
if ( access == null ) {
|
||||
// todo (6.0) : is it an error here if the entity is not configured for caching (no map hit)?
|
||||
}
|
||||
return access;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public NaturalIdDataAccess getNaturalIdDataAccess(NavigableRole rootEntityRole) {
|
||||
final NaturalIdDataAccess access = naturalIdDataAccessMap.get( rootEntityRole );
|
||||
if ( access == null ) {
|
||||
// todo (6.0) : is it an error here if the entity is not configured for caching (no map hit)?
|
||||
}
|
||||
return access;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionDataAccess getCollectionDataAccess(NavigableRole collectionRole) {
|
||||
final CollectionDataAccess access = collectionDataAccessMap.get( collectionRole );
|
||||
if ( access == null ) {
|
||||
// todo (6.0) : is it an error here if the entity is not configured for caching (no map hit)?
|
||||
}
|
||||
return access;
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// creation
|
||||
|
||||
protected abstract EntityDataAccess generateEntityAccess(EntityDataCachingConfig entityAccessConfig);
|
||||
protected abstract CollectionDataAccess generateCollectionAccess(CollectionDataCachingConfig cachingConfig);
|
||||
protected abstract NaturalIdDataAccess generateNaturalIdAccess(NaturalIdDataCachingConfig naturalIdAccessConfig);
|
||||
|
||||
private Map<NavigableRole, EntityDataAccess> generateEntityDataAccessMap(
|
||||
DomainDataRegionConfig regionConfig) {
|
||||
if ( regionConfig.getEntityCaching().isEmpty() ) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
final Map<NavigableRole, EntityDataAccess> accessMap = new ConcurrentHashMap<>();
|
||||
for ( EntityDataCachingConfig entityAccessConfig : regionConfig.getEntityCaching() ) {
|
||||
accessMap.computeIfAbsent(
|
||||
entityAccessConfig.getNavigableRole(),
|
||||
hierarchy -> generateEntityAccess( entityAccessConfig )
|
||||
);
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap( accessMap );
|
||||
}
|
||||
|
||||
private Map<NavigableRole, NaturalIdDataAccess> generateNaturalIdDataAccessMap(DomainDataRegionConfig regionConfig) {
|
||||
if ( regionConfig.getNaturalIdCaching().isEmpty() ) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
final Map<NavigableRole, NaturalIdDataAccess> accessMap = new ConcurrentHashMap<>();
|
||||
for ( NaturalIdDataCachingConfig naturalIdAccessConfig : regionConfig.getNaturalIdCaching() ) {
|
||||
accessMap.computeIfAbsent(
|
||||
naturalIdAccessConfig.getNavigableRole(),
|
||||
hierarchy -> generateNaturalIdAccess( naturalIdAccessConfig )
|
||||
);
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap( accessMap );
|
||||
}
|
||||
|
||||
private Map<NavigableRole, CollectionDataAccess> generateCollectionDataAccessMap(
|
||||
DomainDataRegionConfig regionConfig) {
|
||||
if ( regionConfig.getCollectionCaching().isEmpty() ) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
final Map<NavigableRole, CollectionDataAccess> accessMap = new ConcurrentHashMap<>();
|
||||
for ( CollectionDataCachingConfig cachingConfig : regionConfig.getCollectionCaching() ) {
|
||||
accessMap.computeIfAbsent(
|
||||
cachingConfig.getNavigableRole(),
|
||||
hierarchy -> generateCollectionAccess( cachingConfig )
|
||||
);
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap( accessMap );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
for ( EntityDataAccess cacheAccess : entityDataAccessMap.values() ) {
|
||||
cacheAccess.evictAll();
|
||||
}
|
||||
|
||||
for ( NaturalIdDataAccess cacheAccess : naturalIdDataAccessMap.values() ) {
|
||||
cacheAccess.evictAll();
|
||||
}
|
||||
|
||||
for ( CollectionDataAccess cacheAccess : collectionDataAccessMap.values() ) {
|
||||
cacheAccess.evictAll();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// destruction
|
||||
|
||||
/**
|
||||
* Optional interface caching implementors can implement in their
|
||||
* CachedDomainDataAccess impls to automatically have them destroyed
|
||||
* when this region is destroyed
|
||||
*/
|
||||
public interface Destructible {
|
||||
void destroy();
|
||||
}
|
||||
|
||||
protected void releaseDataAccess(EntityDataAccess cacheAccess) {
|
||||
if ( Destructible.class.isInstance( cacheAccess ) ) {
|
||||
( (Destructible) cacheAccess ).destroy();
|
||||
}
|
||||
}
|
||||
|
||||
protected void releaseDataAccess(NaturalIdDataAccess cacheAccess) {
|
||||
if ( Destructible.class.isInstance( cacheAccess ) ) {
|
||||
( (Destructible) cacheAccess ).destroy();
|
||||
}
|
||||
}
|
||||
|
||||
protected void releaseDataAccess(CollectionDataAccess cacheAccess) {
|
||||
if ( Destructible.class.isInstance( cacheAccess ) ) {
|
||||
( (Destructible) cacheAccess ).destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws CacheException {
|
||||
for ( EntityDataAccess cacheAccess : entityDataAccessMap.values() ) {
|
||||
releaseDataAccess( cacheAccess );
|
||||
}
|
||||
|
||||
for ( NaturalIdDataAccess cacheAccess : naturalIdDataAccessMap.values() ) {
|
||||
releaseDataAccess( cacheAccess );
|
||||
}
|
||||
|
||||
for ( CollectionDataAccess cacheAccess : collectionDataAccessMap.values() ) {
|
||||
releaseDataAccess( cacheAccess );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Describes attributes regarding the type of data to be cached.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface CacheDataDescription {
|
||||
/**
|
||||
* Is the data marked as being mutable?
|
||||
*
|
||||
* @return {@code true} if the data is mutable; {@code false} otherwise.
|
||||
*/
|
||||
public boolean isMutable();
|
||||
|
||||
/**
|
||||
* Is the data to be cached considered versioned?
|
||||
*
|
||||
* If {@code true}, it is illegal for {@link #getVersionComparator} to return {@code null}
|
||||
* or an instance of {@link org.hibernate.type.descriptor.java.IncomparableComparator}.
|
||||
*
|
||||
* @return {@code true} if the data is versioned; {@code false} otherwise.
|
||||
*/
|
||||
public boolean isVersioned();
|
||||
|
||||
/**
|
||||
* Get the comparator used to compare two different version values. May return {@code null} <b>if</b>
|
||||
* {@link #isVersioned()} returns false.
|
||||
*
|
||||
* @return The comparator for versions, or {@code null}
|
||||
*/
|
||||
public Comparator getVersionComparator();
|
||||
|
||||
/**
|
||||
* @return Type of the key that will be used as the key in the cache, or {@code null} if the natural comparison
|
||||
* ({@link Object#hashCode()} and {@link Object#equals(Object)} methods should be used.
|
||||
*/
|
||||
Type getKeyType();
|
||||
}
|
|
@ -0,0 +1,258 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.Cache;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cache.cfg.spi.DomainDataRegionConfig;
|
||||
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.service.Service;
|
||||
|
||||
/**
|
||||
* SPI contract for Hibernate's second-level cache engine
|
||||
*
|
||||
* @since 4.1
|
||||
*
|
||||
* @author Strong Liu
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface CacheImplementor extends Service, Cache, Serializable {
|
||||
@Override
|
||||
SessionFactoryImplementor getSessionFactory();
|
||||
|
||||
/**
|
||||
* The underlying RegionFactory in use.
|
||||
*
|
||||
* @apiNote CacheImplementor acts partially as a wrapper for details
|
||||
* of interacting with the configured RegionFactory. Care should
|
||||
* be taken when accessing the RegionFactory directly.
|
||||
*/
|
||||
RegionFactory getRegionFactory();
|
||||
|
||||
/**
|
||||
* An initialization phase allowing the caching provider to prime itself
|
||||
* from the passed configs
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
void prime(Set<DomainDataRegionConfig> cacheRegionConfigs);
|
||||
|
||||
/**
|
||||
* Get a cache Region by name
|
||||
*
|
||||
* @apiNote It is only valid to call this method after {@link #prime} has
|
||||
* been performed
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
Region getRegion(String regionName);
|
||||
|
||||
/**
|
||||
* The unqualified name of all regions. Intended for use with {@link #getRegion}
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
Set<String> getCacheRegionNames();
|
||||
|
||||
/**
|
||||
* Find the cache data access strategy for Hibernate's timestamps cache.
|
||||
* Will return {@code null} if Hibernate is not configured for query result caching
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
TimestampsRegionAccess getTimestampsRegionAccess();
|
||||
|
||||
/**
|
||||
* Access to the "default" region used to store query results when caching
|
||||
* was requested but no region was explicitly named. Will return {@code null}
|
||||
* if Hibernate is not configured for query result caching
|
||||
*/
|
||||
QueryResultRegionAccess getDefaultQueryResultsRegionAccess();
|
||||
|
||||
/**
|
||||
* Get query cache by <tt>region name</tt> or create a new one if none exist.
|
||||
*
|
||||
* If the region name is null, then default query cache region will be returned.
|
||||
*
|
||||
* Will return {@code null} if Hibernate is not configured for query result caching
|
||||
*/
|
||||
QueryResultRegionAccess getQueryResultsRegionAccess(String regionName);
|
||||
|
||||
/**
|
||||
* Get the named QueryResultRegionAccess but not creating one if it
|
||||
* does not already exist. This is intended for use by statistics.
|
||||
*
|
||||
* Will return {@code null} if Hibernate is not configured for query result
|
||||
* caching or if no such region (yet) exists
|
||||
*
|
||||
* @since 5.3
|
||||
*/
|
||||
QueryResultRegionAccess getQueryResultsRegionAccessStrictly(String regionName);
|
||||
|
||||
/**
|
||||
* Clean up the default query cache
|
||||
*/
|
||||
default void evictQueries() throws HibernateException {
|
||||
QueryResultRegionAccess cache = getDefaultQueryResultsRegionAccess();
|
||||
if ( cache != null ) {
|
||||
cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close this "cache", releasing all underlying resources.
|
||||
*/
|
||||
void close();
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Deprecations (5.3)
|
||||
|
||||
/**
|
||||
* Get the *qualified* names of all regions caching entity and collection data.
|
||||
*
|
||||
* @return All cache region names
|
||||
*
|
||||
* @deprecated (since 5.3) Use {@link CacheImplementor#getCacheRegionNames()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
String[] getSecondLevelCacheRegionNames();
|
||||
|
||||
/**
|
||||
* Find the cache data access strategy for an entity. Will
|
||||
* return {@code null} when the entity is not configured for caching.
|
||||
*
|
||||
* @param rootEntityName The NavigableRole representation of the root entity
|
||||
*
|
||||
* @apiNote It is only valid to call this method after {@link #prime} has
|
||||
* been performed
|
||||
*
|
||||
* @deprecated Use {@link EntityPersister#getCacheAccessStrategy()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
EntityDataAccess getEntityRegionAccess(NavigableRole rootEntityName);
|
||||
|
||||
/**
|
||||
* Find the cache data access strategy for the given entity's natural-id cache.
|
||||
* Will return {@code null} when the entity does not define a natural-id, or its
|
||||
* natural-id is not configured for caching.
|
||||
*
|
||||
* @param rootEntityName The NavigableRole representation of the root entity
|
||||
*
|
||||
* @apiNote It is only valid to call this method after {@link #prime} has
|
||||
* been performed
|
||||
*
|
||||
* @deprecated Use {@link EntityPersister#getNaturalIdCacheAccessStrategy()} ()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
NaturalIdDataAccess getNaturalIdRegionAccess(NavigableRole rootEntityName);
|
||||
|
||||
/**
|
||||
* Find the cache data access strategy for the given collection. Will
|
||||
* return {@code null} when the collection is not configured for caching.
|
||||
*
|
||||
* @apiNote It is only valid to call this method after {@link #prime} has
|
||||
* been performed
|
||||
*
|
||||
* @deprecated Use {@link EntityPersister#getNaturalIdCacheAccessStrategy()} ()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
CollectionDataAccess getCollectionRegionAccess(NavigableRole collectionRole);
|
||||
|
||||
|
||||
/**
|
||||
* Get {@code UpdateTimestampsCache} instance managed by the {@code SessionFactory}.
|
||||
*
|
||||
* @deprecated Use {@link #getTimestampsRegionAccess} instead
|
||||
*/
|
||||
@Deprecated
|
||||
default UpdateTimestampsCache getUpdateTimestampsCache() {
|
||||
return getTimestampsRegionAccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default {@code QueryCache}.
|
||||
*
|
||||
* @deprecated Use {@link #getDefaultQueryResultsRegionAccess} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default QueryCache getQueryCache() {
|
||||
return getDefaultQueryResultsRegionAccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default {@code QueryCache}.
|
||||
*
|
||||
* @deprecated Use {@link #getDefaultQueryResultsRegionAccess} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default QueryCache getDefaultQueryCache() {
|
||||
return getDefaultQueryResultsRegionAccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #getQueryResultsRegionAccess(String)} instead, but using unqualified name
|
||||
*/
|
||||
@Deprecated
|
||||
default QueryCache getQueryCache(String regionName) throws HibernateException {
|
||||
return getQueryResultsRegionAccess( unqualifyRegionName( regionName ) );
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Some new (default) support methods for the above deprecations
|
||||
// - themselves deprecated
|
||||
|
||||
/**
|
||||
* @deprecated (since 5.3) No replacement - added just to continue some backwards compatibility
|
||||
* in supporting the newly deprecated methods expecting a qualified (prefix +) region name
|
||||
*/
|
||||
@Deprecated
|
||||
default String unqualifyRegionName(String name) {
|
||||
if ( getSessionFactory().getSessionFactoryOptions().getCacheRegionPrefix() == null ) {
|
||||
return name;
|
||||
}
|
||||
|
||||
if ( !name.startsWith( getSessionFactory().getSessionFactoryOptions().getCacheRegionPrefix() ) ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Legacy methods for accessing cache information expect a qualified (prefix) region name - " +
|
||||
"but passed name [%s] was not qualified by the configured prefix [%s]",
|
||||
name,
|
||||
getSessionFactory().getSessionFactoryOptions().getCacheRegionPrefix()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return name.substring( getSessionFactory().getSessionFactoryOptions().getCacheRegionPrefix().length() + 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated No replacement - added just for support of the newly deprecated methods expecting a qualified region name
|
||||
*/
|
||||
@Deprecated
|
||||
default Region getRegionByLegacyName(String legacyName) {
|
||||
return getRegion( unqualifyRegionName( legacyName ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated No replacement - added just for support of the newly deprecated methods expecting a qualified region name
|
||||
*/
|
||||
@Deprecated
|
||||
Set<NaturalIdDataAccess> getNaturalIdAccessesInRegion(String legacyQualifiedRegionName);
|
||||
}
|
102
hibernate-core/src/main/java/org/hibernate/cache/spi/CacheTransactionSynchronization.java
vendored
Normal file
102
hibernate-core/src/main/java/org/hibernate/cache/spi/CacheTransactionSynchronization.java
vendored
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
/**
|
||||
* Defines a context object that a {@link RegionFactory} is asked to create
|
||||
* ({@link RegionFactory#createTransactionContext}}) when a Hibernate Session
|
||||
* is created. It's lifecycle is that of the Session. It receives
|
||||
* "transactional event callbacks" around joining and completing resource
|
||||
* transactions.
|
||||
*
|
||||
* This allows the cache impl to book-keep data related to current transaction,
|
||||
* such as and process it in unique ways. E.g. this allows an impl to perform
|
||||
* batch updates if Hibernate is configured to use JDBC-only transactions,
|
||||
* and therefore information cannot be retrieved from the JTA transaction
|
||||
* assigned to current thread.
|
||||
*
|
||||
* While transactional semantics might be fully implemented by the cache
|
||||
* provider, Hibernate may require different transactional semantics: In order
|
||||
* to prevent inconsistent reads, 2LC should not expose entities that are
|
||||
* modified in any concurrently executing transactions, and force DB load
|
||||
* instead. Native transactional implementation may provide looser semantics
|
||||
* and 2LC implementation has to adapt to these.
|
||||
*
|
||||
* @implNote Even though a JTA transaction may involve more than one Session
|
||||
* the CacheTransactionContext is specific to each Session since the distinction
|
||||
* is generally unimportant. However, a provider is free to attempt to scope
|
||||
* these CacheTransactionContext instances in such a way that they may be
|
||||
* associated with more than one Session at a time. This SPI is designed
|
||||
* to not require this of the caching impl, but it certainly allows the
|
||||
* provider to do it
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Radim Vansa
|
||||
*/
|
||||
public interface CacheTransactionSynchronization {
|
||||
/**
|
||||
* What is the start time of this context object?
|
||||
*
|
||||
* @apiNote If not currently joined to a transaction, the timestamp from
|
||||
* the last transaction is safe to use. If not ever/yet joined to a
|
||||
* transaction, a timestamp at the time the Session/CacheTransactionSynchronization
|
||||
* were created should be returned.
|
||||
*
|
||||
* @implSpec This "timestamp" need not be related to timestamp in the Java
|
||||
* Date/millisecond sense. It just needs to be an incrementing value.
|
||||
*/
|
||||
long getCurrentTransactionStartTimestamp();
|
||||
|
||||
/**
|
||||
* Callback that owning Session has become joined to a resource transaction.
|
||||
*
|
||||
* @apiNote Implementors can consider this the effective start of a
|
||||
* transaction.
|
||||
*/
|
||||
void transactionJoined();
|
||||
|
||||
/**
|
||||
* Callback that the underling resource transaction to which the owning
|
||||
* Session was joined is in the beginning stages of completing. Note that
|
||||
* this is only called for successful "begin completion" of the underlying
|
||||
* resource transaction (not rolling-back, marked-for-rollback, etc)
|
||||
*/
|
||||
void transactionCompleting();
|
||||
|
||||
/**
|
||||
* Callback that the underling resource transaction to which the owning
|
||||
* Session was joined is in the "completed" stage. This method is called
|
||||
* regardless of success or failure of the transaction - the outcome is
|
||||
* passed as a boolean.
|
||||
*
|
||||
* @param successful Was the resource transaction successful?
|
||||
*/
|
||||
void transactionCompleted(boolean successful);
|
||||
|
||||
/**
|
||||
* Currently not used. Here for future expansion
|
||||
*
|
||||
* @implNote Currently not used. JTA defines no standard means to
|
||||
* be notified when a transaction is suspended nor resumed. Such
|
||||
* a feature is proposed.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
default void transactionSuspended() {
|
||||
// nothing to do since it is currently not used/supported
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently not used. Here for future expansion
|
||||
*
|
||||
* @implNote Currently not used. JTA defines no standard means to
|
||||
* be notified when a transaction is suspended nor resumed
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
default void transactionResumed() {
|
||||
// nothing to do since it is currently not used/supported
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
|
||||
/**
|
||||
* Defines the contract for a cache region which will specifically be used to
|
||||
* store collection data.
|
||||
* <p/>
|
||||
* Impl note: Hibernate always deals with changes to collections which
|
||||
* (potentially) has its data in the L2 cache by removing that collection
|
||||
* data; in other words it never tries to update the cached state, thereby
|
||||
* allowing it to avoid a bunch of concurrency problems.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface CollectionRegion extends TransactionalDataRegion {
|
||||
|
||||
/**
|
||||
* Build an access strategy for the requested access type.
|
||||
*
|
||||
* @param accessType The type of access strategy to build; never null.
|
||||
* @return The appropriate strategy contract for accessing this region
|
||||
* for the requested type of access.
|
||||
* @throws org.hibernate.cache.CacheException Usually indicates mis-configuration.
|
||||
*/
|
||||
public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException;
|
||||
}
|
42
hibernate-core/src/main/java/org/hibernate/cache/spi/DirectAccessRegion.java
vendored
Normal file
42
hibernate-core/src/main/java/org/hibernate/cache/spi/DirectAccessRegion.java
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
/**
|
||||
* Specialized Region whose data is accessed directly - not requiring
|
||||
* key wrapping, e.g.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DirectAccessRegion extends Region {
|
||||
interface DataAccess {
|
||||
Object getFromCache(Object key);
|
||||
void addToCache(Object key, Object value);
|
||||
void removeFromCache(Object key);
|
||||
void clearCache();
|
||||
}
|
||||
|
||||
DataAccess getAccess();
|
||||
// Object get(Object key, SharedSessionContractImplementor session);
|
||||
// void put(Object key, Object value, SharedSessionContractImplementor session);
|
||||
//
|
||||
// /**
|
||||
// * Forcibly evict an item from the cache immediately without regard for transaction
|
||||
// * isolation. This behavior is exactly Hibernate legacy behavior, but it is also required
|
||||
// * by JPA - so we cannot remove it.
|
||||
// *
|
||||
// * @param key The key of the item to remove
|
||||
// */
|
||||
// void evict(Object key);
|
||||
//
|
||||
// /**
|
||||
// * Forcibly evict all items from the cache immediately without regard for transaction
|
||||
// * isolation. This behavior is exactly Hibernate legacy behavior, but it is also required
|
||||
// * by JPA - so we cannot remove it.
|
||||
// */
|
||||
// void evictAll();
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
|
||||
/**
|
||||
* A Region for cacheable domain data - entity, collection, natural-id
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DomainDataRegion extends Region {
|
||||
/**
|
||||
* Build a EntityRegionAccess instance representing access to entity data
|
||||
* stored in this cache region using the given AccessType.
|
||||
*
|
||||
* @param rootEntityRole The root entity name for the hierarchy whose data
|
||||
* we want to access
|
||||
*
|
||||
* @throws org.hibernate.cache.CacheException If the provider cannot provide the requested access
|
||||
*/
|
||||
EntityDataAccess getEntityDataAccess(NavigableRole rootEntityRole);
|
||||
|
||||
/**
|
||||
* Build a NaturalIdRegionAccess instance representing access to natural-id
|
||||
* data stored in this cache region using the given AccessType.
|
||||
*
|
||||
* @param rootEntityRole The NavigableRole of the root entity whose
|
||||
* natural-id data we want to access
|
||||
*
|
||||
* @throws org.hibernate.cache.CacheException If the provider cannot provide the requested access
|
||||
*/
|
||||
NaturalIdDataAccess getNaturalIdDataAccess(NavigableRole rootEntityRole);
|
||||
|
||||
/**
|
||||
* Build a CollectionRegionAccess instance representing access to collection
|
||||
* data stored in this cache region using the given AccessType.
|
||||
*
|
||||
* @param collectionRole The NavigableRole of the collection whose data
|
||||
* we want to access
|
||||
*
|
||||
* @throws org.hibernate.cache.CacheException If the provider cannot provide the requested access
|
||||
*/
|
||||
CollectionDataAccess getCollectionDataAccess(NavigableRole collectionRole);
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
|
||||
/**
|
||||
* Defines the contract for a cache region which will specifically be used to
|
||||
* store entity data.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface EntityRegion extends TransactionalDataRegion {
|
||||
|
||||
/**
|
||||
* Build an access strategy for the requested access type.
|
||||
*
|
||||
* @param accessType The type of access strategy to build; never null.
|
||||
* @return The appropriate strategy contract for accessing this region
|
||||
* for the requested type of access.
|
||||
* @throws org.hibernate.cache.CacheException Usually indicates mis-configuration.
|
||||
*/
|
||||
EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException;
|
||||
}
|
20
hibernate-core/src/main/java/org/hibernate/cache/spi/ExtendedStatisticsSupport.java
vendored
Normal file
20
hibernate-core/src/main/java/org/hibernate/cache/spi/ExtendedStatisticsSupport.java
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
/**
|
||||
* Optional Region contract defining support for extra statistic information
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ExtendedStatisticsSupport {
|
||||
long getElementCountInMemory();
|
||||
|
||||
long getElementCountOnDisk();
|
||||
|
||||
long getSizeInMemory();
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
||||
/**
|
||||
* Contract for general-purpose cache regions.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface GeneralDataRegion extends Region {
|
||||
|
||||
/**
|
||||
* Get an item from the cache.
|
||||
*
|
||||
* @param session
|
||||
* @param key The key of the item to be retrieved.
|
||||
*
|
||||
* @return the cached object or <tt>null</tt>
|
||||
*
|
||||
* @throws org.hibernate.cache.CacheException Indicates a problem accessing the item or region.
|
||||
*/
|
||||
Object get(SharedSessionContractImplementor session, Object key) throws CacheException;
|
||||
|
||||
/**
|
||||
* Put an item into the cache.
|
||||
*
|
||||
* @param session
|
||||
* @param key The key under which to cache the item.
|
||||
* @param value The item to cache.
|
||||
*
|
||||
* @throws CacheException Indicates a problem accessing the region.
|
||||
*/
|
||||
void put(SharedSessionContractImplementor session, Object key, Object value) throws CacheException;
|
||||
|
||||
/**
|
||||
* Evict an item from the cache immediately (without regard for transaction
|
||||
* isolation).
|
||||
*
|
||||
* @param key The key of the item to remove
|
||||
* @throws CacheException Indicates a problem accessing the item or region.
|
||||
*/
|
||||
void evict(Object key) throws CacheException;
|
||||
|
||||
/**
|
||||
* Evict all contents of this particular cache region (without regard for transaction
|
||||
* isolation).
|
||||
*
|
||||
* @throws CacheException Indicates problem accessing the region.
|
||||
*/
|
||||
void evictAll() throws CacheException;
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
|
||||
/**
|
||||
* Defines the contract for a cache region which will specifically be used to
|
||||
* store naturalId data.
|
||||
*
|
||||
* @author Eric Dalquist
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface NaturalIdRegion extends TransactionalDataRegion {
|
||||
|
||||
/**
|
||||
* Build an access strategy for the requested access type.
|
||||
*
|
||||
* @param accessType The type of access strategy to build; never null.
|
||||
* @return The appropriate strategy contract for accessing this region
|
||||
* for the requested type of access.
|
||||
* @throws org.hibernate.cache.CacheException Usually indicates mis-configuration.
|
||||
*/
|
||||
public NaturalIdRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException;
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Contract for sources of optimistically lockable data sent to the second level
|
||||
* cache.
|
||||
* <p/>
|
||||
* Note currently {@link org.hibernate.persister.entity.EntityPersister}s are
|
||||
* the only viable source.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface OptimisticCacheSource {
|
||||
/**
|
||||
* Is the data to be cached considered versioned?
|
||||
* <p/>
|
||||
* If true, it is illegal for {@link #getVersionComparator} to return
|
||||
* null.
|
||||
*
|
||||
* @return True if the data is versioned; false otherwise.
|
||||
*/
|
||||
public boolean isVersioned();
|
||||
|
||||
/**
|
||||
* Get the comparator used to compare two different version values.
|
||||
* <p/>
|
||||
* May return null <b>if</b> {@link #isVersioned()} returns false.
|
||||
* @return Comparator used to compare two different version values.
|
||||
*/
|
||||
public Comparator getVersionComparator();
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
|
@ -10,26 +10,25 @@ import java.io.Serializable;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Defines the contract for caches capable of storing query results. These
|
||||
* caches should only concern themselves with storing the matching result ids.
|
||||
* The transactional semantics are necessarily less strict than the semantics
|
||||
* of an item cache.
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @deprecated Use {@link QueryResultRegionAccess} instead -
|
||||
* {@link CacheImplementor#getQueryResultsRegionAccess} rather than
|
||||
* {@link CacheImplementor#getQueryCache}
|
||||
*/
|
||||
@Deprecated
|
||||
public interface QueryCache {
|
||||
/**
|
||||
* Clear items from the query cache.
|
||||
*
|
||||
* @throws CacheException Indicates a problem delegating to the underlying cache.
|
||||
*/
|
||||
void clear() throws CacheException;
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Put a result into the query cache.
|
||||
|
@ -41,15 +40,13 @@ public interface QueryCache {
|
|||
* @param session The originating session
|
||||
*
|
||||
* @return Whether the put actually happened.
|
||||
*
|
||||
* @throws HibernateException Indicates a problem delegating to the underlying cache.
|
||||
*/
|
||||
boolean put(
|
||||
QueryKey key,
|
||||
Type[] returnTypes,
|
||||
List result,
|
||||
boolean isNaturalKeyLookup,
|
||||
SharedSessionContractImplementor session) throws HibernateException;
|
||||
SharedSessionContractImplementor session);
|
||||
|
||||
/**
|
||||
* Get results from the cache.
|
||||
|
@ -61,15 +58,13 @@ public interface QueryCache {
|
|||
* @param session The originating session
|
||||
*
|
||||
* @return The cached results; may be null.
|
||||
*
|
||||
* @throws HibernateException Indicates a problem delegating to the underlying cache.
|
||||
*/
|
||||
List get(
|
||||
QueryKey key,
|
||||
Type[] returnTypes,
|
||||
boolean isNaturalKeyLookup,
|
||||
Set<Serializable> spaces,
|
||||
SharedSessionContractImplementor session) throws HibernateException;
|
||||
SharedSessionContractImplementor session);
|
||||
|
||||
/**
|
||||
* Destroy the cache.
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import org.hibernate.engine.spi.CacheImplementor;
|
||||
|
||||
/**
|
||||
* Defines a factory for query cache instances. These factories are responsible for
|
||||
* creating individual QueryCache instances.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface QueryCacheFactory {
|
||||
/**
|
||||
* Builds a named query cache.
|
||||
*
|
||||
* @param region The cache region
|
||||
* @param cacheManager The CacheImplementor reference.
|
||||
*
|
||||
* @return The cache.
|
||||
*/
|
||||
QueryCache buildQueryCache(QueryResultsRegion region, CacheImplementor cacheManager);
|
||||
}
|
121
hibernate-core/src/main/java/org/hibernate/cache/spi/QueryResultRegionAccess.java
vendored
Normal file
121
hibernate-core/src/main/java/org/hibernate/cache/spi/QueryResultRegionAccess.java
vendored
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Defines the responsibility for managing query result data caching
|
||||
* in regards to a specific region.
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface QueryResultRegionAccess extends QueryCache {
|
||||
/**
|
||||
* The underlying cache region being used.
|
||||
*/
|
||||
@Override
|
||||
QueryResultsRegion getRegion();
|
||||
|
||||
/**
|
||||
* Clear items from the query cache.
|
||||
*
|
||||
* @throws CacheException Indicates a problem delegating to the underlying cache.
|
||||
*/
|
||||
@Override
|
||||
default void clear() throws CacheException {
|
||||
getRegion().getAccess().clearCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a result into the query cache.
|
||||
*
|
||||
* @param key The cache key
|
||||
* @param result The results to cache
|
||||
* @param session The originating session
|
||||
*
|
||||
* @return Whether the put actually happened.
|
||||
*
|
||||
* @throws HibernateException Indicates a problem delegating to the underlying cache.
|
||||
*/
|
||||
boolean put(
|
||||
QueryKey key,
|
||||
List result,
|
||||
Type[] returnTypes,
|
||||
SharedSessionContractImplementor session) throws HibernateException;
|
||||
|
||||
/**
|
||||
* Get results from the cache.
|
||||
*
|
||||
* @param key The cache key
|
||||
* @param spaces The query spaces (used in invalidation plus validation checks)
|
||||
* @param session The originating session
|
||||
*
|
||||
* @return The cached results; may be null.
|
||||
*
|
||||
* @throws HibernateException Indicates a problem delegating to the underlying cache.
|
||||
*/
|
||||
List get(
|
||||
QueryKey key,
|
||||
Set<Serializable> spaces,
|
||||
Type[] returnTypes,
|
||||
SharedSessionContractImplementor session) throws HibernateException;
|
||||
|
||||
/**
|
||||
* Get results from the cache.
|
||||
*
|
||||
* @param key The cache key
|
||||
* @param spaces The query spaces (used in invalidation plus validation checks)
|
||||
* @param session The originating session
|
||||
*
|
||||
* @return The cached results; may be null.
|
||||
*
|
||||
* @throws HibernateException Indicates a problem delegating to the underlying cache.
|
||||
*/
|
||||
List get(
|
||||
QueryKey key,
|
||||
String[] spaces,
|
||||
Type[] returnTypes,
|
||||
SharedSessionContractImplementor session) throws HibernateException;
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Deprecations
|
||||
|
||||
@Override
|
||||
default boolean put(
|
||||
QueryKey key,
|
||||
Type[] returnTypes,
|
||||
List result,
|
||||
boolean isNaturalKeyLookup,
|
||||
SharedSessionContractImplementor session) {
|
||||
return put( key, result, returnTypes, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
default List get(
|
||||
QueryKey key,
|
||||
Type[] returnTypes,
|
||||
boolean isNaturalKeyLookup,
|
||||
Set<Serializable> spaces,
|
||||
SharedSessionContractImplementor session) {
|
||||
return get( key, spaces, returnTypes, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
default void destroy() {
|
||||
// nothing to do.. the region itself gets destroyed
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
|
@ -12,5 +12,9 @@ package org.hibernate.cache.spi;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface QueryResultsRegion extends GeneralDataRegion {
|
||||
public interface QueryResultsRegion extends DirectAccessRegion {
|
||||
@Override
|
||||
default void clear() {
|
||||
getAccess().clearCache();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class QuerySpacesHelper {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final QuerySpacesHelper INSTANCE = new QuerySpacesHelper();
|
||||
|
||||
private QuerySpacesHelper() {
|
||||
}
|
||||
|
||||
public String[] toStringArray(Set spacesSet) {
|
||||
return (String[]) spacesSet.toArray( new String[0] );
|
||||
}
|
||||
|
||||
public Set<String> toStringSet(String[] spacesArray) {
|
||||
final HashSet<String> set = new HashSet<>();
|
||||
Collections.addAll( set, spacesArray );
|
||||
return set;
|
||||
}
|
||||
|
||||
public Set<Serializable> toSerializableSet(String[] spacesArray) {
|
||||
final HashSet<Serializable> set = new HashSet<>();
|
||||
Collections.addAll( set, spacesArray );
|
||||
return set;
|
||||
}
|
||||
}
|
|
@ -1,13 +1,11 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
|
||||
/**
|
||||
|
@ -24,6 +22,13 @@ public interface Region {
|
|||
*/
|
||||
String getName();
|
||||
|
||||
RegionFactory getRegionFactory();
|
||||
|
||||
/**
|
||||
* Clear all data cached in the region
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* The "end state" contract of the region's lifecycle. Called
|
||||
* during {@link org.hibernate.SessionFactory#close()} to give
|
||||
|
@ -32,68 +37,4 @@ public interface Region {
|
|||
* @throws org.hibernate.cache.CacheException Indicates problem shutting down
|
||||
*/
|
||||
void destroy() throws CacheException;
|
||||
|
||||
/**
|
||||
* Determine whether this region contains data for the given key.
|
||||
* <p/>
|
||||
* The semantic here is whether the cache contains data visible for the
|
||||
* current call context. This should be viewed as a "best effort", meaning
|
||||
* blocking should be avoid if possible.
|
||||
*
|
||||
* @param key The cache key
|
||||
*
|
||||
* @return True if the underlying cache contains corresponding data; false
|
||||
* otherwise.
|
||||
*/
|
||||
boolean contains(Object key);
|
||||
|
||||
/**
|
||||
* The number of bytes is this cache region currently consuming in memory.
|
||||
*
|
||||
* @return The number of bytes consumed by this region; -1 if unknown or
|
||||
* unsupported.
|
||||
*/
|
||||
long getSizeInMemory();
|
||||
|
||||
/**
|
||||
* The count of entries currently contained in the regions in-memory store.
|
||||
*
|
||||
* @return The count of entries in memory; -1 if unknown or unsupported.
|
||||
*/
|
||||
long getElementCountInMemory();
|
||||
|
||||
/**
|
||||
* The count of entries currently contained in the regions disk store.
|
||||
*
|
||||
* @return The count of entries on disk; -1 if unknown or unsupported.
|
||||
*/
|
||||
long getElementCountOnDisk();
|
||||
|
||||
/**
|
||||
* Get the contents of this region as a map.
|
||||
* <p/>
|
||||
* Implementors which do not support this notion
|
||||
* should simply return an empty map.
|
||||
*
|
||||
* @return The content map.
|
||||
*/
|
||||
Map toMap();
|
||||
|
||||
/**
|
||||
* Get the next timestamp according to the underlying cache implementor.
|
||||
*
|
||||
* @todo Document the usages of this method so providers know exactly what is expected.
|
||||
*
|
||||
* @return The next timestamp
|
||||
*/
|
||||
long nextTimestamp();
|
||||
|
||||
/**
|
||||
* Get a timeout value.
|
||||
*
|
||||
* @todo Again, document the usages of this method so providers know exactly what is expected.
|
||||
*
|
||||
* @return The time out value
|
||||
*/
|
||||
int getTimeout();
|
||||
}
|
||||
|
|
|
@ -1,18 +1,22 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.cfg.spi.DomainDataRegionBuildingContext;
|
||||
import org.hibernate.cache.cfg.spi.DomainDataRegionConfig;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.service.Service;
|
||||
import org.hibernate.service.spi.Stoppable;
|
||||
|
||||
/**
|
||||
* Contract for building second level cache regions.
|
||||
|
@ -22,32 +26,14 @@ import org.hibernate.service.Service;
|
|||
* <li>MyRegionFactoryImpl()</li>
|
||||
* </ul>
|
||||
* Use the first when we need to read config properties prior to
|
||||
* {@link #start(SessionFactoryOptions, Properties)} being called.
|
||||
* {@link #start} being called.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface RegionFactory extends Service {
|
||||
|
||||
public interface RegionFactory extends Service, Stoppable {
|
||||
/**
|
||||
* Lifecycle callback to perform any necessary initialization of the
|
||||
* underlying cache implementation(s). Called exactly once during the
|
||||
* construction of a {@link org.hibernate.internal.SessionFactoryImpl}.
|
||||
*
|
||||
* @param settings The settings in effect.
|
||||
* @param properties The defined cfg properties
|
||||
*
|
||||
* @throws org.hibernate.cache.CacheException Indicates problems starting the L2 cache impl;
|
||||
* considered as a sign to stop {@link org.hibernate.SessionFactory}
|
||||
* building.
|
||||
*
|
||||
* @deprecated (since 5.2) use the form accepting map instead.
|
||||
*/
|
||||
@Deprecated
|
||||
void start(SessionFactoryOptions settings, Properties properties) throws CacheException;
|
||||
|
||||
/**
|
||||
* Lifecycle callback to perform any necessary initialization of the
|
||||
* underlying cache implementation(s). Called exactly once during the
|
||||
* underlying cache provider. Called exactly once during the
|
||||
* construction of a {@link org.hibernate.internal.SessionFactoryImpl}.
|
||||
*
|
||||
* @param settings The settings in effect.
|
||||
|
@ -57,18 +43,7 @@ public interface RegionFactory extends Service {
|
|||
* considered as a sign to stop {@link org.hibernate.SessionFactory}
|
||||
* building.
|
||||
*/
|
||||
default void start(SessionFactoryOptions settings, Map<String, Object> configValues) throws CacheException {
|
||||
final Properties properties = new Properties();
|
||||
properties.putAll( configValues );
|
||||
start( settings, properties );
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifecycle callback to perform any necessary cleanup of the underlying
|
||||
* cache implementation(s). Called exactly once during
|
||||
* {@link org.hibernate.SessionFactory#close}.
|
||||
*/
|
||||
void stop();
|
||||
void start(SessionFactoryOptions settings, Map configValues) throws CacheException;
|
||||
|
||||
/**
|
||||
* By default should we perform "minimal puts" when using this second
|
||||
|
@ -80,185 +55,43 @@ public interface RegionFactory extends Service {
|
|||
boolean isMinimalPutsEnabledByDefault();
|
||||
|
||||
/**
|
||||
* Get the default access type for {@link EntityRegion entity} and
|
||||
* {@link CollectionRegion collection} regions.
|
||||
*
|
||||
* @return This factory's default access type.
|
||||
* Get the default access type for any "user model" data
|
||||
*/
|
||||
AccessType getDefaultAccessType();
|
||||
|
||||
CacheTransactionSynchronization createTransactionContext(SharedSessionContractImplementor session);
|
||||
|
||||
/**
|
||||
* Generate a timestamp.
|
||||
* <p/>
|
||||
* This is generally used for cache content locking/unlocking purposes
|
||||
* depending upon the access-strategy being used.
|
||||
* Generate a timestamp. This value is generally used for purpose of
|
||||
* locking/unlocking cache content depending upon the access-strategy being
|
||||
* used. The intended consumer of this method is the Session to manage
|
||||
* its {@link SharedSessionContractImplementor#getTransactionStartTimestamp} value.
|
||||
*
|
||||
* @return The generated timestamp.
|
||||
* It is also expected that this be the value used for this's RegionFactory's
|
||||
* CacheTransactionContext
|
||||
*
|
||||
* @apiNote This "timestamp" need not be related to timestamp in the Java Date/millisecond
|
||||
* sense. It just needs to be an incrementing value
|
||||
*/
|
||||
long nextTimestamp();
|
||||
|
||||
/**
|
||||
* Build a cache region specialized for storing entity data.
|
||||
*
|
||||
* @param regionName The name of the region.
|
||||
* @param properties Configuration properties.
|
||||
* @param metadata Information regarding the type of data to be cached
|
||||
*
|
||||
* @return The built region
|
||||
*
|
||||
* @throws CacheException Indicates problems building the region.
|
||||
*
|
||||
* @deprecated (since 5.2) use the form taking Map instead
|
||||
*/
|
||||
@Deprecated
|
||||
EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata)
|
||||
throws CacheException;
|
||||
|
||||
/**
|
||||
* Build a cache region specialized for storing entity data.
|
||||
*
|
||||
* @param regionName The name of the region.
|
||||
* @param configValues Available config values.
|
||||
* @param metadata Information regarding the type of data to be cached
|
||||
*
|
||||
* @return The built region
|
||||
*
|
||||
* @throws CacheException Indicates problems building the region.
|
||||
*/
|
||||
default EntityRegion buildEntityRegion(String regionName, Map<String,Object> configValues, CacheDataDescription metadata)
|
||||
throws CacheException {
|
||||
final Properties properties = new Properties();
|
||||
properties.putAll( configValues );
|
||||
return buildEntityRegion( regionName, properties, metadata );
|
||||
default long getTimeout() {
|
||||
// most existing providers defined this as 60 seconds.
|
||||
return 60000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a cache region specialized for storing NaturalId to Primary Key mappings.
|
||||
* Create a named Region for holding domain model data
|
||||
*
|
||||
* @param regionName The name of the region.
|
||||
* @param properties Configuration properties.
|
||||
* @param metadata Information regarding the type of data to be cached
|
||||
*
|
||||
* @return The built region
|
||||
*
|
||||
* @throws CacheException Indicates problems building the region.
|
||||
*
|
||||
* @deprecated (since 5.2) use the form accepting a Map instead
|
||||
* @param regionConfig The user requested caching configuration for this Region
|
||||
* @param buildingContext Access to delegates useful in building the Region
|
||||
*/
|
||||
@Deprecated
|
||||
NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata)
|
||||
throws CacheException;
|
||||
DomainDataRegion buildDomainDataRegion(
|
||||
DomainDataRegionConfig regionConfig,
|
||||
DomainDataRegionBuildingContext buildingContext);
|
||||
|
||||
/**
|
||||
* Build a cache region specialized for storing NaturalId to Primary Key mappings.
|
||||
*
|
||||
* @param regionName The name of the region.
|
||||
* @param configValues Available config values.
|
||||
* @param metadata Information regarding the type of data to be cached
|
||||
*
|
||||
* @return The built region
|
||||
*
|
||||
* @throws CacheException Indicates problems building the region.
|
||||
*/
|
||||
default NaturalIdRegion buildNaturalIdRegion(String regionName, Map<String,Object> configValues, CacheDataDescription metadata)
|
||||
throws CacheException {
|
||||
final Properties properties = new Properties();
|
||||
properties.putAll( configValues );
|
||||
return buildNaturalIdRegion( regionName, properties, metadata );
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a cache region specialized for storing collection data.
|
||||
*
|
||||
* @param regionName The name of the region.
|
||||
* @param properties Configuration properties.
|
||||
* @param metadata Information regarding the type of data to be cached
|
||||
*
|
||||
* @return The built region
|
||||
*
|
||||
* @throws CacheException Indicates problems building the region.
|
||||
*/
|
||||
CollectionRegion buildCollectionRegion(String regionName, Properties properties, CacheDataDescription metadata)
|
||||
throws CacheException;
|
||||
|
||||
/**
|
||||
* Build a cache region specialized for storing collection data.
|
||||
*
|
||||
* @param regionName The name of the region.
|
||||
* @param configValues Available config values.
|
||||
* @param metadata Information regarding the type of data to be cached
|
||||
*
|
||||
* @return The built region
|
||||
*
|
||||
* @throws CacheException Indicates problems building the region.
|
||||
*/
|
||||
default CollectionRegion buildCollectionRegion(String regionName, Map<String,Object> configValues, CacheDataDescription metadata)
|
||||
throws CacheException {
|
||||
final Properties properties = new Properties();
|
||||
properties.putAll( configValues );
|
||||
return buildCollectionRegion( regionName, properties, metadata );
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a cache region specialized for storing query results.
|
||||
*
|
||||
* @param regionName The name of the region.
|
||||
* @param properties Configuration properties.
|
||||
*
|
||||
* @return The built region
|
||||
*
|
||||
* @throws CacheException Indicates problems building the region.
|
||||
*
|
||||
* @deprecated (since 5.2) use the form taking Map instead
|
||||
*/
|
||||
@Deprecated
|
||||
QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException;
|
||||
|
||||
/**
|
||||
* Build a cache region specialized for storing query results.
|
||||
*
|
||||
* @param qualifyRegionName The qualified name of the region.
|
||||
* @param configValues Available config values.
|
||||
*
|
||||
* @return The built region
|
||||
*
|
||||
* @throws CacheException Indicates problems building the region.
|
||||
*/
|
||||
default QueryResultsRegion buildQueryResultsRegion(String qualifyRegionName, Map<String,Object> configValues) {
|
||||
final Properties properties = new Properties();
|
||||
properties.putAll( configValues );
|
||||
return buildQueryResultsRegion( qualifyRegionName, properties );
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a cache region specialized for storing update-timestamps data.
|
||||
*
|
||||
* @param regionName The name of the region.
|
||||
* @param properties Configuration properties.
|
||||
*
|
||||
* @return The built region
|
||||
*
|
||||
* @throws CacheException Indicates problems building the region.
|
||||
*
|
||||
* @deprecated (since 5.2) use the form taking Map
|
||||
*/
|
||||
@Deprecated
|
||||
TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException;
|
||||
|
||||
/**
|
||||
* Build a cache region specialized for storing update-timestamps data.
|
||||
*
|
||||
* @param regionName The name of the region.
|
||||
* @param configValues The available config values.
|
||||
*
|
||||
* @return The built region
|
||||
*
|
||||
* @throws CacheException Indicates problems building the region.
|
||||
*/
|
||||
default TimestampsRegion buildTimestampsRegion(String regionName, Map<String,Object> configValues) throws CacheException {
|
||||
final Properties properties = new Properties();
|
||||
properties.putAll( configValues );
|
||||
return buildTimestampsRegion( regionName, properties );
|
||||
}
|
||||
QueryResultsRegion buildQueryResultsRegion(String regionName, SessionFactoryImplementor sessionFactory);
|
||||
|
||||
TimestampsRegion buildTimestampsRegion(String regionName, SessionFactoryImplementor sessionFactory);
|
||||
}
|
||||
|
|
32
hibernate-core/src/main/java/org/hibernate/cache/spi/SecondLevelCacheLogger.java
vendored
Normal file
32
hibernate-core/src/main/java/org/hibernate/cache/spi/SecondLevelCacheLogger.java
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import org.jboss.logging.BasicLogger;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.logging.annotations.MessageLogger;
|
||||
import org.jboss.logging.annotations.ValidIdRange;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@MessageLogger( projectCode = "HHH" )
|
||||
@ValidIdRange( min = 90001001, max = 90002000 )
|
||||
public interface SecondLevelCacheLogger extends BasicLogger {
|
||||
SecondLevelCacheLogger INSTANCE = Logger.getMessageLogger(
|
||||
SecondLevelCacheLogger.class,
|
||||
"org.hibernate.orm.cache"
|
||||
);
|
||||
|
||||
enum RegionAccessType {
|
||||
ENTITY,
|
||||
NATURAL_ID,
|
||||
COLLECTION,
|
||||
QUERY_RESULTS,
|
||||
TIMESTAMPS
|
||||
}
|
||||
}
|
|
@ -1,16 +1,17 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
/**
|
||||
* Defines the contract for a cache region which will specifically be used to
|
||||
* store entity "update timestamps".
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface TimestampsRegion extends GeneralDataRegion {
|
||||
public interface TimestampsRegion extends DirectAccessRegion {
|
||||
@Override
|
||||
default void clear() {
|
||||
getAccess().clearCache();
|
||||
}
|
||||
}
|
||||
|
|
105
hibernate-core/src/main/java/org/hibernate/cache/spi/TimestampsRegionAccess.java
vendored
Normal file
105
hibernate-core/src/main/java/org/hibernate/cache/spi/TimestampsRegionAccess.java
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
||||
/**
|
||||
* Wrapper for a {@link TimestampsRegion} adding handling of stale results
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface TimestampsRegionAccess extends UpdateTimestampsCache {
|
||||
TimestampsRegion getRegion();
|
||||
|
||||
/**
|
||||
* Perform pre-invalidation of the passed spaces (table names)
|
||||
* using the passed region for storing update-timestamps
|
||||
*/
|
||||
void preInvalidate(
|
||||
String[] spaces,
|
||||
SharedSessionContractImplementor session);
|
||||
|
||||
/**
|
||||
* Perform invalidation of the passed spaces (table names)
|
||||
* using the passed region for storing update-timestamps
|
||||
*/
|
||||
void invalidate(
|
||||
String[] spaces,
|
||||
SharedSessionContractImplementor session);
|
||||
|
||||
/**
|
||||
* Perform an up-to-date check for the given set of query spaces as
|
||||
* part of verifying the validity of cached query results.
|
||||
*
|
||||
* @param spaces The spaces to check
|
||||
* @param timestamp The timestamp from the transaction when the query results were cached.
|
||||
* @param session The session whether this check originated.
|
||||
*
|
||||
* @return Whether all those spaces are up-to-date
|
||||
*/
|
||||
boolean isUpToDate(
|
||||
String[] spaces,
|
||||
Long timestamp,
|
||||
SharedSessionContractImplementor session);
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Deprecations
|
||||
|
||||
|
||||
@Override
|
||||
default void preInvalidate(Serializable[] spaces, SharedSessionContractImplementor session) {
|
||||
final String[] spaceStrings = new String[ spaces.length ];
|
||||
// todo - does this copy work?
|
||||
System.arraycopy( spaces, 0, spaceStrings, 0, spaces.length );
|
||||
preInvalidate( spaceStrings, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
default void invalidate(Serializable[] spaces, SharedSessionContractImplementor session) {
|
||||
final String[] spaceStrings = new String[ spaces.length ];
|
||||
// todo - does this copy work?
|
||||
System.arraycopy( spaces, 0, spaceStrings, 0, spaces.length );
|
||||
invalidate( spaceStrings, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean isUpToDate(
|
||||
Set<Serializable> spaces,
|
||||
Long timestamp,
|
||||
SharedSessionContractImplementor session) {
|
||||
final String[] spaceArray = new String[ spaces.size() ];
|
||||
|
||||
spaces.forEach(
|
||||
new Consumer<Serializable>() {
|
||||
int position = 0;
|
||||
@Override
|
||||
public void accept(Serializable serializable) {
|
||||
spaceArray[position++] = (String) serializable;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return isUpToDate( spaceArray, timestamp, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
default void clear() throws CacheException {
|
||||
getRegion().getAccess().clearCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
default void destroy() {
|
||||
// nothing to do - the region itself is destroyed
|
||||
}
|
||||
}
|
17
hibernate-core/src/main/java/org/hibernate/cache/spi/TimestampsRegionAccessFactory.java
vendored
Normal file
17
hibernate-core/src/main/java/org/hibernate/cache/spi/TimestampsRegionAccessFactory.java
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
/**
|
||||
* Responsible for building the TimestampsRegionAccessFactory to use for
|
||||
* managing query results in regards to staleness
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface TimestampsRegionAccessFactory {
|
||||
TimestampsRegionAccess buildTimestampsRegionAccess(CacheImplementor cacheManager, TimestampsRegion timestampsRegion);
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
/**
|
||||
* Marker interface for identifying {@link org.hibernate.Cache} implementations which are aware of JTA transactions
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface TransactionAwareCache {
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
/**
|
||||
* Defines contract for regions which hold transactionally-managed data.
|
||||
* <p/>
|
||||
* The data is not transactionally managed within the region; merely it is
|
||||
* transactionally-managed in relation to its association with a particular
|
||||
* {@link org.hibernate.Session}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface TransactionalDataRegion extends Region {
|
||||
/**
|
||||
* Is the underlying cache implementation aware of (and "participating in")
|
||||
* ongoing JTA transactions?
|
||||
* <p/>
|
||||
* Regions which report that they are transaction-aware are considered
|
||||
* "synchronous", in that we assume we can immediately (i.e. synchronously)
|
||||
* write the changes to the cache and that the cache will properly manage
|
||||
* application of the written changes within the bounds of ongoing JTA
|
||||
* transactions. Conversely, regions reporting false are considered
|
||||
* "asynchronous", where it is assumed that changes must be manually
|
||||
* delayed by Hibernate until we are certain that the current transaction
|
||||
* is successful (i.e. maintaining READ_COMMITTED isolation).
|
||||
*
|
||||
* @return True if transaction aware; false otherwise.
|
||||
*/
|
||||
public boolean isTransactionAware();
|
||||
|
||||
/**
|
||||
* Get the description of the type of data to be stored here, which would have been given to the RegionFactory
|
||||
* when creating this region
|
||||
*
|
||||
* @return The data descriptor.
|
||||
*/
|
||||
public CacheDataDescription getCacheDataDescription();
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
|
@ -10,11 +10,7 @@ import java.io.Serializable;
|
|||
import java.util.Set;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Tracks the timestamps of the most recent updates to particular tables. It is
|
||||
|
@ -25,102 +21,38 @@ import org.jboss.logging.Logger;
|
|||
*
|
||||
* @author Gavin King
|
||||
* @author Mikheil Kapanadze
|
||||
*
|
||||
* @deprecated Use {@link TimestampsRegionAccess} instead
|
||||
*/
|
||||
public class UpdateTimestampsCache {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, UpdateTimestampsCache.class.getName() );
|
||||
private static final boolean DEBUG_ENABLED = LOG.isDebugEnabled();
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Deprecated
|
||||
public interface UpdateTimestampsCache {
|
||||
/**
|
||||
* The region name of the update-timestamps cache.
|
||||
*/
|
||||
public static final String REGION_NAME = UpdateTimestampsCache.class.getName();
|
||||
|
||||
private final SessionFactoryImplementor factory;
|
||||
private final TimestampsRegion region;
|
||||
|
||||
/**
|
||||
* Constructs an UpdateTimestampsCache.
|
||||
* Get the underlying cache region where data is stored..
|
||||
*
|
||||
* @param sessionFactory The SessionFactory
|
||||
* @param region The underlying second level cache region to use.
|
||||
* @return The underlying region.
|
||||
*/
|
||||
public UpdateTimestampsCache(SessionFactoryImplementor sessionFactory, TimestampsRegion region) {
|
||||
LOG.startingUpdateTimestampsCache( region.getName() );
|
||||
this.factory = sessionFactory;
|
||||
this.region = region;
|
||||
}
|
||||
TimestampsRegion getRegion();
|
||||
|
||||
/**
|
||||
* Perform pre-invalidation.
|
||||
*
|
||||
*
|
||||
* @param spaces The spaces to pre-invalidate
|
||||
*
|
||||
* @param session
|
||||
* @throws CacheException Indicated problem delegating to underlying region.
|
||||
*/
|
||||
public void preInvalidate(Serializable[] spaces, SharedSessionContractImplementor session) throws CacheException {
|
||||
final boolean stats = factory != null && factory.getStatistics().isStatisticsEnabled();
|
||||
|
||||
final Long ts = region.nextTimestamp() + region.getTimeout();
|
||||
|
||||
for ( Serializable space : spaces ) {
|
||||
if ( DEBUG_ENABLED ) {
|
||||
LOG.debugf( "Pre-invalidating space [%s], timestamp: %s", space, ts );
|
||||
}
|
||||
|
||||
try {
|
||||
session.getEventListenerManager().cachePutStart();
|
||||
|
||||
//put() has nowait semantics, is this really appropriate?
|
||||
//note that it needs to be async replication, never local or sync
|
||||
region.put( session, space, ts );
|
||||
}
|
||||
finally {
|
||||
session.getEventListenerManager().cachePutEnd();
|
||||
}
|
||||
|
||||
if ( stats ) {
|
||||
factory.getStatistics().updateTimestampsCachePut();
|
||||
}
|
||||
}
|
||||
}
|
||||
void preInvalidate(Serializable[] spaces, SharedSessionContractImplementor session) throws CacheException;
|
||||
|
||||
/**
|
||||
* Perform invalidation.
|
||||
*
|
||||
*
|
||||
* @param spaces The spaces to invalidate.
|
||||
*
|
||||
* @param session
|
||||
*
|
||||
* @throws CacheException Indicated problem delegating to underlying region.
|
||||
*/
|
||||
public void invalidate(Serializable[] spaces, SharedSessionContractImplementor session) throws CacheException {
|
||||
final boolean stats = factory != null && factory.getStatistics().isStatisticsEnabled();
|
||||
|
||||
final Long ts = region.nextTimestamp();
|
||||
|
||||
for (Serializable space : spaces) {
|
||||
if ( DEBUG_ENABLED ) {
|
||||
LOG.debugf( "Invalidating space [%s], timestamp: %s", space, ts );
|
||||
}
|
||||
|
||||
try {
|
||||
session.getEventListenerManager().cachePutStart();
|
||||
|
||||
//put() has nowait semantics, is this really appropriate?
|
||||
//note that it needs to be async replication, never local or sync
|
||||
region.put( session, space, ts );
|
||||
}
|
||||
finally {
|
||||
session.getEventListenerManager().cachePutEnd();
|
||||
}
|
||||
|
||||
if ( stats ) {
|
||||
factory.getStatistics().updateTimestampsCachePut();
|
||||
}
|
||||
}
|
||||
}
|
||||
void invalidate(Serializable[] spaces, SharedSessionContractImplementor session) throws CacheException;
|
||||
|
||||
/**
|
||||
* Perform an up-to-date check for the given set of query spaces.
|
||||
|
@ -129,91 +61,21 @@ public class UpdateTimestampsCache {
|
|||
* @param spaces The spaces to check
|
||||
* @param timestamp The timestamp against which to check.
|
||||
*
|
||||
* @param session
|
||||
* @return Whether all those spaces are up-to-date
|
||||
*
|
||||
* @throws CacheException Indicated problem delegating to underlying region.
|
||||
*/
|
||||
public boolean isUpToDate(Set<Serializable> spaces, Long timestamp, SharedSessionContractImplementor session) throws CacheException {
|
||||
final boolean stats = factory != null && factory.getStatistics().isStatisticsEnabled();
|
||||
|
||||
for ( Serializable space : spaces ) {
|
||||
final Long lastUpdate = getLastUpdateTimestampForSpace( space, session );
|
||||
if ( lastUpdate == null ) {
|
||||
if ( stats ) {
|
||||
factory.getStatistics().updateTimestampsCacheMiss();
|
||||
}
|
||||
//the last update timestamp was lost from the cache
|
||||
//(or there were no updates since startup!)
|
||||
//updateTimestamps.put( space, new Long( updateTimestamps.nextTimestamp() ) );
|
||||
//result = false; // safer
|
||||
}
|
||||
else {
|
||||
if ( DEBUG_ENABLED ) {
|
||||
LOG.debugf(
|
||||
"[%s] last update timestamp: %s",
|
||||
space,
|
||||
lastUpdate + ", result set timestamp: " + timestamp
|
||||
);
|
||||
}
|
||||
if ( stats ) {
|
||||
factory.getStatistics().updateTimestampsCacheHit();
|
||||
}
|
||||
if ( lastUpdate >= timestamp ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private Long getLastUpdateTimestampForSpace(Serializable space, SharedSessionContractImplementor session) {
|
||||
Long ts = null;
|
||||
try {
|
||||
session.getEventListenerManager().cacheGetStart();
|
||||
ts = (Long) region.get( session, space );
|
||||
}
|
||||
finally {
|
||||
session.getEventListenerManager().cacheGetEnd( ts != null );
|
||||
}
|
||||
return ts;
|
||||
}
|
||||
boolean isUpToDate(Set<Serializable> spaces, Long timestamp, SharedSessionContractImplementor session) throws CacheException;
|
||||
|
||||
/**
|
||||
* Clear the update-timestamps data.
|
||||
*
|
||||
* @throws CacheException Indicates problem delegating call to underlying region.
|
||||
*/
|
||||
public void clear() throws CacheException {
|
||||
region.evictAll();
|
||||
}
|
||||
void clear() throws CacheException;
|
||||
|
||||
/**
|
||||
* Destroys the cache.
|
||||
*
|
||||
* @throws CacheException Indicates problem delegating call to underlying region.
|
||||
*/
|
||||
public void destroy() {
|
||||
try {
|
||||
region.destroy();
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.unableToDestroyUpdateTimestampsCache( region.getName(), e.getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the underlying cache region where data is stored..
|
||||
*
|
||||
* @return The underlying region.
|
||||
*/
|
||||
public TimestampsRegion getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UpdateTimestampsCache";
|
||||
}
|
||||
|
||||
void destroy();
|
||||
}
|
||||
|
|
189
hibernate-core/src/main/java/org/hibernate/cache/spi/access/CachedDomainDataAccess.java
vendored
Normal file
189
hibernate-core/src/main/java/org/hibernate/cache/spi/access/CachedDomainDataAccess.java
vendored
Normal file
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi.access;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Cache;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.DomainDataRegion;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
||||
/**
|
||||
* Base contract for accessing the underlying cached data for a particular
|
||||
* Navigable of the user's domain model in a transactionally ACID manner.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public interface CachedDomainDataAccess {
|
||||
DomainDataRegion getRegion();
|
||||
|
||||
/**
|
||||
* Determine whether this region contains data for the given key.
|
||||
* <p/>
|
||||
* The semantic here is whether the cache contains data visible for the
|
||||
* current call context. This should be viewed as a "best effort", meaning
|
||||
* blocking should be avoid if possible.
|
||||
*
|
||||
* @param key The cache key
|
||||
*
|
||||
* @return True if the underlying cache contains corresponding data; false
|
||||
* otherwise.
|
||||
*/
|
||||
boolean contains(Object key);
|
||||
|
||||
/**
|
||||
* Attempt to retrieve an object from the cache. Mainly used in attempting
|
||||
* to resolve entities/collections from the second level cache.
|
||||
*
|
||||
* @param session Current session.
|
||||
* @param key The key of the item to be retrieved.
|
||||
*
|
||||
* @return the cached data or {@code null}
|
||||
*
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
Object get(SharedSessionContractImplementor session, Object key);
|
||||
|
||||
/**
|
||||
* Attempt to cache an object, afterQuery loading from the database.
|
||||
*
|
||||
* @param session Current session.
|
||||
* @param key The item key
|
||||
* @param value The item
|
||||
* @param version the item version number
|
||||
*
|
||||
* @return {@code true} if the object was successfully cached
|
||||
*
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
boolean putFromLoad(
|
||||
SharedSessionContractImplementor session,
|
||||
Object key,
|
||||
Object value,
|
||||
Object version);
|
||||
|
||||
/**
|
||||
* Attempt to cache an object, afterQuery loading from the database, explicitly
|
||||
* specifying the minimalPut behavior.
|
||||
*
|
||||
* @param session Current session.
|
||||
* @param key The item key
|
||||
* @param value The item
|
||||
* @param version the item version number
|
||||
* @param minimalPutOverride Explicit minimalPut flag
|
||||
*
|
||||
* @return {@code true} if the object was successfully cached
|
||||
*
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
boolean putFromLoad(
|
||||
SharedSessionContractImplementor session,
|
||||
Object key,
|
||||
Object value,
|
||||
Object version,
|
||||
boolean minimalPutOverride);
|
||||
|
||||
/**
|
||||
* We are going to attempt to update/delete the keyed object. This
|
||||
* method is used by "asynchronous" concurrency strategies.
|
||||
* <p/>
|
||||
* The returned object must be passed back to {@link #unlockItem}, to release the
|
||||
* lock. Concurrency strategies which do not support client-visible
|
||||
* locks may silently return null.
|
||||
*
|
||||
* @param session Current session.
|
||||
* @param key The key of the item to lock
|
||||
* @param version The item's current version value
|
||||
*
|
||||
* @return A representation of our lock on the item; or {@code null}.
|
||||
*
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version);
|
||||
|
||||
/**
|
||||
* Lock the entire region
|
||||
*
|
||||
* @return A representation of our lock on the item; or {@code null}.
|
||||
*
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
SoftLock lockRegion();
|
||||
|
||||
/**
|
||||
* Called when we have finished the attempted update/delete (which may or
|
||||
* may not have been successful), after transaction completion. This method
|
||||
* is used by "asynchronous" concurrency strategies.
|
||||
*
|
||||
* @param session Current session.
|
||||
* @param key The item key
|
||||
* @param lock The lock previously obtained from {@link #lockItem}
|
||||
*
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock);
|
||||
|
||||
/**
|
||||
* Called after we have finished the attempted invalidation of the entire
|
||||
* region
|
||||
*
|
||||
* @param lock The lock previously obtained from {@link #lockRegion}
|
||||
*
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
void unlockRegion(SoftLock lock);
|
||||
|
||||
/**
|
||||
* Called afterQuery an item has become stale (beforeQuery the transaction completes).
|
||||
* This method is used by "synchronous" concurrency strategies.
|
||||
*
|
||||
* @param session Current session.
|
||||
* @param key The key of the item to remove
|
||||
*
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
void remove(SharedSessionContractImplementor session, Object key);
|
||||
|
||||
/**
|
||||
* Called to evict data from the entire region
|
||||
*
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
void removeAll();
|
||||
|
||||
/**
|
||||
* Forcibly evict an item from the cache immediately without regard for transaction
|
||||
* isolation and/or locking. This behavior is exactly Hibernate legacy behavior, but
|
||||
* it is also required by JPA - so we cannot remove it.
|
||||
* <p/>
|
||||
* Used from JPA's {@link javax.persistence.Cache#evict(Class, Object)}, as well as the
|
||||
* Hibernate extension {@link org.hibernate.Cache#evictEntityData(Class, Serializable)}
|
||||
* and {@link org.hibernate.Cache#evictEntityData(String, Serializable)}
|
||||
*
|
||||
* @param key The key of the item to remove
|
||||
*
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
void evict(Object key);
|
||||
|
||||
/**
|
||||
* Forcibly evict all items from the cache immediately without regard for transaction
|
||||
* isolation. This behavior is exactly Hibernate legacy behavior, but it is also required
|
||||
* by JPA - so we cannot remove it.
|
||||
* <p/>
|
||||
* Used from our JPA impl of {@link Cache#evictAll()} as well as the Hibernate
|
||||
* extensions {@link org.hibernate.Cache#evictEntityData(Class)},
|
||||
* {@link org.hibernate.Cache#evictEntityData(String)} and
|
||||
* {@link org.hibernate.Cache#evictEntityData()}
|
||||
*
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
void evictAll();
|
||||
}
|
|
@ -1,12 +1,11 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi.access;
|
||||
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
|
||||
|
@ -17,38 +16,37 @@ import org.hibernate.persister.collection.CollectionPersister;
|
|||
* {@link #lockItem} -> {@link #remove} -> {@link #unlockItem}
|
||||
* <p/>
|
||||
* There is another usage pattern that is used to invalidate entries
|
||||
* after performing "bulk" HQL/SQL operations:
|
||||
* afterQuery performing "bulk" HQL/SQL operations:
|
||||
* {@link #lockRegion} -> {@link #removeAll} -> {@link #unlockRegion}
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface CollectionRegionAccessStrategy extends RegionAccessStrategy {
|
||||
|
||||
public interface CollectionDataAccess extends CachedDomainDataAccess {
|
||||
/**
|
||||
* To create instances of CollectionCacheKey for this region, Hibernate will invoke this method
|
||||
* exclusively so that generated implementations can generate optimised keys.
|
||||
* @param id the primary identifier of the Collection
|
||||
* @param persister the persister for the type for which a key is being generated
|
||||
* @param collectionDescriptor the descriptor of the collection for which a key is being generated
|
||||
* @param factory a reference to the current SessionFactory
|
||||
* @param tenantIdentifier the tenant id, or null if multi-tenancy is not being used.
|
||||
*
|
||||
* @return a key which can be used to identify this collection on this same region
|
||||
*/
|
||||
public Object generateCacheKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier);
|
||||
Object generateCacheKey(
|
||||
Object id,
|
||||
CollectionPersister collectionDescriptor,
|
||||
SessionFactoryImplementor factory,
|
||||
String tenantIdentifier);
|
||||
|
||||
/**
|
||||
* Performs reverse operation to {@link #generateCacheKey(Object, CollectionPersister, SessionFactoryImplementor, String)}
|
||||
* Performs reverse operation to {@link #generateCacheKey}
|
||||
*
|
||||
* @param cacheKey key previously returned from {@link #generateCacheKey(Object, CollectionPersister, SessionFactoryImplementor, String)}
|
||||
* @return original key passed to {@link #generateCacheKey(Object, CollectionPersister, SessionFactoryImplementor, String)}
|
||||
* @param cacheKey key previously returned from {@link #generateCacheKey}
|
||||
*
|
||||
* @return original key passed to {@link #generateCacheKey}
|
||||
*/
|
||||
public Object getCacheKeyId(Object cacheKey);
|
||||
Object getCacheKeyId(Object cacheKey);
|
||||
|
||||
/**
|
||||
* Get the wrapped collection cache region
|
||||
*
|
||||
* @return The underlying region
|
||||
*/
|
||||
public CollectionRegion getRegion();
|
||||
|
||||
}
|
|
@ -1,13 +1,12 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi.access;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
@ -18,7 +17,7 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
* <li><b>INSERTS</b> : {@link #insert} -> {@link #afterInsert}</li>
|
||||
* <li><b>UPDATES</b> : {@link #lockItem} -> {@link #update} -> {@link #afterUpdate}</li>
|
||||
* <li><b>DELETES</b> : {@link #lockItem} -> {@link #remove} -> {@link #unlockItem}</li>
|
||||
* <li><b>LOADS</b> : {@link @putFromLoad}</li>
|
||||
* <li><b>LOADS</b> : {@link #putFromLoad}</li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* There is another usage pattern that is used to invalidate entries
|
||||
|
@ -28,40 +27,34 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface EntityRegionAccessStrategy extends RegionAccessStrategy {
|
||||
|
||||
public interface EntityDataAccess extends CachedDomainDataAccess {
|
||||
/**
|
||||
* To create instances of keys for this region, Hibernate will invoke this method
|
||||
* exclusively so that generated implementations can generate optimised keys.
|
||||
* @param id the primary identifier of the entity
|
||||
* @param persister the persister for the type for which a key is being generated
|
||||
* @param rootEntityDescriptor Hierarchy for which a key is being generated
|
||||
* @param factory a reference to the current SessionFactory
|
||||
* @param tenantIdentifier the tenant id, or null if multi-tenancy is not being used.
|
||||
* @return a key which can be used to identify this entity on this same region
|
||||
*
|
||||
* todo (6.0) : the access for an entity knows the entity hierarchy and the factory. why pass them in?
|
||||
*/
|
||||
Object generateCacheKey(
|
||||
Object id,
|
||||
EntityPersister persister,
|
||||
EntityPersister rootEntityDescriptor,
|
||||
SessionFactoryImplementor factory,
|
||||
String tenantIdentifier);
|
||||
|
||||
/**
|
||||
* Performs reverse operation to {@link #generateCacheKey(Object, EntityPersister, SessionFactoryImplementor, String)}
|
||||
* Performs reverse operation to {@link #generateCacheKey}
|
||||
*
|
||||
* @param cacheKey key previously returned from {@link #generateCacheKey(Object, EntityPersister, SessionFactoryImplementor, String)}
|
||||
* @return original id passed to {@link #generateCacheKey(Object, EntityPersister, SessionFactoryImplementor, String)}
|
||||
* @param cacheKey key previously returned from {@link #generateCacheKey}
|
||||
* @return original id passed to {@link #generateCacheKey}
|
||||
*/
|
||||
Object getCacheKeyId(Object cacheKey);
|
||||
|
||||
/**
|
||||
* Get the wrapped entity cache region
|
||||
*
|
||||
* @return The underlying region
|
||||
*/
|
||||
EntityRegion getRegion();
|
||||
|
||||
/**
|
||||
* Called after an item has been inserted (before the transaction completes),
|
||||
* Called afterQuery an item has been inserted (beforeQuery the transaction completes),
|
||||
* instead of calling evict().
|
||||
* This method is used by "synchronous" concurrency strategies.
|
||||
*
|
||||
|
@ -70,12 +63,12 @@ public interface EntityRegionAccessStrategy extends RegionAccessStrategy {
|
|||
* @param value The item
|
||||
* @param version The item's version value
|
||||
* @return Were the contents of the cache actual changed by this operation?
|
||||
* @throws CacheException Propagated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
boolean insert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException;
|
||||
boolean insert(SharedSessionContractImplementor session, Object key, Object value, Object version);
|
||||
|
||||
/**
|
||||
* Called after an item has been inserted (after the transaction completes),
|
||||
* Called afterQuery an item has been inserted (afterQuery the transaction completes),
|
||||
* instead of calling release().
|
||||
* This method is used by "asynchronous" concurrency strategies.
|
||||
*
|
||||
|
@ -84,12 +77,12 @@ public interface EntityRegionAccessStrategy extends RegionAccessStrategy {
|
|||
* @param value The item
|
||||
* @param version The item's version value
|
||||
* @return Were the contents of the cache actual changed by this operation?
|
||||
* @throws CacheException Propagated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException;
|
||||
boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value, Object version);
|
||||
|
||||
/**
|
||||
* Called after an item has been updated (before the transaction completes),
|
||||
* Called afterQuery an item has been updated (beforeQuery the transaction completes),
|
||||
* instead of calling evict(). This method is used by "synchronous" concurrency
|
||||
* strategies.
|
||||
*
|
||||
|
@ -100,12 +93,17 @@ public interface EntityRegionAccessStrategy extends RegionAccessStrategy {
|
|||
* @param currentVersion The item's current version value
|
||||
* @param previousVersion The item's previous version value
|
||||
* @return Were the contents of the cache actual changed by this operation?
|
||||
* @throws CacheException Propagated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
boolean update(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion) throws CacheException;
|
||||
boolean update(
|
||||
SharedSessionContractImplementor session,
|
||||
Object key,
|
||||
Object value,
|
||||
Object currentVersion,
|
||||
Object previousVersion);
|
||||
|
||||
/**
|
||||
* Called after an item has been updated (after the transaction completes),
|
||||
* Called afterQuery an item has been updated (afterQuery the transaction completes),
|
||||
* instead of calling release(). This method is used by "asynchronous"
|
||||
* concurrency strategies.
|
||||
*
|
||||
|
@ -116,7 +114,7 @@ public interface EntityRegionAccessStrategy extends RegionAccessStrategy {
|
|||
* @param previousVersion The item's previous version value
|
||||
* @param lock The lock previously obtained from {@link #lockItem}
|
||||
* @return Were the contents of the cache actual changed by this operation?
|
||||
* @throws CacheException Propagated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
boolean afterUpdate(
|
||||
SharedSessionContractImplementor session,
|
||||
|
@ -124,5 +122,5 @@ public interface EntityRegionAccessStrategy extends RegionAccessStrategy {
|
|||
Object value,
|
||||
Object currentVersion,
|
||||
Object previousVersion,
|
||||
SoftLock lock) throws CacheException;
|
||||
SoftLock lock);
|
||||
}
|
|
@ -1,13 +1,12 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi.access;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.NaturalIdRegion;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
|
@ -23,90 +22,90 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
* old entry as well as
|
||||
* <p/>
|
||||
* There is another usage pattern that is used to invalidate entries
|
||||
* after performing "bulk" HQL/SQL operations:
|
||||
* afterQuery performing "bulk" HQL/SQL operations:
|
||||
* {@link #lockRegion} -> {@link #removeAll} -> {@link #unlockRegion}
|
||||
* <p/>
|
||||
* IMPORTANT : NaturalIds are not versioned so {@code null} will always be passed to the version parameter to:<ul>
|
||||
* <li>{@link RegionAccessStrategy#putFromLoad(SharedSessionContractImplementor, Object, Object, long, Object)}</li>
|
||||
* <li>{@link RegionAccessStrategy#putFromLoad(SharedSessionContractImplementor, Object, Object, long, Object, boolean)}</li>
|
||||
* <li>{@link RegionAccessStrategy#lockItem(SharedSessionContractImplementor, Object, Object)}</li>
|
||||
* <li>{@link CachedDomainDataAccess#putFromLoad(SharedSessionContractImplementor, Object, Object, Object)}</li>
|
||||
* <li>{@link CachedDomainDataAccess#putFromLoad(SharedSessionContractImplementor, Object, Object, Object, boolean)}</li>
|
||||
* <li>{@link CachedDomainDataAccess#lockItem(SharedSessionContractImplementor, Object, Object)}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
* @author Eric Dalquist
|
||||
*/
|
||||
public interface NaturalIdRegionAccessStrategy extends RegionAccessStrategy {
|
||||
public interface NaturalIdDataAccess extends CachedDomainDataAccess {
|
||||
|
||||
/**
|
||||
* To create instances of NaturalIdCacheKey for this region, Hibernate will invoke this method
|
||||
* exclusively so that generated implementations can generate optimised keys.
|
||||
* @param naturalIdValues the sequence of values which unequivocally identifies a cached element on this region
|
||||
* @param persister the persister of the element being cached
|
||||
* @param session
|
||||
* @param rootEntityDescriptor the persister of the element being cached
|
||||
*
|
||||
* @return a key which can be used to identify this an element unequivocally on this same region
|
||||
*/
|
||||
Object generateCacheKey(
|
||||
Object[] naturalIdValues,
|
||||
EntityPersister persister,
|
||||
EntityPersister rootEntityDescriptor,
|
||||
SharedSessionContractImplementor session);
|
||||
|
||||
/**
|
||||
* Performs reverse operation to {@link #generateCacheKey(Object[], EntityPersister, SharedSessionContractImplementor)}, returning
|
||||
* Performs reverse operation to {@link #generateCacheKey}, returning
|
||||
* the original naturalIdValues.
|
||||
* @param cacheKey key returned from {@link #generateCacheKey(Object[], EntityPersister, SharedSessionContractImplementor)}
|
||||
* @param cacheKey key returned from {@link #generateCacheKey}
|
||||
*
|
||||
* @return the sequence of values which unequivocally identifies a cached element on this region
|
||||
*/
|
||||
Object[] getNaturalIdValues(Object cacheKey);
|
||||
|
||||
/**
|
||||
* Get the wrapped naturalId cache region
|
||||
*
|
||||
* @return The underlying region
|
||||
*/
|
||||
NaturalIdRegion getRegion();
|
||||
|
||||
/**
|
||||
* Called after an item has been inserted (before the transaction completes),
|
||||
* Called afterQuery an item has been inserted (beforeQuery the transaction completes),
|
||||
* instead of calling evict().
|
||||
* This method is used by "synchronous" concurrency strategies.
|
||||
*
|
||||
* @param session Current session
|
||||
* @param key The item key
|
||||
* @param value The item
|
||||
*
|
||||
* @return Were the contents of the cache actual changed by this operation?
|
||||
* @throws CacheException Propagated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
boolean insert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException;
|
||||
boolean insert(SharedSessionContractImplementor session, Object key, Object value);
|
||||
|
||||
/**
|
||||
* Called after an item has been inserted (after the transaction completes),
|
||||
* Called afterQuery an item has been inserted (afterQuery the transaction completes),
|
||||
* instead of calling release().
|
||||
* This method is used by "asynchronous" concurrency strategies.
|
||||
*
|
||||
* @param session Current session
|
||||
* @param key The item key
|
||||
* @param value The item
|
||||
*
|
||||
* @return Were the contents of the cache actual changed by this operation?
|
||||
* @throws CacheException Propagated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException;
|
||||
boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value);
|
||||
|
||||
/**
|
||||
* Called after an item has been updated (before the transaction completes),
|
||||
* Called afterQuery an item has been updated (beforeQuery the transaction completes),
|
||||
* instead of calling evict(). This method is used by "synchronous" concurrency
|
||||
* strategies.
|
||||
*
|
||||
* @param session Current session
|
||||
* @param key The item key
|
||||
* @param value The item
|
||||
*
|
||||
* @return Were the contents of the cache actual changed by this operation?
|
||||
* @throws CacheException Propagated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
boolean update(SharedSessionContractImplementor session, Object key, Object value) throws CacheException;
|
||||
boolean update(SharedSessionContractImplementor session, Object key, Object value);
|
||||
|
||||
/**
|
||||
* Called after an item has been updated (after the transaction completes),
|
||||
* Called afterQuery an item has been updated (afterQuery the transaction completes),
|
||||
* instead of calling release(). This method is used by "asynchronous"
|
||||
* concurrency strategies.
|
||||
*
|
||||
|
@ -114,8 +113,10 @@ public interface NaturalIdRegionAccessStrategy extends RegionAccessStrategy {
|
|||
* @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}
|
||||
*
|
||||
* @throws CacheException Propagated from underlying cache provider
|
||||
*/
|
||||
boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, SoftLock lock) throws CacheException;
|
||||
boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, SoftLock lock);
|
||||
}
|
|
@ -1,149 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.cache.spi.access;
|
||||
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
||||
/**
|
||||
* Base access strategy for all regions.
|
||||
*
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public interface RegionAccessStrategy {
|
||||
|
||||
/**
|
||||
* Attempt to retrieve an object from the cache. Mainly used in attempting
|
||||
* to resolve entities/collections from the second level cache.
|
||||
*
|
||||
* @param session Current session.
|
||||
* @param key The key of the item to be retrieved.
|
||||
* @param txTimestamp a timestamp prior to the transaction start time
|
||||
* @return the cached object or <tt>null</tt>
|
||||
* @throws org.hibernate.cache.CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
Object get(SharedSessionContractImplementor session, Object key, long txTimestamp) throws CacheException;
|
||||
|
||||
/**
|
||||
* Attempt to cache an object, after loading from the database.
|
||||
*
|
||||
* @param session Current session.
|
||||
* @param key The item key
|
||||
* @param value The item
|
||||
* @param txTimestamp a timestamp prior to the transaction start time
|
||||
* @param version the item version number
|
||||
* @return <tt>true</tt> if the object was successfully cached
|
||||
* @throws org.hibernate.cache.CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
boolean putFromLoad(
|
||||
SharedSessionContractImplementor session,
|
||||
Object key,
|
||||
Object value,
|
||||
long txTimestamp,
|
||||
Object version) throws CacheException;
|
||||
|
||||
/**
|
||||
* Attempt to cache an object, after loading from the database, explicitly
|
||||
* specifying the minimalPut behavior.
|
||||
*
|
||||
* @param session Current session.
|
||||
* @param key The item key
|
||||
* @param value The item
|
||||
* @param txTimestamp a timestamp prior to the transaction start time
|
||||
* @param version the item version number
|
||||
* @param minimalPutOverride Explicit minimalPut flag
|
||||
* @return <tt>true</tt> if the object was successfully cached
|
||||
* @throws org.hibernate.cache.CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
boolean putFromLoad(
|
||||
SharedSessionContractImplementor session,
|
||||
Object key,
|
||||
Object value,
|
||||
long txTimestamp,
|
||||
Object version,
|
||||
boolean minimalPutOverride) throws CacheException;
|
||||
|
||||
/**
|
||||
* We are going to attempt to update/delete the keyed object. This
|
||||
* method is used by "asynchronous" concurrency strategies.
|
||||
* <p/>
|
||||
* The returned object must be passed back to {@link #unlockItem}, to release the
|
||||
* lock. Concurrency strategies which do not support client-visible
|
||||
* locks may silently return null.
|
||||
*
|
||||
* @param session Current session.
|
||||
* @param key The key of the item to lock
|
||||
* @param version The item's current version value
|
||||
* @return A representation of our lock on the item; or null.
|
||||
* @throws org.hibernate.cache.CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws CacheException;
|
||||
|
||||
/**
|
||||
* Lock the entire region
|
||||
*
|
||||
* @return A representation of our lock on the item; or null.
|
||||
* @throws org.hibernate.cache.CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
SoftLock lockRegion() throws CacheException;
|
||||
|
||||
/**
|
||||
* Called when we have finished the attempted update/delete (which may or
|
||||
* may not have been successful), after transaction completion. This method
|
||||
* is used by "asynchronous" concurrency strategies.
|
||||
*
|
||||
* @param session Current session.
|
||||
* @param key The item key
|
||||
* @param lock The lock previously obtained from {@link #lockItem}
|
||||
* @throws org.hibernate.cache.CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException;
|
||||
|
||||
/**
|
||||
* Called after we have finished the attempted invalidation of the entire
|
||||
* region
|
||||
*
|
||||
* @param lock The lock previously obtained from {@link #lockRegion}
|
||||
* @throws org.hibernate.cache.CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
void unlockRegion(SoftLock lock) throws CacheException;
|
||||
|
||||
/**
|
||||
* Called after an item has become stale (before the transaction completes).
|
||||
* This method is used by "synchronous" concurrency strategies.
|
||||
*
|
||||
* @param session
|
||||
* @param key The key of the item to remove
|
||||
* @throws org.hibernate.cache.CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
void remove(SharedSessionContractImplementor session, Object key) throws CacheException;
|
||||
|
||||
/**
|
||||
* Called to evict data from the entire region
|
||||
*
|
||||
* @throws org.hibernate.cache.CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
void removeAll() throws CacheException;
|
||||
|
||||
/**
|
||||
* Forcibly evict an item from the cache immediately without regard for transaction
|
||||
* isolation.
|
||||
*
|
||||
* @param key The key of the item to remove
|
||||
* @throws org.hibernate.cache.CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
void evict(Object key) throws CacheException;
|
||||
|
||||
/**
|
||||
* Forcibly evict all items from the cache immediately without regard for transaction
|
||||
* isolation.
|
||||
*
|
||||
* @throws org.hibernate.cache.CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
|
||||
*/
|
||||
void evictAll() throws CacheException;
|
||||
}
|
|
@ -1,13 +1,13 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi.access;
|
||||
|
||||
/**
|
||||
* Marker object for use by synchronous concurrency strategies
|
||||
* Memento object for use by synchronous concurrency strategies
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.cache.spi.access;
|
||||
|
||||
|
@ -10,6 +10,8 @@ import org.hibernate.HibernateException;
|
|||
|
||||
/**
|
||||
* Indicates that an unknown AccessType external name was encountered
|
||||
* or that an AccessType was requested that the underlying cache provider
|
||||
* does not support.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
<html>
|
||||
<body>
|
||||
<p>
|
||||
Defines contracts for transactional and concurrent access to cached
|
||||
{@link org.hibernate.cache.spi.access.EntityRegionAccessStrategy entity} and
|
||||
{@link org.hibernate.cache.spi.access.CollectionRegionAccessStrategy collection} data. Transactions pass in a
|
||||
Defines contracts for transactional and concurrent access to cached
|
||||
{@link org.hibernate.cache.spi.access.EntityDataAccess entity} and
|
||||
{@link org.hibernate.cache.spi.access.CollectionDataAccess collection} data. Transactions pass in a
|
||||
timestamp indicating transaction start time which is then used to protect against concurrent access (exactly how
|
||||
that occurs is based on the actual access-strategy impl used). Two different implementation patterns are provided
|
||||
for:
|
||||
<ul>
|
||||
<ul>
|
||||
<li>
|
||||
A transaction-aware cache implementation might be wrapped by a <i>synchronous</i> access strategy,
|
||||
where updates to the cache are written to the cache inside the transaction.
|
||||
|
|
|
@ -13,6 +13,7 @@ import javax.persistence.GeneratedValue;
|
|||
import org.hibernate.Transaction;
|
||||
import org.hibernate.boot.MetadataBuilder;
|
||||
import org.hibernate.boot.registry.classloading.internal.TcclLookupPrecedence;
|
||||
import org.hibernate.cache.spi.TimestampsRegionAccessFactory;
|
||||
import org.hibernate.internal.log.DeprecationLogger;
|
||||
import org.hibernate.jpa.JpaCompliance;
|
||||
import org.hibernate.query.internal.ParameterMetadataImpl;
|
||||
|
@ -1054,7 +1055,7 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings {
|
|||
String USE_QUERY_CACHE = "hibernate.cache.use_query_cache";
|
||||
|
||||
/**
|
||||
* The {@link org.hibernate.cache.spi.QueryCacheFactory} implementation class.
|
||||
* The {@link TimestampsRegionAccessFactory} implementation class.
|
||||
*/
|
||||
String QUERY_CACHE_FACTORY = "hibernate.cache.query_cache_factory";
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@ import org.hibernate.boot.Metadata;
|
|||
import org.hibernate.boot.SchemaAutoTooling;
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.cache.spi.QueryCacheFactory;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cache.spi.TimestampsRegionAccessFactory;
|
||||
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
|
||||
import org.hibernate.hql.spi.QueryTranslatorFactory;
|
||||
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
|
||||
|
@ -93,7 +93,7 @@ public final class Settings {
|
|||
|
||||
LOG.debugf( "Second-level cache: %s", enabledDisabled( sessionFactoryOptions.isSecondLevelCacheEnabled() ) );
|
||||
LOG.debugf( "Second-level query cache: %s", enabledDisabled( sessionFactoryOptions.isQueryCacheEnabled() ) );
|
||||
LOG.debugf( "Second-level query cache factory: %s", sessionFactoryOptions.getQueryCacheFactory() );
|
||||
LOG.debugf( "Second-level query cache factory: %s", sessionFactoryOptions.getTimestampsRegionAccessFactory() );
|
||||
LOG.debugf( "Second-level cache region prefix: %s", sessionFactoryOptions.getCacheRegionPrefix() );
|
||||
LOG.debugf( "Optimize second-level cache for minimal puts: %s", enabledDisabled( sessionFactoryOptions.isMinimalPutsEnabled() ) );
|
||||
LOG.debugf( "Structured second-level cache entries: %s", enabledDisabled( sessionFactoryOptions.isStructuredCacheEntriesEnabled() ) );
|
||||
|
@ -227,8 +227,8 @@ public final class Settings {
|
|||
return sessionFactoryOptions.isQueryCacheEnabled();
|
||||
}
|
||||
|
||||
public QueryCacheFactory getQueryCacheFactory() {
|
||||
return sessionFactoryOptions.getQueryCacheFactory();
|
||||
public TimestampsRegionAccessFactory getTimestampsRegionAccessFactory() {
|
||||
return sessionFactoryOptions.getTimestampsRegionAccessFactory();
|
||||
}
|
||||
|
||||
public String getCacheRegionPrefix() {
|
||||
|
|
|
@ -8,7 +8,7 @@ package org.hibernate.engine.internal;
|
|||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.cache.spi.access.RegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.CachedDomainDataAccess;
|
||||
import org.hibernate.engine.spi.SessionEventListenerManager;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
||||
|
@ -24,12 +24,12 @@ public final class CacheHelper {
|
|||
public static Serializable fromSharedCache(
|
||||
SharedSessionContractImplementor session,
|
||||
Object cacheKey,
|
||||
RegionAccessStrategy cacheAccessStrategy) {
|
||||
CachedDomainDataAccess cacheAccess) {
|
||||
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
|
||||
Serializable cachedValue = null;
|
||||
eventListenerManager.cacheGetStart();
|
||||
try {
|
||||
cachedValue = (Serializable) cacheAccessStrategy.get( session, cacheKey, session.getTimestamp() );
|
||||
cachedValue = (Serializable) cacheAccess.get( session, cacheKey );
|
||||
}
|
||||
finally {
|
||||
eventListenerManager.cacheGetEnd( cachedValue != null );
|
||||
|
|
|
@ -15,7 +15,7 @@ import java.util.Map;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
|
||||
import org.hibernate.engine.spi.PersistenceContext;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
|
@ -107,7 +107,7 @@ public class NaturalIdXrefDelegate {
|
|||
}
|
||||
|
||||
if ( persister.hasNaturalIdCache() ) {
|
||||
final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy = persister
|
||||
final NaturalIdDataAccess naturalIdCacheAccessStrategy = persister
|
||||
.getNaturalIdCacheAccessStrategy();
|
||||
final Object naturalIdCacheKey = naturalIdCacheAccessStrategy.generateCacheKey( naturalIdValues, persister, session() );
|
||||
naturalIdCacheAccessStrategy.evict( naturalIdCacheKey );
|
||||
|
@ -238,7 +238,7 @@ public class NaturalIdXrefDelegate {
|
|||
}
|
||||
|
||||
// Try resolution from second-level cache
|
||||
final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy = persister.getNaturalIdCacheAccessStrategy();
|
||||
final NaturalIdDataAccess naturalIdCacheAccessStrategy = persister.getNaturalIdCacheAccessStrategy();
|
||||
final Object naturalIdCacheKey = naturalIdCacheAccessStrategy.generateCacheKey( naturalIdValues, persister, session() );
|
||||
|
||||
pk = CacheHelper.fromSharedCache( session(), naturalIdCacheKey, naturalIdCacheAccessStrategy );
|
||||
|
@ -247,9 +247,7 @@ public class NaturalIdXrefDelegate {
|
|||
final SessionFactoryImplementor factory = session().getFactory();
|
||||
if ( pk != null ) {
|
||||
if ( factory.getStatistics().isStatisticsEnabled() ) {
|
||||
factory.getStatisticsImplementor().naturalIdCacheHit(
|
||||
naturalIdCacheAccessStrategy.getRegion().getName()
|
||||
);
|
||||
factory.getStatistics().naturalIdCacheHit( persister.getRootEntityName() );
|
||||
}
|
||||
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
|
@ -274,7 +272,7 @@ public class NaturalIdXrefDelegate {
|
|||
entityNaturalIdResolutionCache.naturalIdToPkMap.put( cachedNaturalId, pk );
|
||||
}
|
||||
else if ( factory.getStatistics().isStatisticsEnabled() ) {
|
||||
factory.getStatisticsImplementor().naturalIdCacheMiss( naturalIdCacheAccessStrategy.getRegion().getName() );
|
||||
factory.getStatistics().naturalIdCacheMiss( persister.getRootEntityName() );
|
||||
}
|
||||
|
||||
return pk;
|
||||
|
|
|
@ -32,7 +32,7 @@ import org.hibernate.PersistentObjectException;
|
|||
import org.hibernate.TransientObjectException;
|
||||
import org.hibernate.action.spi.AfterTransactionCompletionProcess;
|
||||
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.loading.internal.LoadContexts;
|
||||
|
@ -1783,7 +1783,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
Object[] naturalIdValues,
|
||||
Object[] previousNaturalIdValues,
|
||||
CachedNaturalIdValueSource source) {
|
||||
final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy = persister.getNaturalIdCacheAccessStrategy();
|
||||
final NaturalIdDataAccess naturalIdCacheAccessStrategy = persister.getNaturalIdCacheAccessStrategy();
|
||||
final Object naturalIdCacheKey = naturalIdCacheAccessStrategy.generateCacheKey( naturalIdValues, persister, session );
|
||||
|
||||
final SessionFactoryImplementor factory = session.getFactory();
|
||||
|
@ -1798,12 +1798,11 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
session,
|
||||
naturalIdCacheKey,
|
||||
id,
|
||||
session.getTimestamp(),
|
||||
null
|
||||
);
|
||||
|
||||
if ( put && factory.getStatistics().isStatisticsEnabled() ) {
|
||||
factory.getStatistics().naturalIdCachePut( naturalIdCacheAccessStrategy.getRegion().getName() );
|
||||
factory.getStatistics().naturalIdCachePut( persister.getRootEntityName() );
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -1811,7 +1810,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
case INSERT: {
|
||||
final boolean put = naturalIdCacheAccessStrategy.insert( session, naturalIdCacheKey, id );
|
||||
if ( put && factory.getStatistics().isStatisticsEnabled() ) {
|
||||
factory.getStatistics().naturalIdCachePut( naturalIdCacheAccessStrategy.getRegion().getName() );
|
||||
factory.getStatistics().naturalIdCachePut( persister.getRootEntityName() );
|
||||
}
|
||||
|
||||
( (EventSource) session ).getActionQueue().registerProcess(
|
||||
|
@ -1822,7 +1821,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
final boolean put = naturalIdCacheAccessStrategy.afterInsert( session, naturalIdCacheKey, id );
|
||||
|
||||
if ( put && factory.getStatistics().isStatisticsEnabled() ) {
|
||||
factory.getStatistics().naturalIdCachePut( naturalIdCacheAccessStrategy.getRegion().getName() );
|
||||
factory.getStatistics().naturalIdCachePut( persister.getRootEntityName() );
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1846,7 +1845,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
final SoftLock lock = naturalIdCacheAccessStrategy.lockItem( session, naturalIdCacheKey, null );
|
||||
final boolean put = naturalIdCacheAccessStrategy.update( session, naturalIdCacheKey, id );
|
||||
if ( put && factory.getStatistics().isStatisticsEnabled() ) {
|
||||
factory.getStatistics().naturalIdCachePut( naturalIdCacheAccessStrategy.getRegion().getName() );
|
||||
factory.getStatistics().naturalIdCachePut( persister.getRootEntityName() );
|
||||
}
|
||||
|
||||
( (EventSource) session ).getActionQueue().registerProcess(
|
||||
|
@ -1863,7 +1862,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
);
|
||||
|
||||
if ( put && factory.getStatistics().isStatisticsEnabled() ) {
|
||||
factory.getStatistics().naturalIdCachePut( naturalIdCacheAccessStrategy.getRegion().getName() );
|
||||
factory.getStatistics().naturalIdCachePut( persister.getRootEntityName() );
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1917,7 +1916,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
// 2) should prefer session-cached values if any (requires interaction from removeLocalNaturalIdCrossReference
|
||||
|
||||
persister = locateProperPersister( persister );
|
||||
final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy = persister.getNaturalIdCacheAccessStrategy();
|
||||
final NaturalIdDataAccess naturalIdCacheAccessStrategy = persister.getNaturalIdCacheAccessStrategy();
|
||||
final Object naturalIdCacheKey = naturalIdCacheAccessStrategy.generateCacheKey( naturalIdValues, persister, session );
|
||||
naturalIdCacheAccessStrategy.evict( naturalIdCacheKey );
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ import org.hibernate.CacheMode;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.cache.spi.entry.CacheEntry;
|
||||
import org.hibernate.engine.profile.Fetch;
|
||||
import org.hibernate.engine.profile.FetchProfile;
|
||||
|
@ -200,7 +200,7 @@ public final class TwoPhaseLoad {
|
|||
|
||||
final Object version = Versioning.getVersion( hydratedState, persister );
|
||||
final CacheEntry entry = persister.buildCacheEntry( entity, hydratedState, version, session );
|
||||
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
||||
final Object cacheKey = cache.generateCacheKey( id, persister, factory, session.getTenantIdentifier() );
|
||||
|
||||
// explicit handling of caching for rows just inserted and then somehow forced to be read
|
||||
|
@ -226,7 +226,6 @@ public final class TwoPhaseLoad {
|
|||
session,
|
||||
cacheKey,
|
||||
persister.getCacheEntryStructure().structure( entry ),
|
||||
session.getTimestamp(),
|
||||
version,
|
||||
useMinimalPuts( session, entityEntry )
|
||||
);
|
||||
|
|
|
@ -17,7 +17,7 @@ import java.util.Set;
|
|||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
||||
import org.hibernate.cache.spi.entry.CollectionCacheEntry;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.spi.CollectionEntry;
|
||||
|
@ -330,8 +330,8 @@ public class CollectionLoadContext {
|
|||
}
|
||||
|
||||
final CollectionCacheEntry entry = new CollectionCacheEntry( lce.getCollection(), persister );
|
||||
final CollectionRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||
final Object cacheKey = cache.generateCacheKey(
|
||||
final CollectionDataAccess cacheAccess = persister.getCacheAccessStrategy();
|
||||
final Object cacheKey = cacheAccess.generateCacheKey(
|
||||
lce.getKey(),
|
||||
persister,
|
||||
session.getFactory(),
|
||||
|
@ -353,11 +353,10 @@ public class CollectionLoadContext {
|
|||
if (isPutFromLoad) {
|
||||
try {
|
||||
session.getEventListenerManager().cachePutStart();
|
||||
final boolean put = cache.putFromLoad(
|
||||
final boolean put = cacheAccess.putFromLoad(
|
||||
session,
|
||||
cacheKey,
|
||||
persister.getCacheEntryStructure().structure( entry ),
|
||||
session.getTimestamp(),
|
||||
version,
|
||||
factory.getSessionFactoryOptions().isMinimalPutsEnabled() && session.getCacheMode()!= CacheMode.REFRESH
|
||||
);
|
||||
|
|
|
@ -397,7 +397,7 @@ public class ActionQueue {
|
|||
beforeTransactionProcesses.register( executable.getBeforeTransactionCompletionProcess() );
|
||||
}
|
||||
if ( session.getFactory().getSessionFactoryOptions().isQueryCacheEnabled() ) {
|
||||
invalidateSpaces( executable.getPropertySpaces() );
|
||||
invalidateSpaces( convertTimestampSpaces( executable.getPropertySpaces() ) );
|
||||
}
|
||||
if( executable.getAfterTransactionCompletionProcess() != null ) {
|
||||
if( afterTransactionProcesses == null ) {
|
||||
|
@ -407,6 +407,10 @@ public class ActionQueue {
|
|||
}
|
||||
}
|
||||
|
||||
private static String[] convertTimestampSpaces(Serializable[] spaces) {
|
||||
return (String[]) spaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are there unresolved entity insert actions that depend on non-nullable associations with a transient entity?
|
||||
*
|
||||
|
@ -620,8 +624,8 @@ public class ActionQueue {
|
|||
// Strictly speaking, only a subset of the list may have been processed if a RuntimeException occurs.
|
||||
// We still invalidate all spaces. I don't see this as a big deal - after all, RuntimeExceptions are
|
||||
// unexpected.
|
||||
Set<Serializable> propertySpaces = list.getQuerySpaces();
|
||||
invalidateSpaces( propertySpaces.toArray( new Serializable[propertySpaces.size()] ) );
|
||||
Set propertySpaces = list.getQuerySpaces();
|
||||
invalidateSpaces( convertTimestampSpaces( propertySpaces ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -629,6 +633,10 @@ public class ActionQueue {
|
|||
session.getJdbcCoordinator().executeBatch();
|
||||
}
|
||||
|
||||
private static String[] convertTimestampSpaces(Set spaces) {
|
||||
return (String[]) spaces.toArray( new String[ spaces.size() ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param executable The action to execute
|
||||
*/
|
||||
|
@ -646,7 +654,7 @@ public class ActionQueue {
|
|||
*
|
||||
* @param spaces The spaces to invalidate
|
||||
*/
|
||||
private void invalidateSpaces(Serializable... spaces) {
|
||||
private void invalidateSpaces(String... spaces) {
|
||||
if ( spaces != null && spaces.length > 0 ) {
|
||||
for ( Serializable s : spaces ) {
|
||||
if( afterTransactionProcesses == null ) {
|
||||
|
@ -655,7 +663,7 @@ public class ActionQueue {
|
|||
afterTransactionProcesses.addSpaceToInvalidate( (String) s );
|
||||
}
|
||||
// Performance win: If we are processing an ExecutableList, this will only be called once
|
||||
session.getFactory().getUpdateTimestampsCache().preInvalidate( spaces, session );
|
||||
session.getFactory().getCache().getTimestampsRegionAccess().preInvalidate( spaces, session );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -984,7 +992,7 @@ public class ActionQueue {
|
|||
}
|
||||
|
||||
if ( session.getFactory().getSessionFactoryOptions().isQueryCacheEnabled() ) {
|
||||
session.getFactory().getUpdateTimestampsCache().invalidate(
|
||||
session.getFactory().getCache().getTimestampsRegionAccess().invalidate(
|
||||
querySpacesToInvalidate.toArray( new String[querySpacesToInvalidate.size()] ),
|
||||
session
|
||||
);
|
||||
|
|
|
@ -14,8 +14,8 @@ import java.util.Map;
|
|||
import java.util.Map.Entry;
|
||||
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.internal.CacheHelper;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
|
@ -216,7 +216,7 @@ public class BatchFetchQueue {
|
|||
private boolean isCached(EntityKey entityKey, EntityPersister persister) {
|
||||
final SharedSessionContractImplementor session = context.getSession();
|
||||
if ( context.getSession().getCacheMode().isGetEnabled() && persister.canReadFromCache() ) {
|
||||
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
||||
final Object key = cache.generateCacheKey(
|
||||
entityKey.getIdentifier(),
|
||||
persister,
|
||||
|
@ -332,7 +332,7 @@ public class BatchFetchQueue {
|
|||
private boolean isCached(Serializable collectionKey, CollectionPersister persister) {
|
||||
SharedSessionContractImplementor session = context.getSession();
|
||||
if ( session.getCacheMode().isGetEnabled() && persister.hasCache() ) {
|
||||
CollectionRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||
CollectionDataAccess cache = persister.getCacheAccessStrategy();
|
||||
Object cacheKey = cache.generateCacheKey(
|
||||
collectionKey,
|
||||
persister,
|
||||
|
|
|
@ -1,128 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.engine.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.Cache;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cache.spi.QueryCache;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cache.spi.UpdateTimestampsCache;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.service.Service;
|
||||
|
||||
/**
|
||||
* Define internal contact of <tt>Cache API</tt>
|
||||
*
|
||||
* @author Strong Liu
|
||||
*/
|
||||
public interface CacheImplementor extends Service, Cache, Serializable {
|
||||
|
||||
/**
|
||||
* Close all cache regions.
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Get query cache by <tt>region name</tt> or create a new one if none exist.
|
||||
* <p/>
|
||||
* If the region name is null, then default query cache region will be returned.
|
||||
*
|
||||
* @param regionName Query cache region name.
|
||||
* @return The {@code QueryCache} associated with the region name, or default query cache if the region name is <tt>null</tt>.
|
||||
* @throws HibernateException {@code HibernateException} maybe thrown when the creation of new QueryCache instance.
|
||||
*/
|
||||
QueryCache getQueryCache(String regionName) throws HibernateException;
|
||||
|
||||
/**
|
||||
* Get the default {@code QueryCache}.
|
||||
*
|
||||
* @deprecated Use {@link #getDefaultQueryCache} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default QueryCache getQueryCache() {
|
||||
return getDefaultQueryCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default {@code QueryCache}.
|
||||
*/
|
||||
QueryCache getDefaultQueryCache();
|
||||
|
||||
/**
|
||||
* Get {@code UpdateTimestampsCache} instance managed by the {@code SessionFactory}.
|
||||
*/
|
||||
UpdateTimestampsCache getUpdateTimestampsCache();
|
||||
|
||||
/**
|
||||
* Clean up the default {@code QueryCache}.
|
||||
*
|
||||
* @throws HibernateException
|
||||
*/
|
||||
void evictQueries() throws HibernateException;
|
||||
|
||||
/**
|
||||
* The underlying RegionFactory in use.
|
||||
*
|
||||
* @return The {@code RegionFactory}
|
||||
*/
|
||||
RegionFactory getRegionFactory();
|
||||
|
||||
/**
|
||||
* Applies any defined prefix, handling all {@code null} checks.
|
||||
*
|
||||
* @param regionName The region name to qualify
|
||||
*
|
||||
* @return The qualified name
|
||||
*/
|
||||
String qualifyRegionName(String regionName);
|
||||
|
||||
/**
|
||||
* Get the names of <tt>all</tt> cache regions, including entity, collection, natural-id and query caches.
|
||||
*
|
||||
* @return All cache region names
|
||||
*/
|
||||
String[] getSecondLevelCacheRegionNames();
|
||||
|
||||
/**
|
||||
* Find the "access strategy" for the named entity cache region.
|
||||
*
|
||||
* @param regionName The name of the region
|
||||
*
|
||||
* @return That region's "access strategy"
|
||||
*/
|
||||
EntityRegionAccessStrategy getEntityRegionAccess(String regionName);
|
||||
|
||||
/**
|
||||
* Find the "access strategy" for the named collection cache region.
|
||||
*
|
||||
* @param regionName The name of the region
|
||||
*
|
||||
* @return That region's "access strategy"
|
||||
*/
|
||||
CollectionRegionAccessStrategy getCollectionRegionAccess(String regionName);
|
||||
|
||||
/**
|
||||
* Find the "access strategy" for the named natrual-id cache region.
|
||||
*
|
||||
* @param regionName The name of the region
|
||||
*
|
||||
* @return That region's "access strategy"
|
||||
*/
|
||||
NaturalIdRegionAccessStrategy getNaturalIdCacheRegionAccessStrategy(String regionName);
|
||||
|
||||
EntityRegionAccessStrategy determineEntityRegionAccessStrategy(PersistentClass model);
|
||||
|
||||
NaturalIdRegionAccessStrategy determineNaturalIdRegionAccessStrategy(PersistentClass model);
|
||||
|
||||
CollectionRegionAccessStrategy determineCollectionRegionAccessStrategy(Collection model);
|
||||
}
|
|
@ -7,7 +7,9 @@
|
|||
package org.hibernate.engine.spi;
|
||||
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.internal.CacheImpl;
|
||||
import org.hibernate.cache.internal.DisabledCaching;
|
||||
import org.hibernate.cache.internal.EnabledCaching;
|
||||
import org.hibernate.cache.spi.CacheImplementor;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceInitiator;
|
||||
|
||||
|
@ -25,7 +27,9 @@ public class CacheInitiator implements SessionFactoryServiceInitiator<CacheImple
|
|||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryOptions sessionFactoryOptions,
|
||||
ServiceRegistryImplementor registry) {
|
||||
return new CacheImpl( sessionFactory );
|
||||
return sessionFactoryOptions.isSecondLevelCacheEnabled()
|
||||
? new EnabledCaching( sessionFactory )
|
||||
: new DisabledCaching( sessionFactory );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -48,6 +48,7 @@ import org.hibernate.SimpleNaturalIdLoadAccess;
|
|||
import org.hibernate.Transaction;
|
||||
import org.hibernate.TypeHelper;
|
||||
import org.hibernate.UnknownProfileException;
|
||||
import org.hibernate.cache.spi.CacheTransactionSynchronization;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.jdbc.LobCreator;
|
||||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
|
@ -334,6 +335,11 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
|
|||
delegate.markForRollbackOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTransactionStartTimestamp() {
|
||||
return delegate.getTransactionStartTimestamp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlushModeType getFlushMode() {
|
||||
return delegate.getFlushMode();
|
||||
|
@ -474,6 +480,16 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
|
|||
return delegate.getTransaction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startTransactionBoundary() {
|
||||
delegate.startTransactionBoundary();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CacheTransactionSynchronization getCacheTransactionSynchronization() {
|
||||
return delegate.getCacheTransactionSynchronization();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTransactionBegin() {
|
||||
delegate.afterTransactionBegin();
|
||||
|
|
|
@ -31,10 +31,7 @@ import org.hibernate.StatelessSession;
|
|||
import org.hibernate.StatelessSessionBuilder;
|
||||
import org.hibernate.TypeHelper;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.cache.spi.QueryCache;
|
||||
import org.hibernate.cache.spi.Region;
|
||||
import org.hibernate.cache.spi.UpdateTimestampsCache;
|
||||
import org.hibernate.cache.spi.access.RegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.CacheImplementor;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
|
@ -272,24 +269,9 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
|
|||
return delegate.findEntityGraphByName( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryCache getQueryCache() {
|
||||
return delegate.getQueryCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryCache getQueryCache(String regionName) throws HibernateException {
|
||||
return delegate.getQueryCache( regionName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateTimestampsCache getUpdateTimestampsCache() {
|
||||
return delegate.getUpdateTimestampsCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatisticsImplementor getStatisticsImplementor() {
|
||||
return delegate.getStatisticsImplementor();
|
||||
return delegate.getStatistics();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -322,31 +304,6 @@ public class SessionFactoryDelegatingImpl implements SessionFactoryImplementor,
|
|||
return delegate.getIdentifierGenerator( rootEntityName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region getSecondLevelCacheRegion(String regionName) {
|
||||
return delegate.getSecondLevelCacheRegion( regionName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionAccessStrategy getSecondLevelCacheRegionAccessStrategy(String regionName) {
|
||||
return delegate.getSecondLevelCacheRegionAccessStrategy(regionName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region getNaturalIdCacheRegion(String regionName) {
|
||||
return delegate.getNaturalIdCacheRegion( regionName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionAccessStrategy getNaturalIdCacheRegionAccessStrategy(String regionName) {
|
||||
return delegate.getNaturalIdCacheRegionAccessStrategy(regionName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map getAllSecondLevelCacheRegions() {
|
||||
return delegate.getAllSecondLevelCacheRegions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLExceptionConverter getSQLExceptionConverter() {
|
||||
return delegate.getSQLExceptionConverter();
|
||||
|
|
|
@ -21,13 +21,7 @@ import org.hibernate.Session;
|
|||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.SessionFactoryObserver;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.cache.spi.QueryCache;
|
||||
import org.hibernate.cache.spi.Region;
|
||||
import org.hibernate.cache.spi.UpdateTimestampsCache;
|
||||
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.access.RegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.CacheImplementor;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
|
@ -217,7 +211,7 @@ public interface SessionFactoryImplementor extends Mapping, SessionFactory, Quer
|
|||
|
||||
|
||||
/**
|
||||
* @deprecated Just use {@link #getStatistics} (with covariant return here as {@link StatisticsImplementor}).
|
||||
* @deprecated (since 5.2) Just use {@link #getStatistics} (with covariant return here as {@link StatisticsImplementor}).
|
||||
*/
|
||||
@Deprecated
|
||||
default StatisticsImplementor getStatisticsImplementor() {
|
||||
|
@ -420,138 +414,4 @@ public interface SessionFactoryImplementor extends Mapping, SessionFactory, Quer
|
|||
EntityGraph findEntityGraphByName(String name);
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Move to CacheImplementor calls
|
||||
|
||||
/**
|
||||
* Get a named second-level cache region
|
||||
*
|
||||
* @param regionName The name of the region to retrieve.
|
||||
*
|
||||
* @return The name of the region
|
||||
*
|
||||
* @deprecated (since 5.2) Use this factory's {@link #getCache()} reference
|
||||
* to access Region via {@link CacheImplementor#determineEntityRegionAccessStrategy} or
|
||||
* {@link CacheImplementor#determineCollectionRegionAccessStrategy} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default Region getSecondLevelCacheRegion(String regionName) {
|
||||
final EntityRegionAccessStrategy entityRegionAccess = getCache().getEntityRegionAccess( regionName );
|
||||
if ( entityRegionAccess != null ) {
|
||||
return entityRegionAccess.getRegion();
|
||||
}
|
||||
|
||||
final CollectionRegionAccessStrategy collectionRegionAccess = getCache().getCollectionRegionAccess( regionName );
|
||||
if ( collectionRegionAccess != null ) {
|
||||
return collectionRegionAccess.getRegion();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the "access strategy" for the named cache region.
|
||||
*
|
||||
* @param regionName The name of the region
|
||||
*
|
||||
* @return That region's "access strategy"
|
||||
*
|
||||
*
|
||||
* @deprecated (since 5.2) Use this factory's {@link #getCache()} reference
|
||||
* to access {@link CacheImplementor#determineEntityRegionAccessStrategy} or
|
||||
* {@link CacheImplementor#determineCollectionRegionAccessStrategy} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default RegionAccessStrategy getSecondLevelCacheRegionAccessStrategy(String regionName) {
|
||||
final EntityRegionAccessStrategy entityRegionAccess = getCache().getEntityRegionAccess( regionName );
|
||||
if ( entityRegionAccess != null ) {
|
||||
return entityRegionAccess;
|
||||
}
|
||||
|
||||
final CollectionRegionAccessStrategy collectionRegionAccess = getCache().getCollectionRegionAccess( regionName );
|
||||
if ( collectionRegionAccess != null ) {
|
||||
return collectionRegionAccess;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a named natural-id cache region
|
||||
*
|
||||
* @param regionName The name of the region to retrieve.
|
||||
*
|
||||
* @return The region
|
||||
*
|
||||
* @deprecated (since 5.2) Use this factory's {@link #getCache()} ->
|
||||
* {@link CacheImplementor#getNaturalIdCacheRegionAccessStrategy(String)} ->
|
||||
* {@link NaturalIdRegionAccessStrategy#getRegion()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default Region getNaturalIdCacheRegion(String regionName) {
|
||||
return getCache().getNaturalIdCacheRegionAccessStrategy( regionName ).getRegion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the "access strategy" for the named naturalId cache region.
|
||||
*
|
||||
* @param regionName The region name
|
||||
*
|
||||
* @return That region's "access strategy"
|
||||
*
|
||||
* @deprecated (since 5.2) Use this factory's {@link #getCache()} ->
|
||||
* {@link CacheImplementor#getNaturalIdCacheRegionAccessStrategy(String)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default RegionAccessStrategy getNaturalIdCacheRegionAccessStrategy(String regionName) {
|
||||
return getCache().getNaturalIdCacheRegionAccessStrategy( regionName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a map of all the second level cache regions currently maintained in
|
||||
* this session factory. The map is structured with the region name as the
|
||||
* key and the {@link Region} instances as the values.
|
||||
*
|
||||
* @return The map of regions
|
||||
*
|
||||
* @deprecated (since 5.2) with no direct replacement; use this factory's {@link #getCache()} reference
|
||||
* to access cache objects as needed.
|
||||
*/
|
||||
@Deprecated
|
||||
Map getAllSecondLevelCacheRegions();
|
||||
|
||||
/**
|
||||
* Get the default query cache.
|
||||
*
|
||||
* @deprecated Use {@link CacheImplementor#getDefaultQueryCache()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
default QueryCache getQueryCache() {
|
||||
return getCache().getDefaultQueryCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a particular named query cache, or the default cache
|
||||
*
|
||||
* @param regionName the name of the cache region, or null for the default query cache
|
||||
*
|
||||
* @return the existing cache, or a newly created cache if none by that region name
|
||||
*
|
||||
* @deprecated Use {@link CacheImplementor#getQueryCache(String)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
default QueryCache getQueryCache(String regionName) {
|
||||
return getCache().getQueryCache( regionName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cache of table update timestamps
|
||||
*
|
||||
* @deprecated Use {@link CacheImplementor#getUpdateTimestampsCache()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
default UpdateTimestampsCache getUpdateTimestampsCache() {
|
||||
return getCache().getUpdateTimestampsCache();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.Interceptor;
|
|||
import org.hibernate.ScrollMode;
|
||||
import org.hibernate.SharedSessionContract;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.cache.spi.CacheTransactionSynchronization;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.jdbc.LobCreationContext;
|
||||
|
@ -151,9 +152,27 @@ public interface SharedSessionContractImplementor
|
|||
void markForRollbackOnly();
|
||||
|
||||
/**
|
||||
* System time before the start of the transaction
|
||||
* A "timestamp" at or before the start of the current transaction.
|
||||
*
|
||||
* @apiNote This "timestamp" need not be related to timestamp in the Java Date/millisecond
|
||||
* sense. It just needs to be an incrementing value. See
|
||||
* {@link CacheTransactionSynchronization#getCurrentTransactionStartTimestamp()}
|
||||
*/
|
||||
long getTimestamp();
|
||||
long getTransactionStartTimestamp();
|
||||
|
||||
/**
|
||||
* @deprecated (since 6.0) Use
|
||||
*/
|
||||
@Deprecated
|
||||
default long getTimestamp() {
|
||||
return getTransactionStartTimestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
* The current CacheTransactionContext associated with the Session. This may
|
||||
* return {@code null} when the Session is not currently part of a transaction.
|
||||
*/
|
||||
CacheTransactionSynchronization getCacheTransactionSynchronization();
|
||||
|
||||
/**
|
||||
* Does this <tt>Session</tt> have an active Hibernate transaction
|
||||
|
|
|
@ -9,7 +9,7 @@ package org.hibernate.event.internal;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.ObjectDeletedException;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.engine.spi.EntityEntry;
|
||||
import org.hibernate.engine.spi.Status;
|
||||
|
@ -66,7 +66,7 @@ public abstract class AbstractLockUpgradeEventListener extends AbstractReassocia
|
|||
Object ck = null;
|
||||
try {
|
||||
if ( cachingEnabled ) {
|
||||
EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||
EntityDataAccess cache = persister.getCacheAccessStrategy();
|
||||
ck = cache.generateCacheKey( entry.getId(), persister, source.getFactory(), source.getTenantIdentifier() );
|
||||
lock = cache.lockItem( source, ck, entry.getVersion() );
|
||||
}
|
||||
|
|
|
@ -669,7 +669,7 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
|
|||
if ( snapshot == null ) {
|
||||
//do we even really need this? the update will fail anyway....
|
||||
if ( session.getFactory().getStatistics().isStatisticsEnabled() ) {
|
||||
session.getFactory().getStatisticsImplementor()
|
||||
session.getFactory().getStatistics()
|
||||
.optimisticFailure( persister.getEntityName() );
|
||||
}
|
||||
throw new StaleObjectStateException( persister.getEntityName(), id );
|
||||
|
|
|
@ -9,7 +9,7 @@ package org.hibernate.event.internal;
|
|||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
||||
import org.hibernate.cache.spi.entry.CollectionCacheEntry;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.internal.CacheHelper;
|
||||
|
@ -78,7 +78,7 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
|
|||
}
|
||||
|
||||
if ( source.getFactory().getStatistics().isStatisticsEnabled() ) {
|
||||
source.getFactory().getStatisticsImplementor().fetchCollection(
|
||||
source.getFactory().getStatistics().fetchCollection(
|
||||
ce.getLoadedPersister().getRole()
|
||||
);
|
||||
}
|
||||
|
@ -116,17 +116,17 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
|
|||
}
|
||||
|
||||
final SessionFactoryImplementor factory = source.getFactory();
|
||||
final CollectionRegionAccessStrategy cacheAccessStrategy = persister.getCacheAccessStrategy();
|
||||
final CollectionDataAccess cacheAccessStrategy = persister.getCacheAccessStrategy();
|
||||
final Object ck = cacheAccessStrategy.generateCacheKey( id, persister, factory, source.getTenantIdentifier() );
|
||||
final Object ce = CacheHelper.fromSharedCache( source, ck, persister.getCacheAccessStrategy() );
|
||||
|
||||
if ( factory.getStatistics().isStatisticsEnabled() ) {
|
||||
if ( ce == null ) {
|
||||
factory.getStatisticsImplementor()
|
||||
factory.getStatistics()
|
||||
.secondLevelCacheMiss( cacheAccessStrategy.getRegion().getName() );
|
||||
}
|
||||
else {
|
||||
factory.getStatisticsImplementor()
|
||||
factory.getStatistics()
|
||||
.secondLevelCacheHit( cacheAccessStrategy.getRegion().getName() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import org.hibernate.NonUniqueObjectException;
|
|||
import org.hibernate.PersistentObjectException;
|
||||
import org.hibernate.TypeMismatchException;
|
||||
import org.hibernate.WrongClassException;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.cache.spi.entry.CacheEntry;
|
||||
import org.hibernate.cache.spi.entry.ReferenceCacheEntryImpl;
|
||||
|
@ -384,7 +384,7 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
|
|||
final SessionImplementor source) {
|
||||
SoftLock lock = null;
|
||||
final Object ck;
|
||||
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
||||
if ( persister.canWriteToCache() ) {
|
||||
ck = cache.generateCacheKey(
|
||||
event.getEntityId(),
|
||||
|
@ -640,7 +640,7 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
|
|||
final LoadEvent event,
|
||||
final EntityPersister persister,
|
||||
SessionImplementor source ) {
|
||||
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
||||
final Object ck = cache.generateCacheKey(
|
||||
event.getEntityId(),
|
||||
persister,
|
||||
|
@ -651,12 +651,12 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
|
|||
final Object ce = CacheHelper.fromSharedCache( source, ck, persister.getCacheAccessStrategy() );
|
||||
if ( source.getFactory().getStatistics().isStatisticsEnabled() ) {
|
||||
if ( ce == null ) {
|
||||
source.getFactory().getStatisticsImplementor().secondLevelCacheMiss(
|
||||
source.getFactory().getStatistics().secondLevelCacheMiss(
|
||||
cache.getRegion().getName()
|
||||
);
|
||||
}
|
||||
else {
|
||||
source.getFactory().getStatisticsImplementor().secondLevelCacheHit(
|
||||
source.getFactory().getStatistics().secondLevelCacheHit(
|
||||
cache.getRegion().getName()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -316,8 +316,7 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme
|
|||
}
|
||||
else if ( isVersionChanged( entity, source, persister, target ) ) {
|
||||
if ( source.getFactory().getStatistics().isStatisticsEnabled() ) {
|
||||
source.getFactory().getStatisticsImplementor()
|
||||
.optimisticFailure( entityName );
|
||||
source.getFactory().getStatistics().optimisticFailure( entityName );
|
||||
}
|
||||
throw new StaleObjectStateException( entityName, id );
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.PersistentObjectException;
|
||||
import org.hibernate.UnresolvableObjectException;
|
||||
import org.hibernate.action.spi.AfterTransactionCompletionProcess;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.engine.internal.Cascade;
|
||||
import org.hibernate.engine.internal.CascadePoint;
|
||||
|
@ -152,7 +152,7 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
|
|||
// multiple actions queued during the same flush
|
||||
previousVersion = persister.getVersion( object );
|
||||
}
|
||||
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
|
||||
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
||||
final Object ck = cache.generateCacheKey(
|
||||
id,
|
||||
persister,
|
||||
|
@ -160,13 +160,8 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
|
|||
source.getTenantIdentifier()
|
||||
);
|
||||
final SoftLock lock = cache.lockItem( source, ck, previousVersion );
|
||||
source.getActionQueue().registerProcess( new AfterTransactionCompletionProcess() {
|
||||
@Override
|
||||
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) {
|
||||
cache.unlockItem( session, ck, lock );
|
||||
}
|
||||
} );
|
||||
cache.remove( source, ck );
|
||||
source.getActionQueue().registerProcess( (success, session) -> cache.unlockItem( session, ck, lock ) );
|
||||
}
|
||||
|
||||
evictCachedCollections( persister, id, source );
|
||||
|
@ -201,7 +196,7 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
|
|||
if ( type.isCollectionType() ) {
|
||||
CollectionPersister collectionPersister = source.getFactory().getMetamodel().collectionPersister( ( (CollectionType) type ).getRole() );
|
||||
if ( collectionPersister.hasCache() ) {
|
||||
final CollectionRegionAccessStrategy cache = collectionPersister.getCacheAccessStrategy();
|
||||
final CollectionDataAccess cache = collectionPersister.getCacheAccessStrategy();
|
||||
final Object ck = cache.generateCacheKey(
|
||||
id,
|
||||
collectionPersister,
|
||||
|
@ -209,13 +204,8 @@ public class DefaultRefreshEventListener implements RefreshEventListener {
|
|||
source.getTenantIdentifier()
|
||||
);
|
||||
final SoftLock lock = cache.lockItem( source, ck, null );
|
||||
source.getActionQueue().registerProcess( new AfterTransactionCompletionProcess() {
|
||||
@Override
|
||||
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) {
|
||||
cache.unlockItem( session, ck, lock );
|
||||
}
|
||||
} );
|
||||
cache.remove( source, ck );
|
||||
source.getActionQueue().registerProcess( (success, session) -> cache.unlockItem( session, ck, lock ) );
|
||||
}
|
||||
}
|
||||
else if ( type.isComponentType() ) {
|
||||
|
|
|
@ -10,7 +10,7 @@ import java.io.Serializable;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.event.spi.ResolveNaturalIdEvent;
|
||||
import org.hibernate.event.spi.ResolveNaturalIdEventListener;
|
||||
|
@ -120,13 +120,12 @@ public class DefaultResolveNaturalIdEventListener
|
|||
);
|
||||
|
||||
if ( stats ) {
|
||||
final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy = event.getEntityPersister().getNaturalIdCacheAccessStrategy();
|
||||
final String regionName = naturalIdCacheAccessStrategy == null ? null : naturalIdCacheAccessStrategy.getRegion().getName();
|
||||
final long endTime = System.nanoTime();
|
||||
final long milliseconds = TimeUnit.MILLISECONDS.convert( endTime - startTime, TimeUnit.NANOSECONDS );
|
||||
factory.getStatisticsImplementor().naturalIdQueryExecuted(
|
||||
regionName,
|
||||
milliseconds );
|
||||
factory.getStatistics().naturalIdQueryExecuted(
|
||||
event.getEntityPersister().getRootEntityName(),
|
||||
milliseconds
|
||||
);
|
||||
}
|
||||
|
||||
//PK can be null if the entity doesn't exist
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue