Author: steve.ebersole(a)jboss.com
Date: 2009-07-07 14:39:39 -0400 (Tue, 07 Jul 2009)
New Revision: 17027
Added:
core/trunk/core/src/main/java/org/hibernate/Cache.java
Modified:
core/trunk/annotations/pom.xml
core/trunk/cache-jbosscache/src/main/java/org/hibernate/cache/jbc/BasicRegionAdapter.java
core/trunk/core/src/main/java/org/hibernate/SessionFactory.java
core/trunk/core/src/main/java/org/hibernate/StatelessSession.java
core/trunk/core/src/main/java/org/hibernate/cache/Region.java
core/trunk/core/src/main/java/org/hibernate/cache/impl/bridge/BaseRegionAdapter.java
core/trunk/core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/EntityManagerFactoryImpl.java
core/trunk/jmx/src/main/java/org/hibernate/jmx/SessionFactoryStub.java
Log:
HHH-4022 - Add an actual API contract for querying/managing cache regions (from app code)
Modified: core/trunk/annotations/pom.xml
===================================================================
--- core/trunk/annotations/pom.xml 2009-07-07 18:33:23 UTC (rev 17026)
+++ core/trunk/annotations/pom.xml 2009-07-07 18:39:39 UTC (rev 17027)
@@ -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>
Modified:
core/trunk/cache-jbosscache/src/main/java/org/hibernate/cache/jbc/BasicRegionAdapter.java
===================================================================
---
core/trunk/cache-jbosscache/src/main/java/org/hibernate/cache/jbc/BasicRegionAdapter.java 2009-07-07
18:33:23 UTC (rev 17026)
+++
core/trunk/cache-jbosscache/src/main/java/org/hibernate/cache/jbc/BasicRegionAdapter.java 2009-07-07
18:39:39 UTC (rev 17027)
@@ -342,6 +342,25 @@
}
}
+ 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 @@
size--;
}
return size;
- } catch (Exception e) {
+ }
+ catch ( CacheException ce ) {
+ throw ce;
+ }
+ catch (Exception e) {
throw new CacheException(e);
}
}
Added: core/trunk/core/src/main/java/org/hibernate/Cache.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/Cache.java (rev
0)
+++ core/trunk/core/src/main/java/org/hibernate/Cache.java 2009-07-07 18:39:39 UTC (rev
17027)
@@ -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();
+}
Modified: core/trunk/core/src/main/java/org/hibernate/SessionFactory.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/SessionFactory.java 2009-07-07 18:33:23
UTC (rev 17026)
+++ core/trunk/core/src/main/java/org/hibernate/SessionFactory.java 2009-07-07 18:39:39
UTC (rev 17027)
@@ -37,68 +37,81 @@
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.
- * @param interceptor a session-scoped interceptor
- * @return Session
+ *
+ * @return The created session.
*/
- public org.hibernate.classic.Session openSession(Connection connection, Interceptor
interceptor);
+ public org.hibernate.classic.Session openSession(Connection connection);
/**
- * Create database connection and open a <tt>Session</tt> on it.
+ * 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.
*
- * @return Session
- * @throws HibernateException
+ * @param connection a connection provided by the application.
+ * @param interceptor a session-scoped interceptor
+ *
+ * @return The created session.
*/
- public org.hibernate.classic.Session openSession() throws HibernateException;
+ public org.hibernate.classic.Session openSession(Connection connection, Interceptor
interceptor);
/**
* Obtains the current session. The definition of what exactly "current"
@@ -111,123 +124,243 @@
* 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
- * @since 3.0
+ * @param connection Connection provided by the application.
+ *
+ * @return The created stateless session.
*/
- public ClassMetadata getClassMetadata(String entityName) throws HibernateException;
+ public StatelessSession openStatelessSession(Connection connection);
/**
- * Get the <tt>CollectionMetadata</tt> associated with the named collection
role
+ * Retrieve the {@link ClassMetadata} associated with the given entity class.
*
- * @see org.hibernate.metadata.CollectionMetadata
+ * @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 CollectionMetadata getCollectionMetadata(String roleName) throws
HibernateException;
+ 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);
/**
- * Get all <tt>ClassMetadata</tt> as a <tt>Map</tt> from
entityname <tt>String</tt>
- * to metadata object
+ * Get the {@link CollectionMetadata} associated with the named collection role.
*
- * @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>
+ * @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 Map getAllClassMetadata() throws HibernateException;
+ public CollectionMetadata getCollectionMetadata(String roleName);
/**
- * Get all <tt>CollectionMetadata</tt> as a <tt>Map</tt> from
role name
- * to metadata object
+ * Retrieve the {@link ClassMetadata} for all mapped entities.
*
- * @see org.hibernate.metadata.CollectionMetadata
+ * @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();
+
+ /**
+ * Get the {@link CollectionMetadata} for all mapped collections
+ *
* @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.
Modified: core/trunk/core/src/main/java/org/hibernate/StatelessSession.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/StatelessSession.java 2009-07-07 18:33:23
UTC (rev 17026)
+++ core/trunk/core/src/main/java/org/hibernate/StatelessSession.java 2009-07-07 18:39:39
UTC (rev 17027)
@@ -28,20 +28,18 @@
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
*/
Modified: core/trunk/core/src/main/java/org/hibernate/cache/Region.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cache/Region.java 2009-07-07 18:33:23 UTC
(rev 17026)
+++ core/trunk/core/src/main/java/org/hibernate/cache/Region.java 2009-07-07 18:39:39 UTC
(rev 17027)
@@ -50,6 +50,20 @@
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.
*
* @return The number of bytes consumed by this region; -1 if unknown or
Modified:
core/trunk/core/src/main/java/org/hibernate/cache/impl/bridge/BaseRegionAdapter.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/cache/impl/bridge/BaseRegionAdapter.java 2009-07-07
18:33:23 UTC (rev 17026)
+++
core/trunk/core/src/main/java/org/hibernate/cache/impl/bridge/BaseRegionAdapter.java 2009-07-07
18:39:39 UTC (rev 17027)
@@ -57,6 +57,11 @@
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();
}
Modified: core/trunk/core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java 2009-07-07
18:33:23 UTC (rev 17026)
+++ core/trunk/core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java 2009-07-07
18:39:39 UTC (rev 17027)
@@ -60,6 +60,7 @@
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 @@
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,78 +956,185 @@
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) );
+ 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 );
}
- CacheKey cacheKey = new CacheKey( id, p.getIdentifierType(), p.getRootEntityName(),
EntityMode.POJO, this );
- p.getCacheAccessStrategy().evict( cacheKey );
}
- }
- 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() );
+ 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();
}
- p.getCacheAccessStrategy().evictAll();
}
- }
- 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) );
+ public void evictEntityRegions() {
+ Iterator entityNames = entityPersisters.keySet().iterator();
+ while ( entityNames.hasNext() ) {
+ evictEntityRegion( ( String ) entityNames.next() );
}
- CacheKey cacheKey = new CacheKey( id, p.getIdentifierType(), p.getRootEntityName(),
EntityMode.POJO, this );
- p.getCacheAccessStrategy().evict( cacheKey );
}
- }
- 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() );
+ 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 );
}
- p.getCacheAccessStrategy().evictAll();
}
- }
- 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) );
+ 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();
}
- CacheKey cacheKey = new CacheKey( id, p.getKeyType(), p.getRole(), EntityMode.POJO,
this );
- p.getCacheAccessStrategy().evict( cacheKey );
}
- }
- 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() );
+ public void evictCollectionRegions() {
+ Iterator collectionRoles = collectionPersisters.keySet().iterator();
+ while ( collectionRoles.hasNext() ) {
+ evictCollectionRegion( ( String ) collectionRoles.next() );
}
- p.getCacheAccessStrategy().evictAll();
}
+
+ 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 Type getReferencedPropertyType(String className, String propertyName)
- throws MappingException {
- return getEntityPersister(className).getPropertyType(propertyName);
+ public Cache getCache() {
+ return cacheAccess;
}
- public ConnectionProvider getConnectionProvider() {
- return settings.getConnectionProvider();
+ public void evictEntity(String entityName, Serializable id) throws HibernateException {
+ getCache().evictEntity( entityName, id );
}
+ public void evictEntity(String entityName) throws HibernateException {
+ getCache().evictEntityRegion( entityName );
+ }
+
+ public void evict(Class persistentClass, Serializable id) throws HibernateException {
+ getCache().evictEntity( persistentClass, id );
+ }
+
+ public void evict(Class persistentClass) throws HibernateException {
+ getCache().evictEntityRegion( persistentClass );
+ }
+
+ public void evictCollection(String roleName, Serializable id) throws HibernateException
{
+ getCache().evictCollection( roleName, id );
+ }
+
+ public void evictCollection(String roleName) throws HibernateException {
+ getCache().evictCollectionRegion( roleName );
+ }
+
+ public void evictQueries() throws HibernateException {
+ if ( settings.isQueryCacheEnabled() ) {
+ queryCache.clear();
+ }
+ }
+
+ public void evictQueries(String regionName) throws HibernateException {
+ getCache().evictQueryRegion( regionName );
+ }
+
public UpdateTimestampsCache getUpdateTimestampsCache() {
return updateTimestampsCache;
}
@@ -1070,28 +1187,6 @@
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 ) {
Modified:
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/EntityManagerFactoryImpl.java
===================================================================
---
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/EntityManagerFactoryImpl.java 2009-07-07
18:33:23 UTC (rev 17026)
+++
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/EntityManagerFactoryImpl.java 2009-07-07
18:39:39 UTC (rev 17027)
@@ -90,26 +90,23 @@
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();
}
}
}
Modified: core/trunk/jmx/src/main/java/org/hibernate/jmx/SessionFactoryStub.java
===================================================================
--- core/trunk/jmx/src/main/java/org/hibernate/jmx/SessionFactoryStub.java 2009-07-07
18:33:23 UTC (rev 17026)
+++ core/trunk/jmx/src/main/java/org/hibernate/jmx/SessionFactoryStub.java 2009-07-07
18:39:39 UTC (rev 17027)
@@ -19,6 +19,7 @@
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 @@
return false;
}
+ public Cache getCache() {
+ return getImpl().getCache();
+ }
+
public void evict(Class persistentClass, Serializable id)
throws HibernateException {
getImpl().evict(persistentClass, id);