HHH-4022 - Add an actual API contract for querying/managing cache regions (from app code)

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17027 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Steve Ebersole 2009-07-07 18:39:39 +00:00
parent cd23a6c3ff
commit b339e33121
10 changed files with 612 additions and 177 deletions

View File

@ -62,7 +62,7 @@
<dependency>
<groupId>org.hibernate.java-persistence</groupId>
<artifactId>jpa-api</artifactId>
<version>2.0.Beta1</version>
<version>2.0.pfd-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>javassist</groupId>

View File

@ -342,6 +342,25 @@ public abstract class BasicRegionAdapter implements Region {
}
}
public boolean contains(Object key) {
if ( !checkValid() ) {
return false;
}
try {
Option opt = new Option();
opt.setLockAcquisitionTimeout(100);
CacheHelper.setInvocationOption( jbcCache, opt );
return CacheHelper.getAllowingTimeout( jbcCache, regionFqn, key ) != null;
}
catch ( CacheException ce ) {
throw ce;
}
catch ( Throwable t ) {
throw new CacheException( t );
}
}
public long getSizeInMemory() {
// not supported
return -1;
@ -356,7 +375,11 @@ public abstract class BasicRegionAdapter implements Region {
size--;
}
return size;
} catch (Exception e) {
}
catch ( CacheException ce ) {
throw ce;
}
catch (Exception e) {
throw new CacheException(e);
}
}

View File

@ -0,0 +1,165 @@
/*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate;
import java.io.Serializable;
/**
* Provides an API for querying/managing the second level cache regions.
* <p/>
* CAUTION: None of these methods respect any isolation or transactional
* semantics associated with the underlying caches. Specifically, evictions
* perform an immediate "hard" removal outside any transactions and/or locking
* scheme(s).
*
* @author Steve Ebersole
*/
public interface Cache {
/**
* Determine whether the cache contains data for the given entity "instance".
* <p/>
* The semantic here is whether the cache contains data visible for the
* current call context.
*
* @param entityClass The entity class.
* @param identifier The entity identifier
*
* @return True if the underlying cache contains corresponding data; false
* otherwise.
*/
public boolean containsEntity(Class entityClass, Serializable identifier);
/**
* Determine whether the cache contains data for the given entity "instance".
* <p/>
* The semantic here is whether the cache contains data visible for the
* current call context.
*
* @param entityName The entity name.
* @param identifier The entity identifier
*
* @return True if the underlying cache contains corresponding data; false otherwise.
*/
public boolean containsEntity(String entityName, Serializable identifier);
/**
* Evicts the entity data for a particular entity "instance".
*
* @param entityClass The entity class.
* @param identifier The entity identifier
*/
public void evictEntity(Class entityClass, Serializable identifier);
/**
* Evicts the entity data for a particular entity "instance".
*
* @param entityName The entity name.
* @param identifier The entity identifier
*/
public void evictEntity(String entityName, Serializable identifier);
/**
* Evicts all entity data from the given region (i.e. for all entities of
* type).
*
* @param entityClass The entity class.
*/
public void evictEntityRegion(Class entityClass);
/**
* Evicts all entity data from the given region (i.e. for all entities of
* type).
*
* @param entityName The entity name.
*/
public void evictEntityRegion(String entityName);
/**
* Evict data from all entity regions.
*/
public void evictEntityRegions();
/**
* Determine whether the cache contains data for the given collection.
* <p/>
* The semantic here is whether the cache contains data visible for the
* current call context.
*
* @param role The name of the collection role (in form
* [owner-entity-name].[collection-property-name]) whose regions should be
* evicted.
* @param ownerIdentifier The identifier of the owning entity
*
* @return True if the underlying cache contains corresponding data; false otherwise.
*/
public boolean containsCollection(String role, Serializable ownerIdentifier);
/**
* 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
*/
public void evictCollection(String role, Serializable ownerIdentifier);
/**
* Evicts all entity data from the given region (i.e. evicts cached data
* for all of the specified c9ollection role).
*
* @param role The "collection role" (in form [owner-entity-name].[collection-property-name]).
*/
public void evictCollectionRegion(String role);
/**
* Evict data from all collection regions.
*/
public void evictCollectionRegions();
/**
* Determine whether the cache contains data for the given query.
* <p/>
* The semantic here is whether the cache contains any data for the given
* region name since query result caches are not transactionally isolated.
*
* @param regionName The cache name given to the query.
*
* @return True if the underlying cache contains corresponding data; false otherwise.
*/
public boolean containsQuery(String regionName);
/**
* Evicts all cached query results from the default region.
*/
public void evictDefaultQueryRegion();
/**
* Evicts all cached query results under the given name.
*
* @param regionName The cache name associated to the queries being cached.
*/
public void evictQueryRegion(String regionName);
/**
* Evict data from all query regions.
*/
public void evictQueryRegions();
}

