added support for Hibernate 3.3 RegionFactory cache SPI to LocalSessionFactoryBean (SPR-6387)
This commit is contained in:
parent
f2477c4bf5
commit
eb0b4f0cbd
|
|
@ -29,7 +29,7 @@ import org.hibernate.cache.CacheProvider;
|
|||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5.1
|
||||
* @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setCacheProvider
|
||||
* @see LocalSessionFactoryBean#setCacheProvider
|
||||
*/
|
||||
public class LocalCacheProviderProxy implements CacheProvider {
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate3;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.cache.CacheDataDescription;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.CollectionRegion;
|
||||
import org.hibernate.cache.EntityRegion;
|
||||
import org.hibernate.cache.QueryResultsRegion;
|
||||
import org.hibernate.cache.RegionFactory;
|
||||
import org.hibernate.cache.TimestampsRegion;
|
||||
import org.hibernate.cfg.Settings;
|
||||
|
||||
/**
|
||||
* Proxy for a Hibernate RegionFactory, delegating to a Spring-managed
|
||||
* RegionFactory instance, determined by LocalSessionFactoryBean's
|
||||
* "cacheRegionFactory" property.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see LocalSessionFactoryBean#setCacheRegionFactory
|
||||
*/
|
||||
public class LocalRegionFactoryProxy implements RegionFactory {
|
||||
|
||||
private final RegionFactory regionFactory;
|
||||
|
||||
|
||||
public LocalRegionFactoryProxy() {
|
||||
RegionFactory rf = LocalSessionFactoryBean.getConfigTimeRegionFactory();
|
||||
// absolutely needs thread-bound RegionFactory to initialize
|
||||
if (rf == null) {
|
||||
throw new IllegalStateException("No Hibernate RegionFactory found - " +
|
||||
"'cacheRegionFactory' property must be set on LocalSessionFactoryBean");
|
||||
}
|
||||
this.regionFactory = rf;
|
||||
}
|
||||
|
||||
|
||||
public void start(Settings settings, Properties properties) throws CacheException {
|
||||
this.regionFactory.start(settings, properties);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
this.regionFactory.stop();
|
||||
}
|
||||
|
||||
public boolean isMinimalPutsEnabledByDefault() {
|
||||
return this.regionFactory.isMinimalPutsEnabledByDefault();
|
||||
}
|
||||
|
||||
public long nextTimestamp() {
|
||||
return this.regionFactory.nextTimestamp();
|
||||
}
|
||||
|
||||
public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata)
|
||||
throws CacheException {
|
||||
|
||||
return this.regionFactory.buildEntityRegion(regionName, properties, metadata);
|
||||
}
|
||||
|
||||
public CollectionRegion buildCollectionRegion(String regionName, Properties properties,
|
||||
CacheDataDescription metadata) throws CacheException {
|
||||
|
||||
return this.regionFactory.buildCollectionRegion(regionName, properties, metadata);
|
||||
}
|
||||
|
||||
public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties)
|
||||
throws CacheException {
|
||||
|
||||
return this.regionFactory.buildQueryResultsRegion(regionName, properties);
|
||||
}
|
||||
|
||||
public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties)
|
||||
throws CacheException {
|
||||
|
||||
return this.regionFactory.buildTimestampsRegion(regionName, properties);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -34,12 +34,14 @@ import org.hibernate.Interceptor;
|
|||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.cache.CacheProvider;
|
||||
import org.hibernate.cache.RegionFactory;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.FilterDefinition;
|
||||
import org.hibernate.event.EventListeners;
|
||||
import org.hibernate.jdbc.Work;
|
||||
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
|
||||
import org.hibernate.transaction.JTATransactionFactory;
|
||||
|
||||
|
|
@ -88,7 +90,7 @@ import org.springframework.util.StringUtils;
|
|||
* {@link org.springframework.orm.hibernate3.support.OpenSessionInViewFilter} /
|
||||
* {@link org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor}.
|
||||
*
|
||||
* <p><b>Requires Hibernate 3.2 or later.</b> Note that this factory will use
|
||||
* <p><b>Requires Hibernate 3.3 or later.</b> Note that this factory will use
|
||||
* "on_close" as default Hibernate connection release mode, unless in the
|
||||
* case of a "jtaTransactionManager" specified, for the reason that
|
||||
* this is appropriate for most Spring-based applications (in particular when
|
||||
|
|
@ -113,6 +115,9 @@ public class LocalSessionFactoryBean extends AbstractSessionFactoryBean implemen
|
|||
private static final ThreadLocal<TransactionManager> configTimeTransactionManagerHolder =
|
||||
new ThreadLocal<TransactionManager>();
|
||||
|
||||
private static final ThreadLocal<RegionFactory> configTimeRegionFactoryHolder =
|
||||
new ThreadLocal<RegionFactory>();
|
||||
|
||||
private static final ThreadLocal<CacheProvider> configTimeCacheProviderHolder =
|
||||
new ThreadLocal<CacheProvider>();
|
||||
|
||||
|
|
@ -145,6 +150,18 @@ public class LocalSessionFactoryBean extends AbstractSessionFactoryBean implemen
|
|||
return configTimeTransactionManagerHolder.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the RegionFactory for the currently configured Hibernate SessionFactory,
|
||||
* to be used by LocalRegionFactoryProxy.
|
||||
* <p>This instance will be set before initialization of the corresponding
|
||||
* SessionFactory, and reset immediately afterwards. It is thus only available
|
||||
* during configuration.
|
||||
* @see #setCacheRegionFactory
|
||||
*/
|
||||
public static RegionFactory getConfigTimeRegionFactory() {
|
||||
return configTimeRegionFactoryHolder.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CacheProvider for the currently configured Hibernate SessionFactory,
|
||||
* to be used by LocalCacheProviderProxy.
|
||||
|
|
@ -173,7 +190,7 @@ public class LocalSessionFactoryBean extends AbstractSessionFactoryBean implemen
|
|||
}
|
||||
|
||||
|
||||
private Class configurationClass = Configuration.class;
|
||||
private Class<? extends Configuration> configurationClass = Configuration.class;
|
||||
|
||||
private Resource[] configLocations;
|
||||
|
||||
|
|
@ -191,6 +208,8 @@ public class LocalSessionFactoryBean extends AbstractSessionFactoryBean implemen
|
|||
|
||||
private TransactionManager jtaTransactionManager;
|
||||
|
||||
private RegionFactory cacheRegionFactory;
|
||||
|
||||
private CacheProvider cacheProvider;
|
||||
|
||||
private LobHandler lobHandler;
|
||||
|
|
@ -231,12 +250,13 @@ public class LocalSessionFactoryBean extends AbstractSessionFactoryBean implemen
|
|||
* @see org.hibernate.cfg.Configuration
|
||||
* @see org.hibernate.cfg.AnnotationConfiguration
|
||||
*/
|
||||
public void setConfigurationClass(Class configurationClass) {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setConfigurationClass(Class<?> configurationClass) {
|
||||
if (configurationClass == null || !Configuration.class.isAssignableFrom(configurationClass)) {
|
||||
throw new IllegalArgumentException(
|
||||
"configurationClass must be assignable to [org.hibernate.cfg.Configuration]");
|
||||
"'configurationClass' must be assignable to [org.hibernate.cfg.Configuration]");
|
||||
}
|
||||
this.configurationClass = configurationClass;
|
||||
this.configurationClass = (Class<? extends Configuration>) configurationClass;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -359,13 +379,29 @@ public class LocalSessionFactoryBean extends AbstractSessionFactoryBean implemen
|
|||
this.jtaTransactionManager = jtaTransactionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Hibernate RegionFactory to use for the SessionFactory.
|
||||
* Allows for using a Spring-managed RegionFactory instance.
|
||||
* <p>As of Hibernate 3.3, this is the preferred mechanism for configuring
|
||||
* caches, superseding the {@link #setCacheProvider CacheProvider SPI}.
|
||||
* <p>Note: If this is set, the Hibernate settings should not define a
|
||||
* cache provider to avoid meaningless double configuration.
|
||||
* @see LocalRegionFactoryProxy
|
||||
*/
|
||||
public void setCacheRegionFactory(RegionFactory cacheRegionFactory) {
|
||||
this.cacheRegionFactory = cacheRegionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Hibernate CacheProvider to use for the SessionFactory.
|
||||
* Allows for using a Spring-managed CacheProvider instance.
|
||||
* <p>Note: If this is set, the Hibernate settings should not define a
|
||||
* cache provider to avoid meaningless double configuration.
|
||||
* @see LocalCacheProviderProxy
|
||||
* @deprecated as of Spring 3.0, following Hibernate 3.3's deprecation
|
||||
* of the CacheProvider SPI
|
||||
* @see #setCacheRegionFactory
|
||||
*/
|
||||
@Deprecated
|
||||
public void setCacheProvider(CacheProvider cacheProvider) {
|
||||
this.cacheProvider = cacheProvider;
|
||||
}
|
||||
|
|
@ -523,6 +559,10 @@ public class LocalSessionFactoryBean extends AbstractSessionFactoryBean implemen
|
|||
// Make Spring-provided JTA TransactionManager available.
|
||||
configTimeTransactionManagerHolder.set(this.jtaTransactionManager);
|
||||
}
|
||||
if (this.cacheRegionFactory != null) {
|
||||
// Make Spring-provided Hibernate RegionFactory available.
|
||||
configTimeRegionFactoryHolder.set(this.cacheRegionFactory);
|
||||
}
|
||||
if (this.cacheProvider != null) {
|
||||
// Make Spring-provided Hibernate CacheProvider available.
|
||||
configTimeCacheProviderHolder.set(this.cacheProvider);
|
||||
|
|
@ -622,7 +662,11 @@ public class LocalSessionFactoryBean extends AbstractSessionFactoryBean implemen
|
|||
config.setProperty(Environment.CONNECTION_PROVIDER, providerClass.getName());
|
||||
}
|
||||
|
||||
if (this.cacheProvider != null) {
|
||||
if (this.cacheRegionFactory != null) {
|
||||
// Expose Spring-provided Hibernate RegionFactory.
|
||||
config.setProperty(Environment.CACHE_REGION_FACTORY, LocalRegionFactoryProxy.class.getName());
|
||||
}
|
||||
else if (this.cacheProvider != null) {
|
||||
// Expose Spring-provided Hibernate CacheProvider.
|
||||
config.setProperty(Environment.CACHE_PROVIDER, LocalCacheProviderProxy.class.getName());
|
||||
}
|
||||
|
|
@ -733,19 +777,18 @@ public class LocalSessionFactoryBean extends AbstractSessionFactoryBean implemen
|
|||
|
||||
finally {
|
||||
if (dataSource != null) {
|
||||
// Reset DataSource holder.
|
||||
configTimeDataSourceHolder.set(null);
|
||||
}
|
||||
if (this.jtaTransactionManager != null) {
|
||||
// Reset TransactionManager holder.
|
||||
configTimeTransactionManagerHolder.set(null);
|
||||
}
|
||||
if (this.cacheRegionFactory != null) {
|
||||
configTimeCacheProviderHolder.set(null);
|
||||
}
|
||||
if (this.cacheProvider != null) {
|
||||
// Reset CacheProvider holder.
|
||||
configTimeCacheProviderHolder.set(null);
|
||||
}
|
||||
if (this.lobHandler != null) {
|
||||
// Reset LobHandler holder.
|
||||
configTimeLobHandlerHolder.set(null);
|
||||
}
|
||||
if (overrideClassLoader) {
|
||||
|
|
@ -768,7 +811,7 @@ public class LocalSessionFactoryBean extends AbstractSessionFactoryBean implemen
|
|||
* @see org.hibernate.cfg.Configuration#Configuration()
|
||||
*/
|
||||
protected Configuration newConfiguration() throws HibernateException {
|
||||
return (Configuration) BeanUtils.instantiateClass(this.configurationClass);
|
||||
return BeanUtils.instantiateClass(this.configurationClass);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -891,12 +934,15 @@ public class LocalSessionFactoryBean extends AbstractSessionFactoryBean implemen
|
|||
logger.info("Dropping database schema for Hibernate SessionFactory");
|
||||
HibernateTemplate hibernateTemplate = new HibernateTemplate(getSessionFactory());
|
||||
hibernateTemplate.execute(
|
||||
new HibernateCallback() {
|
||||
new HibernateCallback<Object>() {
|
||||
public Object doInHibernate(Session session) throws HibernateException, SQLException {
|
||||
Connection con = session.connection();
|
||||
session.doWork(new Work() {
|
||||
public void execute(Connection connection) throws SQLException {
|
||||
Dialect dialect = Dialect.getDialect(getConfiguration().getProperties());
|
||||
String[] sql = getConfiguration().generateDropSchemaScript(dialect);
|
||||
executeSchemaScript(con, sql);
|
||||
executeSchemaScript(connection, sql);
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -920,12 +966,15 @@ public class LocalSessionFactoryBean extends AbstractSessionFactoryBean implemen
|
|||
logger.info("Creating database schema for Hibernate SessionFactory");
|
||||
HibernateTemplate hibernateTemplate = new HibernateTemplate(getSessionFactory());
|
||||
hibernateTemplate.execute(
|
||||
new HibernateCallback() {
|
||||
new HibernateCallback<Object>() {
|
||||
public Object doInHibernate(Session session) throws HibernateException, SQLException {
|
||||
Connection con = session.connection();
|
||||
session.doWork(new Work() {
|
||||
public void execute(Connection connection) throws SQLException {
|
||||
Dialect dialect = Dialect.getDialect(getConfiguration().getProperties());
|
||||
String[] sql = getConfiguration().generateSchemaCreationScript(dialect);
|
||||
executeSchemaScript(con, sql);
|
||||
executeSchemaScript(connection, sql);
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -952,13 +1001,16 @@ public class LocalSessionFactoryBean extends AbstractSessionFactoryBean implemen
|
|||
HibernateTemplate hibernateTemplate = new HibernateTemplate(getSessionFactory());
|
||||
hibernateTemplate.setFlushMode(HibernateTemplate.FLUSH_NEVER);
|
||||
hibernateTemplate.execute(
|
||||
new HibernateCallback() {
|
||||
new HibernateCallback<Object>() {
|
||||
public Object doInHibernate(Session session) throws HibernateException, SQLException {
|
||||
Connection con = session.connection();
|
||||
session.doWork(new Work() {
|
||||
public void execute(Connection connection) throws SQLException {
|
||||
Dialect dialect = Dialect.getDialect(getConfiguration().getProperties());
|
||||
DatabaseMetadata metadata = new DatabaseMetadata(con, dialect);
|
||||
DatabaseMetadata metadata = new DatabaseMetadata(connection, dialect);
|
||||
String[] sql = getConfiguration().generateSchemaUpdateScript(dialect, metadata);
|
||||
executeSchemaScript(con, sql);
|
||||
executeSchemaScript(connection, sql);
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
|
@ -39,6 +38,8 @@ import org.hibernate.Interceptor;
|
|||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.cache.CacheProvider;
|
||||
import org.hibernate.cache.NoCacheProvider;
|
||||
import org.hibernate.cache.RegionFactory;
|
||||
import org.hibernate.cache.impl.NoCachingRegionFactory;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.cfg.ImprovedNamingStrategy;
|
||||
|
|
@ -79,7 +80,6 @@ public class LocalSessionFactoryBeanTests extends TestCase {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected SessionFactory newSessionFactory(Configuration config) {
|
||||
assertEquals(LocalDataSourceConnectionProvider.class.getName(),
|
||||
config.getProperty(Environment.CONNECTION_PROVIDER));
|
||||
|
|
@ -94,6 +94,37 @@ public class LocalSessionFactoryBeanTests extends TestCase {
|
|||
assertEquals("newSessionFactory", invocations.get(0));
|
||||
}
|
||||
|
||||
public void testLocalSessionFactoryBeanWithCacheRegionFactory() throws Exception {
|
||||
final RegionFactory regionFactory = new NoCachingRegionFactory(null);
|
||||
final List invocations = new ArrayList();
|
||||
LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() {
|
||||
protected Configuration newConfiguration() {
|
||||
return new Configuration() {
|
||||
public Configuration addInputStream(InputStream is) {
|
||||
try {
|
||||
is.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
}
|
||||
invocations.add("addResource");
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
protected SessionFactory newSessionFactory(Configuration config) {
|
||||
assertEquals(LocalRegionFactoryProxy.class.getName(),
|
||||
config.getProperty(Environment.CACHE_REGION_FACTORY));
|
||||
assertSame(regionFactory, LocalSessionFactoryBean.getConfigTimeRegionFactory());
|
||||
invocations.add("newSessionFactory");
|
||||
return null;
|
||||
}
|
||||
};
|
||||
sfb.setCacheRegionFactory(regionFactory);
|
||||
sfb.afterPropertiesSet();
|
||||
assertTrue(sfb.getConfiguration() != null);
|
||||
assertEquals("newSessionFactory", invocations.get(0));
|
||||
}
|
||||
|
||||
public void testLocalSessionFactoryBeanWithCacheProvider() throws Exception {
|
||||
final CacheProvider cacheProvider = new NoCacheProvider();
|
||||
final List invocations = new ArrayList();
|
||||
|
|
|
|||
Loading…
Reference in New Issue