com.oracle.coherence.hibernate.cache.CoherenceRegionFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of coherence-hibernate-cache-52 Show documentation
Show all versions of coherence-hibernate-cache-52 Show documentation
A Coherence-based implementation of the second-level cache SPI introduced in Hibernate 3.3.
/*
* Copyright (c) 2013, 2021, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* https://oss.oracle.com/licenses/upl.
*/
package com.oracle.coherence.hibernate.cache;
import com.oracle.coherence.hibernate.cache.region.CoherenceCollectionRegion;
import com.oracle.coherence.hibernate.cache.region.CoherenceEntityRegion;
import com.oracle.coherence.hibernate.cache.region.CoherenceNaturalIdRegion;
import com.oracle.coherence.hibernate.cache.region.CoherenceQueryResultsRegion;
import com.oracle.coherence.hibernate.cache.region.CoherenceTimestampsRegion;
import com.tangosol.net.CacheFactory;
import com.tangosol.net.ConfigurableCacheFactory;
import com.tangosol.net.NamedCache;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
import org.hibernate.cache.spi.CacheDataDescription;
import org.hibernate.cache.spi.CacheKeysFactory;
import org.hibernate.cache.spi.CollectionRegion;
import org.hibernate.cache.spi.EntityRegion;
import org.hibernate.cache.spi.NaturalIdRegion;
import org.hibernate.cache.spi.QueryResultsRegion;
import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.cache.spi.TimestampsRegion;
import org.hibernate.cache.spi.access.AccessType;
import org.hibernate.cfg.Environment;
import java.util.Properties;
/**
* A CoherenceRegionFactory is a factory for regions of Hibernate second-level cache implemented with Oracle Coherence.
*
* @author Randy Stafford
* @author Gunnar Hillert
*/
public class CoherenceRegionFactory
implements RegionFactory
{
// ---- Constants
/**
* The prefix of the names of all properties specific to this SPI implementation.
*/
public static final String PROPERTY_NAME_PREFIX = "com.oracle.coherence.hibernate.cache.";
/**
* The name of the property specifying the path to the Coherence cache configuration file.
*/
public static final String CACHE_CONFIG_FILE_PATH_PROPERTY_NAME = PROPERTY_NAME_PREFIX + "cache_config_file_path";
/**
* The name of the property specifying the severity level at which debug messages should be logged.
*/
public static final String DEBUG_MESSAGE_SEVERITY_LEVEL_PROPERTY_NAME = PROPERTY_NAME_PREFIX + "debug_message_severity_level";
/**
* The severity level at which debug messages should be logged by default.
*/
public static final int DEFAULT_DEBUG_MESSAGE_SEVERITY_LEVEL = 7;
/**
* The name of the property specifying whether to dump stack on debug messages.
*/
public static final String DUMP_STACK_ON_DEBUG_MESSAGE_PROPERTY_NAME = PROPERTY_NAME_PREFIX + "dump_stack_on_debug_message";
/**
* The default path to the cache configuration file.
*/
protected static final String DEFAULT_CACHE_CONFIG_FILE_PATH = "hibernate-second-level-cache-config.xml";
// ---- Fields
/**
* The severity level at which debug messages should be logged.
*/
private static int debugMessageSeverityLevel = DEFAULT_DEBUG_MESSAGE_SEVERITY_LEVEL;
/**
* A flag indicating whether to dump stack on debug messages.
*/
private static boolean dumpStackOnDebugMessage = false;
/**
* The ConfigurableCacheFactory used by this CoherenceRegionFactory.
*/
private ConfigurableCacheFactory cacheFactory;
/**
* The Hibernate settings object; may contain user-supplied "minimal puts" setting.
*/
private SessionFactoryOptions sessionFactoryOptions;
/**
* The Hibernate {@link CacheKeysFactory} to use. Hibernate ships with 2 {@link CacheKeysFactory}
* implementations:
*
*
* - {{@link org.hibernate.cache.internal.DefaultCacheKeysFactory}}
*
- {@link org.hibernate.cache.internal.SimpleCacheKeysFactory}
*
*
* If none is specified, then the {@link org.hibernate.cache.internal.DefaultCacheKeysFactory} is used.
*/
private CacheKeysFactory cacheKeysFactory;
// ---- Accessing
/**
* Returns the ConfigurableCacheFactory used by this CoherenceRegionFactory.
*
* @return the ConfigurableCacheFactory used by this CoherenceRegionFactory
*/
protected ConfigurableCacheFactory getConfigurableCacheFactory()
{
return cacheFactory;
}
/**
* Sets the ConfigurableCacheFactory used by this CoherenceRegionFactory.
*
* @param cacheFactory the ConfigurableCacheFactory used by this CoherenceRegionFactory
*/
protected void setConfigurableCacheFactory(ConfigurableCacheFactory cacheFactory)
{
this.cacheFactory = cacheFactory;
}
// ---- interface java.lang.Object
/**
* {@inheritDoc}
*/
@Override
public String toString()
{
StringBuilder stringBuilder = new StringBuilder(getClass().getName());
stringBuilder.append("(");
stringBuilder.append("cacheFactory=").append(cacheFactory);
stringBuilder.append(", sessionFactoryOptions=").append(sessionFactoryOptions);
stringBuilder.append(")");
return stringBuilder.toString();
}
// ---- API: logging support
/**
* Log the argument message with formatted arguments at debug severity.
*
* @param message the message to log
* @param arguments the arguments to the format specifiers in message
*/
public static void debugf(String message, Object ... arguments)
{
CacheFactory.log(String.format(message, arguments), debugMessageSeverityLevel);
if (dumpStackOnDebugMessage) Thread.dumpStack();
}
// ---- interface org.hibernate.cache.spi.RegionFactory
/**
* {@inheritDoc}
*/
@Override
public void start(SessionFactoryOptions options, Properties properties) throws CacheException
{
this.sessionFactoryOptions = options;
if (this.sessionFactoryOptions != null)
{
StrategySelector selector = this.sessionFactoryOptions.getServiceRegistry().getService(StrategySelector.class);
this.cacheKeysFactory = selector.resolveDefaultableStrategy(CacheKeysFactory.class,
properties.get(Environment.CACHE_KEYS_FACTORY), new DefaultCacheKeysFactory());
}
else
{
this.cacheKeysFactory = new DefaultCacheKeysFactory();
}
CacheFactory.ensureCluster();
String cacheConfigFilePath = (properties == null) ?
null :
properties.getProperty(CACHE_CONFIG_FILE_PATH_PROPERTY_NAME);
if (cacheConfigFilePath == null)
{
cacheConfigFilePath = System.getProperty(
CACHE_CONFIG_FILE_PATH_PROPERTY_NAME,
DEFAULT_CACHE_CONFIG_FILE_PATH);
}
ConfigurableCacheFactory factory = CacheFactory.getCacheFactoryBuilder().getConfigurableCacheFactory(
cacheConfigFilePath,
getClass().getClassLoader());
setConfigurableCacheFactory(factory);
debugMessageSeverityLevel = Integer.getInteger(DEBUG_MESSAGE_SEVERITY_LEVEL_PROPERTY_NAME, DEFAULT_DEBUG_MESSAGE_SEVERITY_LEVEL);
dumpStackOnDebugMessage = Boolean.getBoolean(DUMP_STACK_ON_DEBUG_MESSAGE_PROPERTY_NAME);
debugf("%s.start(%s, %s)", this, options, properties);
}
/**
* {@inheritDoc}
*/
@Override
public void stop()
{
// Note: Gavin's original CacheProvider called
// CacheFactory.shutdown() but this causes problems when
// multiple Hibernate SessionFactory instances are used in an application.
// It also causes problems if the application is using
// Coherence directly and has dependencies on it beyond
// the lifespan of the Hibernate SessionFactory.
//
// In particular, it is difficult to determine which resources
// (caches, cache services, cluster service) are shared.
//
// Since Coherence 3.5.1, we should release the factory
CacheFactory.getCacheFactoryBuilder().release(getConfigurableCacheFactory());
setConfigurableCacheFactory(null);
}
/**
* {@inheritDoc}
*/
@Override
public boolean isMinimalPutsEnabledByDefault()
{
return true;
}
/**
* {@inheritDoc}
*/
@Override
public AccessType getDefaultAccessType()
{
return AccessType.READ_WRITE;
}
/**
* {@inheritDoc}
*/
@Override
public long nextTimestamp()
{
// See also related methods in CoherenceRegion ... there are fundamental
// flaws with this approach (in the Hibernate code) no matter what we
// do, so the goal is to minimize problems; note that we use the static
// CacheFactory for this particular call rather than our own since
// they both share a cluster service (and all we care about is time).
return CacheFactory.ensureCluster().getTimeMillis();
}
/**
* {@inheritDoc}
*/
@Override
public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata)
throws CacheException
{
return new CoherenceEntityRegion(ensureNamedCache(regionName), sessionFactoryOptions, properties, metadata, cacheKeysFactory);
}
/**
* {@inheritDoc}
*/
@Override
public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata)
throws CacheException
{
return new CoherenceNaturalIdRegion(ensureNamedCache(regionName), sessionFactoryOptions, properties, metadata, cacheKeysFactory);
}
/**
* {@inheritDoc}
*/
@Override
public CollectionRegion buildCollectionRegion(String regionName, Properties properties, CacheDataDescription metadata)
throws CacheException
{
return new CoherenceCollectionRegion(ensureNamedCache(regionName), sessionFactoryOptions, properties, metadata, cacheKeysFactory);
}
/**
* {@inheritDoc}
*/
@Override
public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException
{
return new CoherenceQueryResultsRegion(ensureNamedCache(regionName), properties);
}
/**
* {@inheritDoc}
*/
@Override
public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException
{
return new CoherenceTimestampsRegion(ensureNamedCache(regionName), properties);
}
// ---- Internal
/**
* Ensure the initialization of a NamedCache of the argument name.
*
* @param cacheName the name of the NamedCache whose initialization to ensure
*
* @return a NamedCache for the argument name
*/
protected NamedCache ensureNamedCache(String cacheName)
{
// We intentionally avoid passing in a ClassLoader (as we can't do any
// more than the default Coherence codepath does); however, this
// method is provided so that customers may easily subclass.
return getConfigurableCacheFactory().ensureCache(cacheName, null);
}
}