View File

@ -37,69 +37,82 @@ import org.hibernate.stat.Statistics;
import org.hibernate.engine.FilterDefinition;
/**
* Creates <tt>Session</tt>s. Usually an application has a single <tt>SessionFactory</tt>.
* Threads servicing client requests obtain <tt>Session</tt>s from the factory.<br>
* <br>
* Implementors must be threadsafe.<br>
* <br>
* <tt>SessionFactory</tt>s are immutable. The behaviour of a <tt>SessionFactory</tt> is
* controlled by properties supplied at configuration time. These properties are defined
* on <tt>Environment</tt>.
* The main contract here is the creation of {@link Session} instances. Usually
* an application has a single {@link SessionFactory} instance and threads
* servicing client requests obtain {@link Session} instances from this factory.
* <p/>
* The internal state of a {@link SessionFactory} is immutable. Once it is created
* this internal state is set. This internal state includes all of the metadata
* about Object/Relational Mapping.
* <p/>
* Implementors <strong>must</strong> be threadsafe.
*
* @see Session
* @see org.hibernate.cfg.Environment
* @see org.hibernate.cfg.Configuration
* @see org.hibernate.connection.ConnectionProvider
* @see org.hibernate.transaction.TransactionFactory
*
* @author Gavin King
* @author Steve Ebersole
*/
public interface SessionFactory extends Referenceable, Serializable {
/**
* Open a <tt>Session</tt> on the given connection.
* <p>
* Note that the second-level cache will be disabled if you
* supply a JDBC connection. Hibernate will not be able to track
* any statements you might have executed in the same transaction.
* Consider implementing your own <tt>ConnectionProvider</tt>.
* Open a {@link Session}.
* <p/>
* JDBC {@link Connection connection(s} will be obtained from the
* configured {@link org.hibernate.connection.ConnectionProvider} as needed
* to perform requested work.
*
* @param connection a connection provided by the application.
* @return Session
* @return The created session.
*
* @throws HibernateException Indicates a peroblem opening the session; pretty rare here.
*/
public org.hibernate.classic.Session openSession(Connection connection);
public org.hibernate.classic.Session openSession() throws HibernateException;
/**
* Create database connection and open a <tt>Session</tt> on it, specifying an
* interceptor.
* Open a {@link Session}, utilizing the specified {@link Interceptor}.
* <p/>
* JDBC {@link Connection connection(s} will be obtained from the
* configured {@link org.hibernate.connection.ConnectionProvider} as needed
* to perform requested work.
*
* @param interceptor a session-scoped interceptor
* @return Session
* @throws HibernateException
*
* @return The created session.
*
* @throws HibernateException Indicates a peroblem opening the session; pretty rare here.
*/
public org.hibernate.classic.Session openSession(Interceptor interceptor) throws HibernateException;
/**
* Open a <tt>Session</tt> on the given connection, specifying an interceptor.
* Open a {@link Session}, utilizing the specfied JDBC {@link Connection}.
* <p>
* Note that the second-level cache will be disabled if you
* supply a JDBC connection. Hibernate will not be able to track
* any statements you might have executed in the same transaction.
* Consider implementing your own <tt>ConnectionProvider</tt>.
* Note that the second-level cache will be disabled if you supply a JDBC
* connection. Hibernate will not be able to track any statements you might
* have executed in the same transaction. Consider implementing your own
* {@link org.hibernate.connection.ConnectionProvider} instead as a highly
* recommended alternative.
*
* @param connection a connection provided by the application.
*
* @return The created session.
*/
public org.hibernate.classic.Session openSession(Connection connection);
/**
* Open a {@link Session}, utilizing the specfied JDBC {@link Connection} and
* specified {@link Interceptor}.
* <p>
* Note that the second-level cache will be disabled if you supply a JDBC
* connection. Hibernate will not be able to track any statements you might
* have executed in the same transaction. Consider implementing your own
* {@link org.hibernate.connection.ConnectionProvider} instead as a highly
* recommended alternative.
*
* @param connection a connection provided by the application.
* @param interceptor a session-scoped interceptor
* @return Session
*
* @return The created session.
*/
public org.hibernate.classic.Session openSession(Connection connection, Interceptor interceptor);
/**
* Create database connection and open a <tt>Session</tt> on it.
*
* @return Session
* @throws HibernateException
*/
public org.hibernate.classic.Session openSession() throws HibernateException;
/**
* Obtains the current session. The definition of what exactly "current"
* means controlled by the {@link org.hibernate.context.CurrentSessionContext} impl configured
@ -111,123 +124,243 @@ public interface SessionFactory extends Referenceable, Serializable {
* impl.
*
* @return The current session.
*
* @throws HibernateException Indicates an issue locating a suitable current session.
*/
public org.hibernate.classic.Session getCurrentSession() throws HibernateException;
/**
* Get the <tt>ClassMetadata</tt> associated with the given entity class
* Open a new stateless session.
*
* @see org.hibernate.metadata.ClassMetadata
* @return The created stateless session.
*/
public ClassMetadata getClassMetadata(Class persistentClass) throws HibernateException;
public StatelessSession openStatelessSession();
/**
* Get the <tt>ClassMetadata</tt> associated with the given entity name
* Open a new stateless session, utilizing the specified JDBC
* {@link Connection}.
*
* @see org.hibernate.metadata.ClassMetadata
* @param connection Connection provided by the application.
*
* @return The created stateless session.
*/
public StatelessSession openStatelessSession(Connection connection);
/**
* Retrieve the {@link ClassMetadata} associated with the given entity class.
*
* @param entityClass The entity class
*
* @return The metadata associated with the given entity; may be null if no such
* entity was mapped.
*
* @throws HibernateException Generally null is returned instead of throwing.
*/
public ClassMetadata getClassMetadata(Class entityClass);
/**
* Retrieve the {@link ClassMetadata} associated with the given entity class.
*
* @param entityName The entity class
*
* @return The metadata associated with the given entity; may be null if no such
* entity was mapped.
*
* @throws HibernateException Generally null is returned instead of throwing.
* @since 3.0
*/
public ClassMetadata getClassMetadata(String entityName) throws HibernateException;
public ClassMetadata getClassMetadata(String entityName);
/**
* Get the <tt>CollectionMetadata</tt> associated with the named collection role
* Get the {@link CollectionMetadata} associated with the named collection role.
*
* @see org.hibernate.metadata.CollectionMetadata
* @param roleName The collection role (in form [owning-entity-name].[collection-property-name]).
*
* @return The metadata associated with the given collection; may be null if no such
* collection was mapped.
*
* @throws HibernateException Generally null is returned instead of throwing.
*/
public CollectionMetadata getCollectionMetadata(String roleName) throws HibernateException;
public CollectionMetadata getCollectionMetadata(String roleName);
/**
* Get all <tt>ClassMetadata</tt> as a <tt>Map</tt> from entityname <tt>String</tt>
* to metadata object
* Retrieve the {@link ClassMetadata} for all mapped entities.
*
* @see org.hibernate.metadata.ClassMetadata
* @return a map from <tt>String</tt> an entity name to <tt>ClassMetaData</tt>
* @since 3.0 changed key from <tt>Class</tt> to <tt>String</tt>
* @return A map containing all {@link ClassMetadata} keyed by the
* corresponding {@link String} entity-name.
*
* @throws HibernateException Generally empty map is returned instead of throwing.
*
* @since 3.0 changed key from {@link Class} to {@link String}.
*/
public Map getAllClassMetadata() throws HibernateException;
public Map getAllClassMetadata();
/**
* Get all <tt>CollectionMetadata</tt> as a <tt>Map</tt> from role name
* to metadata object
* Get the {@link CollectionMetadata} for all mapped collections
*
* @see org.hibernate.metadata.CollectionMetadata
* @return a map from <tt>String</tt> to <tt>CollectionMetadata</tt>
*
* @throws HibernateException Generally empty map is returned instead of throwing.
*/
public Map getAllCollectionMetadata() throws HibernateException;
public Map getAllCollectionMetadata();
/**
* Get the statistics for this session factory
* Retrieve the statistics fopr this factory.
*
* @return The statistics.
*/
public Statistics getStatistics();
/**
* Destroy this <tt>SessionFactory</tt> and release all resources (caches,
* connection pools, etc). It is the responsibility of the application
* to ensure that there are no open <tt>Session</tt>s before calling
* <tt>close()</tt>.
* connection pools, etc).
* <p/>
* It is the responsibility of the application to ensure that there are no
* open {@link Session sessions} before calling this method as the impact
* on those {@link Session sessions} is indeterminate.
* <p/>
* No-ops if already {@link #isClosed closed}.
*
* @throws HibernateException Indicates an issue closing the factory.
*/
public void close() throws HibernateException;
/**
* Was this <tt>SessionFactory</tt> already closed?
* Is this factory already closed?
*
* @return True if this factory is already closed; false otherwise.
*/
public boolean isClosed();
/**
* Obtain direct access to the underlying cache regions.
*
* @return The direct cache access API.
*/
public Cache getCache();
/**
* Evict all entries from the second-level cache. This method occurs outside
* of any transaction; it performs an immediate "hard" remove, so does not respect
* any transaction isolation semantics of the usage strategy. Use with care.
*
* @param persistentClass The entity class for which to evict data.
*
* @throws HibernateException Generally will mean that either that
* 'persisttentClass' did not name a mapped entity or a problem
* communicating with underlying cache impl.
*
* @deprecated Use {@link Cache#evictEntityRegion(Class)} accessed through
* {@link #getCache()} instead.
*/
public void evict(Class persistentClass) throws HibernateException;
/**
* Evict an entry from the second-level cache. This method occurs outside
* of any transaction; it performs an immediate "hard" remove, so does not respect
* any transaction isolation semantics of the usage strategy. Use with care.
*
* @param persistentClass The entity class for which to evict data.
* @param id The entity id
*
* @throws HibernateException Generally will mean that either that
* 'persisttentClass' did not name a mapped entity or a problem
* communicating with underlying cache impl.
*
* @deprecated Use {@link Cache#containsEntity(Class, Serializable)} accessed through
* {@link #getCache()} instead.
*/
public void evict(Class persistentClass, Serializable id) throws HibernateException;
/**
* Evict all entries from the second-level cache. This method occurs outside
* of any transaction; it performs an immediate "hard" remove, so does not respect
* any transaction isolation semantics of the usage strategy. Use with care.
*
* @param entityName The entity name for which to evict data.
*
* @throws HibernateException Generally will mean that either that
* 'persisttentClass' did not name a mapped entity or a problem
* communicating with underlying cache impl.
*
* @deprecated Use {@link Cache#evictEntityRegion(String)} accessed through
* {@link #getCache()} instead.
*/
public void evictEntity(String entityName) throws HibernateException;
/**
* Evict an entry from the second-level cache. This method occurs outside
* of any transaction; it performs an immediate "hard" remove, so does not respect
* any transaction isolation semantics of the usage strategy. Use with care.
*
* @param entityName The entity name for which to evict data.
* @param id The entity id
*
* @throws HibernateException Generally will mean that either that
* 'persisttentClass' did not name a mapped entity or a problem
* communicating with underlying cache impl.
*
* @deprecated Use {@link Cache#evictEntity(String,Serializable)} accessed through
* {@link #getCache()} instead.
*/
public void evictEntity(String entityName, Serializable id) throws HibernateException;
/**
* Evict all entries from the second-level cache. This method occurs outside
* of any transaction; it performs an immediate "hard" remove, so does not respect
* any transaction isolation semantics of the usage strategy. Use with care.
*
* @param roleName The name of the collection role whose regions should be evicted
*
* @throws HibernateException Generally will mean that either that
* 'roleName' did not name a mapped collection or a problem
* communicating with underlying cache impl.
*
* @deprecated Use {@link Cache#evictCollectionRegion(String)} accessed through
* {@link #getCache()} instead.
*/
public void evictCollection(String roleName) throws HibernateException;
/**
* Evict an entry from the second-level cache. This method occurs outside
* of any transaction; it performs an immediate "hard" remove, so does not respect
* any transaction isolation semantics of the usage strategy. Use with care.
*
* @param roleName The name of the collection role
* @param id The id of the collection owner
*
* @throws HibernateException Generally will mean that either that
* 'roleName' did not name a mapped collection or a problem
* communicating with underlying cache impl.
*
* @deprecated Use {@link Cache#evictCollection(String,Serializable)} accessed through
* {@link #getCache()} instead.
*/
public void evictCollection(String roleName, Serializable id) throws HibernateException;
/**
* Evict any query result sets cached in the default query cache region.
*/
public void evictQueries() throws HibernateException;
/**
* Evict any query result sets cached in the named query cache region.
*
* @param cacheRegion The named query cache region from which to evict.
*
* @throws HibernateException Since a not-found 'cacheRegion' simply no-ops,
* this should indicate a problem communicating with underlying cache impl.
*
* @deprecated Use {@link Cache#evictQueryRegion(String)} accessed through
* {@link #getCache()} instead.
*/
public void evictQueries(String cacheRegion) throws HibernateException;
/**
* Get a new stateless session.
* Evict any query result sets cached in the default query cache region.
*
* @throws HibernateException Indicate a problem communicating with
* underlying cache impl.
*
* @deprecated Use {@link Cache#evictQueryRegions} accessed through
* {@link #getCache()} instead.
*/
public StatelessSession openStatelessSession();
/**
* Get a new stateless session for the given JDBC connection.
*/
public StatelessSession openStatelessSession(Connection connection);
public void evictQueries() throws HibernateException;
/**
* Obtain a set of the names of all filters defined on this SessionFactory.

View File

@ -28,20 +28,18 @@ import java.io.Serializable;
import java.sql.Connection;
/**
* A command-oriented API for performing bulk operations
* against a database.<br>
* <br>
* A stateless session does not implement a first-level cache nor
* interact with any second-level cache, nor does it implement
* transactional write-behind or automatic dirty checking, nor do
* operations cascade to associated instances. Collections are
* ignored by a stateless session. Operations performed via a
* stateless session bypass Hibernate's event model and
* interceptors. Stateless sessions are vulnerable to data
* aliasing effects, due to the lack of a first-level cache.<br>
* <br>
* For certain kinds of transactions, a stateless session may
* perform slightly faster than a stateful session.
* A command-oriented API for performing bulk operations against a database.
* <p/>
* A stateless session does not implement a first-level cache nor interact
* with any second-level cache, nor does it implement transactional
* write-behind or automatic dirty checking, nor do operations cascade to
* associated instances. Collections are ignored by a stateless session.
* Operations performed via a stateless session bypass Hibernate's event model
* and interceptors. Stateless sessions are vulnerable to data aliasing
* effects, due to the lack of a first-level cache.
* <p/>
* For certain kinds of transactions, a stateless session may perform slightly
* faster than a stateful session.
*
* @author Gavin King
*/

View File

@ -49,6 +49,20 @@ public interface Region {
*/
public 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.
*/
public boolean contains(Object key);
/**
* The number of bytes is this cache region currently consuming in memory.
*

View File

@ -57,6 +57,11 @@ public abstract class BaseRegionAdapter implements Region {
underlyingCache.destroy();
}
public boolean contains(Object key) {
// safer to utilize the toMap() as oposed to say get(key) != null
return underlyingCache.toMap().containsKey( key );
}
public long getSizeInMemory() {
return underlyingCache.getSizeInMemory();
}

View File

@ -60,6 +60,7 @@ import org.hibernate.SessionFactory;
import org.hibernate.StatelessSession;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.EntityNameResolver;
import org.hibernate.Cache;
import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.cache.CacheKey;
import org.hibernate.cache.CollectionRegion;
@ -877,6 +878,15 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
return collectionMetadata;
}
public Type getReferencedPropertyType(String className, String propertyName)
throws MappingException {
return getEntityPersister(className).getPropertyType(propertyName);
}
public ConnectionProvider getConnectionProvider() {
return settings.getConnectionProvider();
}
/**
* Closes the session factory, releasing all held resources.
*
@ -946,76 +956,183 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
eventListeners.destroyListeners();
}
public void evictEntity(String entityName, Serializable id) throws HibernateException {
EntityPersister p = getEntityPersister( entityName );
if ( p.hasCache() ) {
if ( log.isDebugEnabled() ) {
log.debug( "evicting second-level cache: " + MessageHelper.infoString(p, id, this) );
}
CacheKey cacheKey = new CacheKey( id, p.getIdentifierType(), p.getRootEntityName(), EntityMode.POJO, this );
p.getCacheAccessStrategy().evict( cacheKey );
private final Cache cacheAccess = new CacheImpl();
private class CacheImpl implements Cache {
public boolean containsEntity(Class entityClass, Serializable identifier) {
return containsEntity( entityClass.getName(), identifier );
}
public boolean containsEntity(String entityName, Serializable identifier) {
// todo : need a contains() method on the underlying regions
throw new UnsupportedOperationException( "not yet implemented - HHH-4021" );
}
public void evictEntity(Class entityClass, Serializable identifier) {
evictEntity( entityClass.getName(), identifier );
}
public void evictEntity(String entityName, Serializable identifier) {
EntityPersister p = getEntityPersister( entityName );
if ( p.hasCache() ) {
if ( log.isDebugEnabled() ) {
log.debug(
"evicting second-level cache: " +
MessageHelper.infoString( p, identifier, SessionFactoryImpl.this )
);
}
CacheKey cacheKey = new CacheKey(
identifier,
p.getIdentifierType(),
p.getRootEntityName(),
EntityMode.POJO,
SessionFactoryImpl.this
);
p.getCacheAccessStrategy().evict( cacheKey );
}
}
public void evictEntityRegion(Class entityClass) {
evictEntityRegion( entityClass.getName() );
}
public void evictEntityRegion(String entityName) {
EntityPersister p = getEntityPersister( entityName );
if ( p.hasCache() ) {
if ( log.isDebugEnabled() ) {
log.debug( "evicting second-level cache: " + p.getEntityName() );
}
p.getCacheAccessStrategy().evictAll();
}
}
public void evictEntityRegions() {
Iterator entityNames = entityPersisters.keySet().iterator();
while ( entityNames.hasNext() ) {
evictEntityRegion( ( String ) entityNames.next() );
}
}
public boolean containsCollection(String role, Serializable ownerIdentifier) {
// todo : need a contains() method on the underlying regions
return false;
}
public void evictCollection(String role, Serializable ownerIdentifier) {
CollectionPersister p = getCollectionPersister( role );
if ( p.hasCache() ) {
if ( log.isDebugEnabled() ) {
log.debug(
"evicting second-level cache: " +
MessageHelper.collectionInfoString(p, ownerIdentifier, SessionFactoryImpl.this)
);
}
CacheKey cacheKey = new CacheKey(
ownerIdentifier,
p.getKeyType(),
p.getRole(),
EntityMode.POJO,
SessionFactoryImpl.this
);
p.getCacheAccessStrategy().evict( cacheKey );
}
}
public void evictCollectionRegion(String role) {
CollectionPersister p = getCollectionPersister( role );
if ( p.hasCache() ) {
if ( log.isDebugEnabled() ) {
log.debug( "evicting second-level cache: " + p.getRole() );
}
p.getCacheAccessStrategy().evictAll();
}
}
public void evictCollectionRegions() {
Iterator collectionRoles = collectionPersisters.keySet().iterator();
while ( collectionRoles.hasNext() ) {
evictCollectionRegion( ( String ) collectionRoles.next() );
}
}
public boolean containsQuery(String regionName) {
// todo : need a contains() method on the underlying regions
return false;
}
public void evictDefaultQueryRegion() {
if ( settings.isQueryCacheEnabled() ) {
queryCache.clear();
}
}
public void evictQueryRegion(String regionName) {
if ( regionName == null ) {
throw new NullPointerException(
"Region-name cannot be null (use Cache#evictDefaultQueryRegion to evict the default query cache)"
);
}
else {
synchronized ( allCacheRegions ) {
if ( settings.isQueryCacheEnabled() ) {
QueryCache namedQueryCache = ( QueryCache ) queryCaches.get( regionName );
if ( namedQueryCache != null ) {
namedQueryCache.clear();
// TODO : cleanup entries in queryCaches + allCacheRegions ?
}
}
}
}
}
public void evictQueryRegions() {
synchronized ( allCacheRegions ) {
Iterator regions = queryCaches.values().iterator();
while ( regions.hasNext() ) {
QueryCache cache = ( QueryCache ) regions.next();
cache.clear();
// TODO : cleanup entries in queryCaches + allCacheRegions ?
}
}
}
}
public Cache getCache() {
return cacheAccess;
}
public void evictEntity(String entityName, Serializable id) throws HibernateException {
getCache().evictEntity( entityName, id );
}
public void evictEntity(String entityName) throws HibernateException {
EntityPersister p = getEntityPersister( entityName );
if ( p.hasCache() ) {
if ( log.isDebugEnabled() ) {
log.debug( "evicting second-level cache: " + p.getEntityName() );
}
p.getCacheAccessStrategy().evictAll();
}
getCache().evictEntityRegion( entityName );
}
public void evict(Class persistentClass, Serializable id) throws HibernateException {
EntityPersister p = getEntityPersister( persistentClass.getName() );
if ( p.hasCache() ) {
if ( log.isDebugEnabled() ) {
log.debug( "evicting second-level cache: " + MessageHelper.infoString(p, id, this) );
}
CacheKey cacheKey = new CacheKey( id, p.getIdentifierType(), p.getRootEntityName(), EntityMode.POJO, this );
p.getCacheAccessStrategy().evict( cacheKey );
}
getCache().evictEntity( persistentClass, id );
}
public void evict(Class persistentClass) throws HibernateException {
EntityPersister p = getEntityPersister( persistentClass.getName() );
if ( p.hasCache() ) {
if ( log.isDebugEnabled() ) {
log.debug( "evicting second-level cache: " + p.getEntityName() );
}
p.getCacheAccessStrategy().evictAll();
}
getCache().evictEntityRegion( persistentClass );
}
public void evictCollection(String roleName, Serializable id) throws HibernateException {
CollectionPersister p = getCollectionPersister( roleName );
if ( p.hasCache() ) {
if ( log.isDebugEnabled() ) {
log.debug( "evicting second-level cache: " + MessageHelper.collectionInfoString(p, id, this) );
}
CacheKey cacheKey = new CacheKey( id, p.getKeyType(), p.getRole(), EntityMode.POJO, this );
p.getCacheAccessStrategy().evict( cacheKey );
}
getCache().evictCollection( roleName, id );
}
public void evictCollection(String roleName) throws HibernateException {
CollectionPersister p = getCollectionPersister( roleName );
if ( p.hasCache() ) {
if ( log.isDebugEnabled() ) {
log.debug( "evicting second-level cache: " + p.getRole() );
}
p.getCacheAccessStrategy().evictAll();
getCache().evictCollectionRegion( roleName );
}
public void evictQueries() throws HibernateException {
if ( settings.isQueryCacheEnabled() ) {
queryCache.clear();
}
}
public Type getReferencedPropertyType(String className, String propertyName)
throws MappingException {
return getEntityPersister(className).getPropertyType(propertyName);
}
public ConnectionProvider getConnectionProvider() {
return settings.getConnectionProvider();
public void evictQueries(String regionName) throws HibernateException {
getCache().evictQueryRegion( regionName );
}
public UpdateTimestampsCache getUpdateTimestampsCache() {
@ -1070,28 +1187,6 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
return statistics;
}
public void evictQueries() throws HibernateException {
if ( settings.isQueryCacheEnabled() ) {
queryCache.clear();
}
}
public void evictQueries(String cacheRegion) throws HibernateException {
if (cacheRegion==null) {
throw new NullPointerException("use the zero-argument form to evict the default query cache");
}
else {
synchronized (allCacheRegions) {
if ( settings.isQueryCacheEnabled() ) {
QueryCache currentQueryCache = (QueryCache) queryCaches.get(cacheRegion);
if ( currentQueryCache != null ) {
currentQueryCache.clear();
}
}
}
}
}
public FilterDefinition getFilterDefinition(String filterName) throws HibernateException {
FilterDefinition def = ( FilterDefinition ) filters.get( filterName );
if ( def == null ) {

View File

@ -90,26 +90,23 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
this.sessionFactory = sessionFactory;
}
public boolean contains(Class aClass, Object o) {
throw new UnsupportedOperationException( "not yet implemented - HHH-4021" );
public boolean contains(Class entityClass, Object identifier) {
return sessionFactory.getCache().containsEntity( entityClass, ( Serializable ) identifier );
}
public void evict(Class entityType, Object id) {
sessionFactory.evict( entityType, ( Serializable ) id );
public void evict(Class entityClass, Object identifier) {
sessionFactory.getCache().evictEntity( entityClass, ( Serializable ) identifier );
}
public void evict(Class entityType) {
sessionFactory.evict( entityType );
public void evict(Class entityClass) {
sessionFactory.getCache().evictEntityRegion( entityClass );
}
public void evictAll() {
for ( String entityName : (Set<String>) sessionFactory.getAllClassMetadata().entrySet() ) {
sessionFactory.evictEntity( entityName );
}
for ( String collectionName : (Set<String>) sessionFactory.getAllCollectionMetadata().entrySet() ) {
sessionFactory.evictCollection( collectionName );
}
sessionFactory.evictQueries();
sessionFactory.getCache().evictEntityRegions();
// TODO : if we want to allow an optional clearing of all cache data, the additional calls would be:
// sessionFactory.getCache().evictCollectionRegions();
// sessionFactory.getCache().evictQueryRegions();
}
}
}

View File

@ -19,6 +19,7 @@ import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.SessionFactory;
import org.hibernate.StatelessSession;
import org.hibernate.Cache;
import org.hibernate.engine.FilterDefinition;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.UUIDHexGenerator;
@ -144,6 +145,10 @@ public class SessionFactoryStub implements SessionFactory {
return false;
}
public Cache getCache() {
return getImpl().getCache();
}
public void evict(Class persistentClass, Serializable id)
throws HibernateException {
getImpl().evict(persistentClass, id);