HHH-9843 Use optimized cache key implementation in Infinispan 2LC
* When multi-tenancy is not used, entity's @Id can be used as key to the cache * Added Type to CacheDataDescription (in SPI), later used for container key equivalence * Introduced CacheKeysFactory to SPI * Pending puts cache is now per region - this is necessary as we need to use custom key equivalence
This commit is contained in:
parent
bcf38a02b5
commit
2f1b67b03f
|
@ -11,6 +11,7 @@ import java.util.Comparator;
|
|||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.VersionType;
|
||||
|
||||
/**
|
||||
|
@ -22,19 +23,21 @@ public class CacheDataDescriptionImpl implements CacheDataDescription {
|
|||
private final boolean mutable;
|
||||
private final boolean versioned;
|
||||
private final Comparator versionComparator;
|
||||
private final Type keyType;
|
||||
|
||||
/**
|
||||
* Constructs a CacheDataDescriptionImpl instance. Generally speaking, code should use one of the
|
||||
* overloaded {@link #decode} methods rather than direct instantiation.
|
||||
*
|
||||
* @param mutable Is the described data mutable?
|
||||
* @param versioned Is the described data versioned?
|
||||
* @param versionComparator The described data's version value comparator (if versioned).
|
||||
* @param keyType
|
||||
*/
|
||||
public CacheDataDescriptionImpl(boolean mutable, boolean versioned, Comparator versionComparator) {
|
||||
public CacheDataDescriptionImpl(boolean mutable, boolean versioned, Comparator versionComparator, Type keyType) {
|
||||
this.mutable = mutable;
|
||||
this.versioned = versioned;
|
||||
this.versionComparator = versionComparator;
|
||||
this.keyType = keyType;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -52,6 +55,11 @@ public class CacheDataDescriptionImpl implements CacheDataDescription {
|
|||
return versionComparator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getKeyType() {
|
||||
return keyType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a CacheDataDescriptionImpl from the mapping model of an entity class.
|
||||
*
|
||||
|
@ -65,8 +73,8 @@ public class CacheDataDescriptionImpl implements CacheDataDescription {
|
|||
model.isVersioned(),
|
||||
model.isVersioned()
|
||||
? ( (VersionType) model.getVersion().getType() ).getComparator()
|
||||
: null
|
||||
);
|
||||
: null,
|
||||
model.getIdentifierProperty().getType());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,8 +90,8 @@ public class CacheDataDescriptionImpl implements CacheDataDescription {
|
|||
model.getOwner().isVersioned(),
|
||||
model.getOwner().isVersioned()
|
||||
? ( (VersionType) model.getOwner().getVersion().getType() ).getComparator()
|
||||
: null
|
||||
);
|
||||
: null,
|
||||
model.getKey().getType());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.cache.internal;
|
||||
|
||||
import org.hibernate.cache.spi.CacheKeysFactory;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
|
@ -48,7 +49,7 @@ public class DefaultCacheKeysFactory {
|
|||
}
|
||||
|
||||
public static Object createNaturalIdKey(Object[] naturalIdValues, EntityPersister persister, SessionImplementor session) {
|
||||
return new OldNaturalIdCacheKey( naturalIdValues, persister, session );
|
||||
return new OldNaturalIdCacheKey( naturalIdValues, persister.getPropertyTypes(), persister.getNaturalIdentifierProperties(), persister.getRootEntityName(), session );
|
||||
}
|
||||
|
||||
public static Object getEntityId(Object cacheKey) {
|
||||
|
@ -62,4 +63,36 @@ public class DefaultCacheKeysFactory {
|
|||
public static Object[] getNaturalIdValues(Object cacheKey) {
|
||||
return ((OldNaturalIdCacheKey) cacheKey).getNaturalIdValues();
|
||||
}
|
||||
|
||||
public static CacheKeysFactory INSTANCE = new CacheKeysFactory() {
|
||||
@Override
|
||||
public Object createCollectionKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) {
|
||||
return DefaultCacheKeysFactory.createCollectionKey(id, persister, factory, tenantIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createEntityKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) {
|
||||
return DefaultCacheKeysFactory.createEntityKey(id, persister, factory, tenantIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createNaturalIdKey(Object[] naturalIdValues, EntityPersister persister, SessionImplementor session) {
|
||||
return DefaultCacheKeysFactory.createNaturalIdKey(naturalIdValues, persister, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getEntityId(Object cacheKey) {
|
||||
return DefaultCacheKeysFactory.getEntityId(cacheKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCollectionId(Object cacheKey) {
|
||||
return DefaultCacheKeysFactory.getCollectionId(cacheKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getNaturalIdValues(Object cacheKey) {
|
||||
return DefaultCacheKeysFactory.getNaturalIdValues(cacheKey);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.internal.util.ValueHolder;
|
||||
import org.hibernate.internal.util.compare.EqualsHelper;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.type.EntityType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
|
@ -41,24 +40,22 @@ public class OldNaturalIdCacheKey implements Serializable {
|
|||
|
||||
/**
|
||||
* Construct a new key for a caching natural identifier resolutions into the second level cache.
|
||||
*
|
||||
* @param naturalIdValues The naturalIdValues associated with the cached data
|
||||
* @param persister The persister for the entity
|
||||
* @param propertyTypes
|
||||
* @param naturalIdPropertyIndexes
|
||||
* @param session The originating session
|
||||
*/
|
||||
public OldNaturalIdCacheKey(
|
||||
final Object[] naturalIdValues,
|
||||
final EntityPersister persister,
|
||||
Type[] propertyTypes, int[] naturalIdPropertyIndexes, final String entityName,
|
||||
final SessionImplementor session) {
|
||||
|
||||
this.entityName = persister.getRootEntityName();
|
||||
this.entityName = entityName;
|
||||
this.tenantId = session.getTenantIdentifier();
|
||||
|
||||
this.naturalIdValues = new Serializable[naturalIdValues.length];
|
||||
|
||||
final SessionFactoryImplementor factory = session.getFactory();
|
||||
final int[] naturalIdPropertyIndexes = persister.getNaturalIdentifierProperties();
|
||||
final Type[] propertyTypes = persister.getPropertyTypes();
|
||||
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
|
@ -93,7 +90,7 @@ public class OldNaturalIdCacheKey implements Serializable {
|
|||
public String initialize() {
|
||||
//Complex toString is needed as naturalIds for entities are not simply based on a single value like primary keys
|
||||
//the only same way to differentiate the keys is to included the disassembled values in the string.
|
||||
final StringBuilder toStringBuilder = new StringBuilder( entityName ).append( "##NaturalId[" );
|
||||
final StringBuilder toStringBuilder = new StringBuilder().append( entityName ).append( "##NaturalId[" );
|
||||
for ( int i = 0; i < naturalIdValues.length; i++ ) {
|
||||
toStringBuilder.append( naturalIdValues[i] );
|
||||
if ( i + 1 < naturalIdValues.length ) {
|
||||
|
|
54
hibernate-core/src/main/java/org/hibernate/cache/internal/SimpleCacheKeysFactory.java
vendored
Normal file
54
hibernate-core/src/main/java/org/hibernate/cache/internal/SimpleCacheKeysFactory.java
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.cache.internal;
|
||||
|
||||
import org.hibernate.cache.spi.CacheKeysFactory;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
/**
|
||||
* Factory that does not fill in the entityName or role
|
||||
*
|
||||
* @author Radim Vansa <rvansa@redhat.com>
|
||||
*/
|
||||
public class SimpleCacheKeysFactory implements CacheKeysFactory {
|
||||
|
||||
public static CacheKeysFactory INSTANCE = new SimpleCacheKeysFactory();
|
||||
|
||||
@Override
|
||||
public Object createCollectionKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createEntityKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createNaturalIdKey(Object[] naturalIdValues, EntityPersister persister, SessionImplementor session) {
|
||||
// natural ids always need to be wrapped
|
||||
return new OldNaturalIdCacheKey(naturalIdValues, persister.getPropertyTypes(), persister.getNaturalIdentifierProperties(), null, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getEntityId(Object cacheKey) {
|
||||
return cacheKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCollectionId(Object cacheKey) {
|
||||
return cacheKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getNaturalIdValues(Object cacheKey) {
|
||||
return ((OldNaturalIdCacheKey) cacheKey).getNaturalIdValues();
|
||||
}
|
||||
}
|
|
@ -8,6 +8,8 @@ package org.hibernate.cache.spi;
|
|||
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Describes attributes regarding the type of data to be cached.
|
||||
*
|
||||
|
@ -37,4 +39,10 @@ public interface CacheDataDescription {
|
|||
* @return The comparator for versions, or {@code null}
|
||||
*/
|
||||
public Comparator getVersionComparator();
|
||||
|
||||
/**
|
||||
* @return Type of the key that will be used as the key in the cache, or {@code null} if the natural comparison
|
||||
* ({@link Object#hashCode()} and {@link Object#equals(Object)} methods should be used.
|
||||
*/
|
||||
Type getKeyType();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.cache.spi;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
/**
|
||||
* @author Radim Vansa <rvansa@redhat.com>
|
||||
*/
|
||||
public interface CacheKeysFactory {
|
||||
Object createCollectionKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier);
|
||||
|
||||
Object createEntityKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier);
|
||||
|
||||
Object createNaturalIdKey(Object[] naturalIdValues, EntityPersister persister, SessionImplementor session);
|
||||
|
||||
Object getEntityId(Object cacheKey);
|
||||
|
||||
Object getCollectionId(Object cacheKey);
|
||||
|
||||
Object[] getNaturalIdValues(Object cacheKey);
|
||||
}
|
|
@ -20,6 +20,7 @@ import java.util.Set;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.MultiTenancyStrategy;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.infinispan.collection.CollectionRegionImpl;
|
||||
|
@ -33,7 +34,10 @@ import org.hibernate.cache.infinispan.timestamp.TimestampsRegionImpl;
|
|||
import org.hibernate.cache.infinispan.tm.HibernateTransactionManagerLookup;
|
||||
import org.hibernate.cache.infinispan.util.CacheCommandFactory;
|
||||
import org.hibernate.cache.infinispan.util.Caches;
|
||||
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||
import org.hibernate.cache.internal.SimpleCacheKeysFactory;
|
||||
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;
|
||||
|
@ -217,6 +221,7 @@ public class InfinispanRegionFactory implements RegionFactory {
|
|||
private org.infinispan.transaction.lookup.TransactionManagerLookup transactionManagerlookup;
|
||||
|
||||
private List<String> regionNames = new ArrayList<String>();
|
||||
private SessionFactoryOptions settings;
|
||||
|
||||
/**
|
||||
* Create a new instance using the default configuration.
|
||||
|
@ -241,8 +246,8 @@ public class InfinispanRegionFactory implements RegionFactory {
|
|||
if ( log.isDebugEnabled() ) {
|
||||
log.debug( "Building collection cache region [" + regionName + "]" );
|
||||
}
|
||||
final AdvancedCache cache = getCache( regionName, COLLECTION_KEY, properties );
|
||||
final CollectionRegionImpl region = new CollectionRegionImpl( cache, regionName, metadata, this );
|
||||
final AdvancedCache cache = getCache( regionName, COLLECTION_KEY, properties, metadata);
|
||||
final CollectionRegionImpl region = new CollectionRegionImpl( cache, regionName, metadata, this, buildCacheKeysFactory() );
|
||||
startRegion( region, regionName );
|
||||
return region;
|
||||
}
|
||||
|
@ -258,8 +263,8 @@ public class InfinispanRegionFactory implements RegionFactory {
|
|||
metadata.isVersioned()
|
||||
);
|
||||
}
|
||||
final AdvancedCache cache = getCache( regionName, metadata.isMutable() ? ENTITY_KEY : IMMUTABLE_ENTITY_KEY, properties );
|
||||
final EntityRegionImpl region = new EntityRegionImpl( cache, regionName, metadata, this );
|
||||
final AdvancedCache cache = getCache( regionName, metadata.isMutable() ? ENTITY_KEY : IMMUTABLE_ENTITY_KEY, properties, metadata );
|
||||
final EntityRegionImpl region = new EntityRegionImpl( cache, regionName, metadata, this, buildCacheKeysFactory() );
|
||||
startRegion( region, regionName );
|
||||
return region;
|
||||
}
|
||||
|
@ -268,10 +273,10 @@ public class InfinispanRegionFactory implements RegionFactory {
|
|||
public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata)
|
||||
throws CacheException {
|
||||
if ( log.isDebugEnabled() ) {
|
||||
log.debug( "Building natural id cache region [" + regionName + "]" );
|
||||
log.debug("Building natural id cache region [" + regionName + "]");
|
||||
}
|
||||
final AdvancedCache cache = getCache( regionName, NATURAL_ID_KEY, properties );
|
||||
final NaturalIdRegionImpl region = new NaturalIdRegionImpl( cache, regionName, metadata, this );
|
||||
final AdvancedCache cache = getCache( regionName, NATURAL_ID_KEY, properties, metadata);
|
||||
final NaturalIdRegionImpl region = new NaturalIdRegionImpl( cache, regionName, metadata, this, buildCacheKeysFactory());
|
||||
startRegion( region, regionName );
|
||||
return region;
|
||||
}
|
||||
|
@ -288,7 +293,7 @@ public class InfinispanRegionFactory implements RegionFactory {
|
|||
cacheName = regionName;
|
||||
}
|
||||
|
||||
final AdvancedCache cache = getCache( cacheName, QUERY_KEY, properties );
|
||||
final AdvancedCache cache = getCache( cacheName, QUERY_KEY, properties, null);
|
||||
final QueryResultsRegionImpl region = new QueryResultsRegionImpl( cache, regionName, this );
|
||||
startRegion( region, regionName );
|
||||
return region;
|
||||
|
@ -300,7 +305,7 @@ public class InfinispanRegionFactory implements RegionFactory {
|
|||
if ( log.isDebugEnabled() ) {
|
||||
log.debug( "Building timestamps cache region [" + regionName + "]" );
|
||||
}
|
||||
final AdvancedCache cache = getCache( regionName, TIMESTAMPS_KEY, properties );
|
||||
final AdvancedCache cache = getCache( regionName, TIMESTAMPS_KEY, properties, null);
|
||||
final TimestampsRegionImpl region = createTimestampsRegion( cache, regionName );
|
||||
startRegion( region, regionName );
|
||||
return region;
|
||||
|
@ -308,7 +313,7 @@ public class InfinispanRegionFactory implements RegionFactory {
|
|||
|
||||
protected TimestampsRegionImpl createTimestampsRegion(
|
||||
AdvancedCache cache, String regionName) {
|
||||
if ( Caches.isClustered( cache ) ) {
|
||||
if ( Caches.isClustered(cache) ) {
|
||||
return new ClusteredTimestampsRegionImpl( cache, regionName, this );
|
||||
}
|
||||
else {
|
||||
|
@ -316,6 +321,15 @@ public class InfinispanRegionFactory implements RegionFactory {
|
|||
}
|
||||
}
|
||||
|
||||
private CacheKeysFactory buildCacheKeysFactory() {
|
||||
if (settings.getMultiTenancyStrategy() != MultiTenancyStrategy.NONE) {
|
||||
return DefaultCacheKeysFactory.INSTANCE;
|
||||
}
|
||||
else {
|
||||
return SimpleCacheKeysFactory.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMinimalPutsEnabledByDefault() {
|
||||
return true;
|
||||
|
@ -345,6 +359,7 @@ public class InfinispanRegionFactory implements RegionFactory {
|
|||
try {
|
||||
transactionManagerlookup = createTransactionManagerLookup( settings, properties );
|
||||
manager = createCacheManager( properties, settings.getServiceRegistry() );
|
||||
this.settings = settings;
|
||||
initGenericDataTypeOverrides();
|
||||
final Enumeration keys = properties.propertyNames();
|
||||
while ( keys.hasMoreElements() ) {
|
||||
|
@ -587,7 +602,7 @@ public class InfinispanRegionFactory implements RegionFactory {
|
|||
}
|
||||
}
|
||||
|
||||
private AdvancedCache getCache(String regionName, String typeKey, Properties properties) {
|
||||
private AdvancedCache getCache(String regionName, String typeKey, Properties properties, CacheDataDescription metadata) {
|
||||
TypeOverrides regionOverride = typeOverrides.get( regionName );
|
||||
if ( !definedConfigurations.contains( regionName ) ) {
|
||||
final String templateCacheName;
|
||||
|
@ -621,6 +636,13 @@ public class InfinispanRegionFactory implements RegionFactory {
|
|||
// Apply overrides
|
||||
typeOverrides.get( typeKey ).applyTo( builder );
|
||||
}
|
||||
// with multi-tenancy the keys will be wrapped
|
||||
if (settings.getMultiTenancyStrategy() == MultiTenancyStrategy.NONE) {
|
||||
// the keys may not define hashCode/equals correctly (e.g. arrays)
|
||||
if (metadata != null && metadata.getKeyType() != null) {
|
||||
builder.dataContainer().keyEquivalence(new TypeEquivalance(metadata.getKeyType()));
|
||||
}
|
||||
}
|
||||
// Configure transaction manager
|
||||
configureTransactionManager( builder, templateCacheName, properties );
|
||||
// Define configuration
|
||||
|
|
46
hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/TypeEquivalance.java
vendored
Normal file
46
hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/TypeEquivalance.java
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.cache.infinispan;
|
||||
|
||||
import org.hibernate.type.Type;
|
||||
import org.infinispan.commons.equivalence.Equivalence;
|
||||
|
||||
/**
|
||||
* @author Radim Vansa <rvansa@redhat.com>
|
||||
*/
|
||||
public class TypeEquivalance implements Equivalence<Object> {
|
||||
private final Type type;
|
||||
|
||||
public TypeEquivalance(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode(Object o) {
|
||||
return type.getHashCode(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object x, Object y) {
|
||||
return type.isEqual(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(Object o) {
|
||||
return String.valueOf(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isComparable(Object o) {
|
||||
return true; // cannot guess from the type
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(Object x, Object y) {
|
||||
return type.compare(x, y);
|
||||
}
|
||||
}
|
|
@ -6,6 +6,9 @@
|
|||
*/
|
||||
package org.hibernate.cache.infinispan.access;
|
||||
|
||||
import javax.transaction.SystemException;
|
||||
import javax.transaction.Transaction;
|
||||
import javax.transaction.TransactionManager;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
@ -15,14 +18,12 @@ import java.util.concurrent.ConcurrentMap;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import javax.transaction.SystemException;
|
||||
import javax.transaction.Transaction;
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.infinispan.InfinispanRegionFactory;
|
||||
|
||||
import org.infinispan.AdvancedCache;
|
||||
import org.infinispan.configuration.cache.Configuration;
|
||||
import org.infinispan.configuration.cache.ConfigurationBuilder;
|
||||
import org.infinispan.manager.EmbeddedCacheManager;
|
||||
|
||||
/**
|
||||
|
@ -130,8 +131,7 @@ public class PutFromLoadValidator {
|
|||
public PutFromLoadValidator(
|
||||
AdvancedCache cache,
|
||||
long nakedPutInvalidationPeriod) {
|
||||
this(
|
||||
cache.getCacheManager(), cache.getTransactionManager(),
|
||||
this(cache, cache.getCacheManager(), cache.getTransactionManager(),
|
||||
nakedPutInvalidationPeriod
|
||||
);
|
||||
}
|
||||
|
@ -139,6 +139,7 @@ public class PutFromLoadValidator {
|
|||
/**
|
||||
* Creates a new put from load validator instance.
|
||||
*
|
||||
* @param cache Cache instance on which to store pending put information.
|
||||
* @param cacheManager where to find a cache to store pending put information
|
||||
* @param tm transaction manager
|
||||
* @param nakedPutInvalidationPeriod Period (in ms) after a removal during which a call to
|
||||
|
@ -146,11 +147,21 @@ public class PutFromLoadValidator {
|
|||
* {@link #registerPendingPut(Object) pre-registered} (aka a "naked put")
|
||||
* will return false.
|
||||
*/
|
||||
public PutFromLoadValidator(
|
||||
public PutFromLoadValidator(AdvancedCache cache,
|
||||
EmbeddedCacheManager cacheManager,
|
||||
TransactionManager tm, long nakedPutInvalidationPeriod) {
|
||||
this.pendingPuts = cacheManager
|
||||
.getCache( InfinispanRegionFactory.PENDING_PUTS_CACHE_NAME );
|
||||
|
||||
Configuration cacheConfiguration = cache.getCacheConfiguration();
|
||||
Configuration pendingPutsConfiguration = cacheManager.getCacheConfiguration(InfinispanRegionFactory.PENDING_PUTS_CACHE_NAME);
|
||||
ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
|
||||
if (pendingPutsConfiguration != null) {
|
||||
configurationBuilder.read(pendingPutsConfiguration);
|
||||
}
|
||||
configurationBuilder.dataContainer().keyEquivalence(cacheConfiguration.dataContainer().keyEquivalence());
|
||||
String pendingPutsName = cache.getName() + "-" + InfinispanRegionFactory.PENDING_PUTS_CACHE_NAME;
|
||||
cacheManager.defineConfiguration(pendingPutsName, configurationBuilder.build());
|
||||
|
||||
this.pendingPuts = cacheManager.getCache(pendingPutsName);
|
||||
this.transactionManager = tm;
|
||||
this.nakedPutInvalidationPeriod = nakedPutInvalidationPeriod;
|
||||
}
|
||||
|
|
|
@ -10,11 +10,11 @@ import org.hibernate.cache.CacheException;
|
|||
import org.hibernate.cache.infinispan.access.PutFromLoadValidator;
|
||||
import org.hibernate.cache.infinispan.impl.BaseTransactionalDataRegion;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.CacheKeysFactory;
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
|
||||
import org.infinispan.AdvancedCache;
|
||||
|
||||
/**
|
||||
|
@ -33,11 +33,12 @@ public class CollectionRegionImpl extends BaseTransactionalDataRegion implements
|
|||
* @param name of collection type
|
||||
* @param metadata for the collection type
|
||||
* @param factory for the region
|
||||
* @param cacheKeysFactory factory for cache keys
|
||||
*/
|
||||
public CollectionRegionImpl(
|
||||
AdvancedCache cache, String name,
|
||||
CacheDataDescription metadata, RegionFactory factory) {
|
||||
super( cache, name, metadata, factory );
|
||||
CacheDataDescription metadata, RegionFactory factory, CacheKeysFactory cacheKeysFactory) {
|
||||
super( cache, name, metadata, factory, cacheKeysFactory );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.cache.infinispan.collection;
|
|||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.infinispan.access.TransactionalAccessDelegate;
|
||||
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
|
@ -82,12 +81,12 @@ class TransactionalAccess implements CollectionRegionAccessStrategy {
|
|||
|
||||
@Override
|
||||
public Object generateCacheKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) {
|
||||
return DefaultCacheKeysFactory.createCollectionKey(id, persister, factory, tenantIdentifier);
|
||||
return region.getCacheKeysFactory().createCollectionKey(id, persister, factory, tenantIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCacheKeyId(Object cacheKey) {
|
||||
return DefaultCacheKeysFactory.getCollectionId(cacheKey);
|
||||
return region.getCacheKeysFactory().getCollectionId(cacheKey);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.cache.CacheException;
|
|||
import org.hibernate.cache.infinispan.access.PutFromLoadValidator;
|
||||
import org.hibernate.cache.infinispan.impl.BaseTransactionalDataRegion;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.CacheKeysFactory;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
|
@ -33,11 +34,12 @@ public class EntityRegionImpl extends BaseTransactionalDataRegion implements Ent
|
|||
* @param name of entity type
|
||||
* @param metadata for the entity type
|
||||
* @param factory for the region
|
||||
* @param cacheKeysFactory factory for cache keys
|
||||
*/
|
||||
public EntityRegionImpl(
|
||||
AdvancedCache cache, String name,
|
||||
CacheDataDescription metadata, RegionFactory factory) {
|
||||
super( cache, name, metadata, factory );
|
||||
CacheDataDescription metadata, RegionFactory factory, CacheKeysFactory cacheKeysFactory) {
|
||||
super( cache, name, metadata, factory, cacheKeysFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -60,5 +62,4 @@ public class EntityRegionImpl extends BaseTransactionalDataRegion implements Ent
|
|||
public PutFromLoadValidator getPutFromLoadValidator() {
|
||||
return new PutFromLoadValidator( cache );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.cache.infinispan.entity;
|
|||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.infinispan.access.TransactionalAccessDelegate;
|
||||
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
|
@ -100,11 +99,11 @@ class TransactionalAccess implements EntityRegionAccessStrategy {
|
|||
|
||||
@Override
|
||||
public Object generateCacheKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) {
|
||||
return DefaultCacheKeysFactory.createEntityKey(id, persister, factory, tenantIdentifier);
|
||||
return region.getCacheKeysFactory().createEntityKey(id, persister, factory, tenantIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCacheKeyId(Object cacheKey) {
|
||||
return DefaultCacheKeysFactory.getEntityId(cacheKey);
|
||||
return region.getCacheKeysFactory().getEntityId(cacheKey);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.cache.infinispan.impl;
|
||||
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.CacheKeysFactory;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cache.spi.TransactionalDataRegion;
|
||||
|
||||
|
@ -23,6 +24,7 @@ public abstract class BaseTransactionalDataRegion
|
|||
extends BaseRegion implements TransactionalDataRegion {
|
||||
|
||||
private final CacheDataDescription metadata;
|
||||
private final CacheKeysFactory cacheKeysFactory;
|
||||
|
||||
/**
|
||||
* Base transactional region constructor
|
||||
|
@ -31,12 +33,14 @@ public abstract class BaseTransactionalDataRegion
|
|||
* @param name of the transactional region
|
||||
* @param metadata for the transactional region
|
||||
* @param factory for the transactional region
|
||||
* @param cacheKeysFactory factory for cache keys
|
||||
*/
|
||||
public BaseTransactionalDataRegion(
|
||||
AdvancedCache cache, String name,
|
||||
CacheDataDescription metadata, RegionFactory factory) {
|
||||
super( cache, name, factory );
|
||||
CacheDataDescription metadata, RegionFactory factory, CacheKeysFactory cacheKeysFactory) {
|
||||
super( cache, name, factory);
|
||||
this.metadata = metadata;
|
||||
this.cacheKeysFactory = cacheKeysFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -44,4 +48,7 @@ public abstract class BaseTransactionalDataRegion
|
|||
return metadata;
|
||||
}
|
||||
|
||||
public CacheKeysFactory getCacheKeysFactory() {
|
||||
return cacheKeysFactory;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,11 @@ import org.hibernate.cache.CacheException;
|
|||
import org.hibernate.cache.infinispan.access.PutFromLoadValidator;
|
||||
import org.hibernate.cache.infinispan.impl.BaseTransactionalDataRegion;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.CacheKeysFactory;
|
||||
import org.hibernate.cache.spi.NaturalIdRegion;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
|
||||
import org.infinispan.AdvancedCache;
|
||||
|
||||
/**
|
||||
|
@ -33,11 +33,12 @@ public class NaturalIdRegionImpl extends BaseTransactionalDataRegion
|
|||
* @param name of natural id region
|
||||
* @param metadata for the natural id region
|
||||
* @param factory for the natural id region
|
||||
* @param cacheKeysFactory factory for cache keys
|
||||
*/
|
||||
public NaturalIdRegionImpl(
|
||||
AdvancedCache cache, String name,
|
||||
CacheDataDescription metadata, RegionFactory factory) {
|
||||
super( cache, name, metadata, factory );
|
||||
CacheDataDescription metadata, RegionFactory factory, CacheKeysFactory cacheKeysFactory) {
|
||||
super( cache, name, metadata, factory, cacheKeysFactory );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.cache.infinispan.naturalid;
|
|||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.infinispan.access.TransactionalAccessDelegate;
|
||||
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||
import org.hibernate.cache.spi.NaturalIdRegion;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
|
@ -108,11 +107,11 @@ class TransactionalAccess implements NaturalIdRegionAccessStrategy {
|
|||
|
||||
@Override
|
||||
public Object generateCacheKey(Object[] naturalIdValues, EntityPersister persister, SessionImplementor session) {
|
||||
return DefaultCacheKeysFactory.createNaturalIdKey( naturalIdValues, persister, session );
|
||||
return region.getCacheKeysFactory().createNaturalIdKey(naturalIdValues, persister, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getNaturalIdValues(Object cacheKey) {
|
||||
return DefaultCacheKeysFactory.getNaturalIdValues(cacheKey);
|
||||
return region.getCacheKeysFactory().getNaturalIdValues(cacheKey);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import org.hibernate.cache.infinispan.impl.BaseTransactionalDataRegion;
|
|||
import org.hibernate.cache.infinispan.util.Caches;
|
||||
import org.hibernate.cache.spi.QueryResultsRegion;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
|
||||
import org.infinispan.AdvancedCache;
|
||||
import org.infinispan.context.Flag;
|
||||
|
||||
|
@ -38,7 +37,7 @@ public class QueryResultsRegionImpl extends BaseTransactionalDataRegion implemen
|
|||
* @param factory for the query region
|
||||
*/
|
||||
public QueryResultsRegionImpl(AdvancedCache cache, String name, RegionFactory factory) {
|
||||
super( cache, name, null, factory );
|
||||
super( cache, name, null, factory, null );
|
||||
// If Infinispan is using INVALIDATION for query cache, we don't want to propagate changes.
|
||||
// We use the Timestamps cache to manage invalidation
|
||||
final boolean localOnly = Caches.isInvalidationCache( cache );
|
||||
|
|
|
@ -11,10 +11,12 @@ import java.util.Properties;
|
|||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cache.infinispan.InfinispanRegionFactory;
|
||||
import org.hibernate.cache.internal.CacheDataDescriptionImpl;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cache.spi.TransactionalDataRegion;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.internal.util.compare.ComparableComparator;
|
||||
import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -29,6 +31,8 @@ import static org.junit.Assert.assertTrue;
|
|||
* @since 3.5
|
||||
*/
|
||||
public abstract class AbstractEntityCollectionRegionTestCase extends AbstractRegionImplTestCase {
|
||||
protected static CacheDataDescription MUTABLE_NON_VERSIONED = new CacheDataDescriptionImpl(true, false, ComparableComparator.INSTANCE, null);
|
||||
|
||||
@Test
|
||||
public void testSupportedAccessTypes() throws Exception {
|
||||
supportedAccessTypeTest();
|
||||
|
|
|
@ -32,7 +32,7 @@ public abstract class AbstractRegionImplTestCase extends AbstractNonFunctionalTe
|
|||
protected abstract void removeFromRegion(Region region, Object key);
|
||||
|
||||
protected CacheDataDescription getCacheDataDescription() {
|
||||
return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE);
|
||||
return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -56,8 +56,8 @@ import static org.junit.Assert.fail;
|
|||
* @since 3.5
|
||||
*/
|
||||
public class InfinispanRegionFactoryTestCase {
|
||||
private static CacheDataDescription MUTABLE_NON_VERSIONED = new CacheDataDescriptionImpl(true, false, null);
|
||||
private static CacheDataDescription IMMUTABLE_NON_VERSIONED = new CacheDataDescriptionImpl(false, false, null);
|
||||
private static final CacheDataDescription MUTABLE_NON_VERSIONED = new CacheDataDescriptionImpl(true, false, null, null);
|
||||
private static final CacheDataDescription IMMUTABLE_NON_VERSIONED = new CacheDataDescriptionImpl(false, false, null, null);
|
||||
|
||||
@Test
|
||||
public void testConfigurationProcessing() {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.test.cache.infinispan.access;
|
||||
|
||||
import javax.transaction.TransactionManager;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
@ -15,20 +16,18 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.hibernate.cache.infinispan.access.PutFromLoadValidator;
|
||||
|
||||
import org.hibernate.test.cache.infinispan.functional.cluster.DualNodeJtaTransactionManagerImpl;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.infinispan.AdvancedCache;
|
||||
import org.infinispan.manager.EmbeddedCacheManager;
|
||||
import org.infinispan.test.CacheManagerCallable;
|
||||
import org.infinispan.test.fwk.TestCacheManagerFactory;
|
||||
import org.infinispan.util.logging.Log;
|
||||
import org.infinispan.util.logging.LogFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.infinispan.test.TestingUtil.withCacheManager;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
@ -84,7 +83,7 @@ public class PutFromLoadValidatorUnitTestCase {
|
|||
@Override
|
||||
public void call() {
|
||||
try {
|
||||
PutFromLoadValidator testee = new PutFromLoadValidator(cm,
|
||||
PutFromLoadValidator testee = new PutFromLoadValidator(cm.getCache().getAdvancedCache(), cm,
|
||||
transactional ? tm : null,
|
||||
PutFromLoadValidator.NAKED_PUT_INVALIDATION_PERIOD);
|
||||
if (transactional) {
|
||||
|
@ -119,7 +118,7 @@ public class PutFromLoadValidatorUnitTestCase {
|
|||
TestCacheManagerFactory.createCacheManager(false)) {
|
||||
@Override
|
||||
public void call() {
|
||||
PutFromLoadValidator testee = new PutFromLoadValidator(cm,
|
||||
PutFromLoadValidator testee = new PutFromLoadValidator(cm.getCache().getAdvancedCache(), cm,
|
||||
transactional ? tm : null,
|
||||
PutFromLoadValidator.NAKED_PUT_INVALIDATION_PERIOD);
|
||||
try {
|
||||
|
@ -166,7 +165,7 @@ public class PutFromLoadValidatorUnitTestCase {
|
|||
TestCacheManagerFactory.createCacheManager(false)) {
|
||||
@Override
|
||||
public void call() {
|
||||
PutFromLoadValidator testee = new PutFromLoadValidator(cm,
|
||||
PutFromLoadValidator testee = new PutFromLoadValidator(cm.getCache().getAdvancedCache(), cm,
|
||||
transactional ? tm : null,
|
||||
PutFromLoadValidator.NAKED_PUT_INVALIDATION_PERIOD);
|
||||
if (removeRegion) {
|
||||
|
@ -218,7 +217,7 @@ public class PutFromLoadValidatorUnitTestCase {
|
|||
TestCacheManagerFactory.createCacheManager(false)) {
|
||||
@Override
|
||||
public void call() {
|
||||
PutFromLoadValidator testee = new PutFromLoadValidator(cm,
|
||||
PutFromLoadValidator testee = new PutFromLoadValidator(cm.getCache().getAdvancedCache(), cm,
|
||||
transactional ? tm : null,
|
||||
PutFromLoadValidator.NAKED_PUT_INVALIDATION_PERIOD);
|
||||
if (removeRegion) {
|
||||
|
@ -272,7 +271,7 @@ public class PutFromLoadValidatorUnitTestCase {
|
|||
TestCacheManagerFactory.createCacheManager(false)) {
|
||||
@Override
|
||||
public void call() {
|
||||
PutFromLoadValidator testee = new PutFromLoadValidator(cm,
|
||||
PutFromLoadValidator testee = new PutFromLoadValidator(cm.getCache().getAdvancedCache(), cm,
|
||||
transactional ? tm : null,
|
||||
PutFromLoadValidator.NAKED_PUT_INVALIDATION_PERIOD);
|
||||
try {
|
||||
|
@ -325,7 +324,7 @@ public class PutFromLoadValidatorUnitTestCase {
|
|||
TestCacheManagerFactory.createCacheManager(false)) {
|
||||
@Override
|
||||
public void call() {
|
||||
PutFromLoadValidator testee = new TestValidator(cm,
|
||||
PutFromLoadValidator testee = new TestValidator(cm.getCache().getAdvancedCache(), cm,
|
||||
transactional ? tm : null, 100);
|
||||
if (removeRegion) {
|
||||
testee.invalidateRegion();
|
||||
|
@ -368,7 +367,7 @@ public class PutFromLoadValidatorUnitTestCase {
|
|||
TestCacheManagerFactory.createCacheManager(false)) {
|
||||
@Override
|
||||
public void call() {
|
||||
final PutFromLoadValidator testee = new PutFromLoadValidator(cm,
|
||||
final PutFromLoadValidator testee = new PutFromLoadValidator(cm.getCache().getAdvancedCache(), cm,
|
||||
transactional ? tm : null,
|
||||
PutFromLoadValidator.NAKED_PUT_INVALIDATION_PERIOD);
|
||||
|
||||
|
@ -440,7 +439,7 @@ public class PutFromLoadValidatorUnitTestCase {
|
|||
TestCacheManagerFactory.createCacheManager(false)) {
|
||||
@Override
|
||||
public void call() {
|
||||
final PutFromLoadValidator testee = new PutFromLoadValidator(
|
||||
final PutFromLoadValidator testee = new PutFromLoadValidator(cm.getCache().getAdvancedCache(),
|
||||
cm, null, PutFromLoadValidator.NAKED_PUT_INVALIDATION_PERIOD);
|
||||
final CountDownLatch removeLatch = new CountDownLatch(1);
|
||||
final CountDownLatch pferLatch = new CountDownLatch(1);
|
||||
|
@ -503,10 +502,10 @@ public class PutFromLoadValidatorUnitTestCase {
|
|||
|
||||
private static class TestValidator extends PutFromLoadValidator {
|
||||
|
||||
protected TestValidator(EmbeddedCacheManager cm,
|
||||
protected TestValidator(AdvancedCache cache, EmbeddedCacheManager cm,
|
||||
TransactionManager transactionManager,
|
||||
long nakedPutInvalidationPeriod) {
|
||||
super(cm, transactionManager, nakedPutInvalidationPeriod);
|
||||
super(cache, cm, transactionManager, nakedPutInvalidationPeriod);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -115,7 +115,7 @@ public abstract class AbstractCollectionRegionAccessStrategyTestCase extends Abs
|
|||
}
|
||||
|
||||
protected CacheDataDescription getCacheDataDescription() {
|
||||
return new CacheDataDescriptionImpl( true, true, ComparableComparator.INSTANCE );
|
||||
return new CacheDataDescriptionImpl( true, true, ComparableComparator.INSTANCE, null);
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -152,7 +152,7 @@ public abstract class AbstractCollectionRegionAccessStrategyTestCase extends Abs
|
|||
withCacheManager(new CacheManagerCallable(TestCacheManagerFactory.createCacheManager(false)) {
|
||||
@Override
|
||||
public void call() {
|
||||
PutFromLoadValidator validator = new PutFromLoadValidator(cm,
|
||||
PutFromLoadValidator validator = new PutFromLoadValidator(remoteCollectionRegion.getCache(), cm,
|
||||
remoteTm, 20000) {
|
||||
@Override
|
||||
public boolean acquirePutFromLoadLock(Object key) {
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.util.Properties;
|
|||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.infinispan.InfinispanRegionFactory;
|
||||
import org.hibernate.cache.internal.CacheDataDescriptionImpl;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.Region;
|
||||
|
@ -29,9 +28,6 @@ import static org.junit.Assert.fail;
|
|||
* @author Galder Zamarreño
|
||||
*/
|
||||
public class CollectionRegionImplTestCase extends AbstractEntityCollectionRegionTestCase {
|
||||
|
||||
private static CacheDataDescription MUTABLE_NON_VERSIONED = new CacheDataDescriptionImpl(true, false, null);
|
||||
|
||||
@Override
|
||||
protected void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties) {
|
||||
CollectionRegion region = regionFactory.buildCollectionRegion("test", properties, MUTABLE_NON_VERSIONED);
|
||||
|
|
|
@ -8,9 +8,12 @@ package org.hibernate.test.cache.infinispan.collection;
|
|||
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cache.infinispan.InfinispanRegionFactory;
|
||||
import org.hibernate.cache.internal.CacheDataDescriptionImpl;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.internal.util.compare.ComparableComparator;
|
||||
import org.hibernate.test.cache.infinispan.AbstractNonFunctionalTestCase;
|
||||
import org.hibernate.test.cache.infinispan.NodeEnvironment;
|
||||
import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
|
||||
|
@ -31,8 +34,8 @@ public class TransactionalExtraAPITestCase extends AbstractNonFunctionalTestCase
|
|||
|
||||
public static final String REGION_NAME = "test/com.foo.test";
|
||||
public static final Object KEY = TestingKeyFactory.generateCollectionCacheKey( "KEY" );
|
||||
public static final String VALUE1 = "VALUE1";
|
||||
public static final String VALUE2 = "VALUE2";
|
||||
public static final CacheDataDescription CACHE_DATA_DESCRIPTION
|
||||
= new CacheDataDescriptionImpl(false, false, ComparableComparator.INSTANCE, null);
|
||||
|
||||
private NodeEnvironment environment;
|
||||
private static CollectionRegionAccessStrategy accessStrategy;
|
||||
|
@ -45,7 +48,7 @@ public class TransactionalExtraAPITestCase extends AbstractNonFunctionalTestCase
|
|||
// Sleep a bit to avoid concurrent FLUSH problem
|
||||
avoidConcurrentFlush();
|
||||
|
||||
accessStrategy = environment.getCollectionRegion( REGION_NAME, null ).buildAccessStrategy( getAccessType() );
|
||||
accessStrategy = environment.getCollectionRegion( REGION_NAME, CACHE_DATA_DESCRIPTION).buildAccessStrategy( getAccessType() );
|
||||
}
|
||||
|
||||
protected StandardServiceRegistryBuilder createStandardServiceRegistryBuilder() {
|
||||
|
|
|
@ -115,7 +115,7 @@ public abstract class AbstractEntityRegionAccessStrategyTestCase extends Abstrac
|
|||
}
|
||||
|
||||
protected CacheDataDescription getCacheDataDescription() {
|
||||
return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE);
|
||||
return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE, null);
|
||||
}
|
||||
|
||||
@After
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.util.Properties;
|
|||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.infinispan.InfinispanRegionFactory;
|
||||
import org.hibernate.cache.internal.CacheDataDescriptionImpl;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
import org.hibernate.cache.spi.Region;
|
||||
|
@ -30,8 +29,6 @@ import static org.junit.Assert.fail;
|
|||
*/
|
||||
public class EntityRegionImplTestCase extends AbstractEntityCollectionRegionTestCase {
|
||||
|
||||
private static CacheDataDescription MUTABLE_NON_VERSIONED = new CacheDataDescriptionImpl(true, false, null);
|
||||
|
||||
@Override
|
||||
protected void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties) {
|
||||
EntityRegion region = regionFactory.buildEntityRegion("test", properties, MUTABLE_NON_VERSIONED);
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.hibernate.cache.internal.CacheDataDescriptionImpl;
|
|||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.internal.util.compare.ComparableComparator;
|
||||
import org.hibernate.test.cache.infinispan.AbstractNonFunctionalTestCase;
|
||||
import org.hibernate.test.cache.infinispan.NodeEnvironment;
|
||||
import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
|
||||
|
@ -38,6 +39,8 @@ public class TransactionalExtraAPITestCase extends AbstractNonFunctionalTestCase
|
|||
public static final Object KEY = TestingKeyFactory.generateEntityCacheKey( "KEY" );
|
||||
public static final String VALUE1 = "VALUE1";
|
||||
public static final String VALUE2 = "VALUE2";
|
||||
protected static final CacheDataDescriptionImpl CACHE_DATA_DESCRIPTION
|
||||
= new CacheDataDescriptionImpl(true, false, ComparableComparator.INSTANCE, null);
|
||||
|
||||
private NodeEnvironment environment;
|
||||
private EntityRegionAccessStrategy accessStrategy;
|
||||
|
@ -50,7 +53,7 @@ public class TransactionalExtraAPITestCase extends AbstractNonFunctionalTestCase
|
|||
// Sleep a bit to avoid concurrent FLUSH problem
|
||||
avoidConcurrentFlush();
|
||||
|
||||
accessStrategy = environment.getEntityRegion( REGION_NAME, new CacheDataDescriptionImpl(true, false, null)).buildAccessStrategy( getAccessType() );
|
||||
accessStrategy = environment.getEntityRegion( REGION_NAME, CACHE_DATA_DESCRIPTION).buildAccessStrategy( getAccessType() );
|
||||
}
|
||||
|
||||
protected StandardServiceRegistryBuilder createStandardServiceRegistryBuilder() {
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
package org.hibernate.test.cache.infinispan.functional;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.stat.Statistics;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.infinispan.test.TestingUtil.withTx;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Persons should be correctly indexed since we can use Type for comparison
|
||||
*
|
||||
* @author Radim Vansa <rvansa@redhat.com>
|
||||
*/
|
||||
public class EqualityTest extends SingleNodeTestCase {
|
||||
@Override
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[] { Person.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualityFromType() throws Exception {
|
||||
Person john = new Person("John", "Black", 26);
|
||||
Person peter = new Person("Peter", "White", 32);
|
||||
|
||||
withTx(tm, new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
Session session = openSession();
|
||||
session.getTransaction().begin();
|
||||
session.persist(john);
|
||||
session.persist(peter);
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
Statistics statistics = sessionFactory().getStatistics();
|
||||
statistics.clear();
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
withTx(tm, new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
Session session = openSession();
|
||||
session.getTransaction().begin();
|
||||
Person p1 = session.get(Person.class, john.name);
|
||||
assertPersonEquals(john, p1);
|
||||
Person p2 = session.get(Person.class, peter.name);
|
||||
assertPersonEquals(peter, p2);
|
||||
Person p3 = session.get(Person.class, new Name("Foo", "Bar"));
|
||||
assertNull(p3);
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
assertTrue(statistics.getSecondLevelCacheHitCount() > 0);
|
||||
assertTrue(statistics.getSecondLevelCacheMissCount() > 0);
|
||||
}
|
||||
|
||||
private static void assertPersonEquals(Person expected, Person person) {
|
||||
assertNotNull(person);
|
||||
assertNotNull(person.getName());
|
||||
assertEquals(expected.getName().getFirstName(), person.getName().getFirstName());
|
||||
assertEquals(expected.getName().getLastName(), person.getName().getLastName());
|
||||
assertEquals(expected.getAge(), person.getAge());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
package org.hibernate.test.cache.infinispan.functional;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.hibernate.MultiTenancyStrategy;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.boot.SessionFactoryBuilder;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cache.infinispan.entity.EntityRegionImpl;
|
||||
import org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
|
||||
import org.hibernate.test.cache.infinispan.tm.XaConnectionProvider;
|
||||
import org.hibernate.testing.env.ConnectionProviderBuilder;
|
||||
import org.infinispan.commons.util.CloseableIteratorSet;
|
||||
import org.infinispan.context.Flag;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.infinispan.test.TestingUtil.withTx;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author Radim Vansa <rvansa@redhat.com>
|
||||
*/
|
||||
public class MultiTenancyTestCase extends SingleNodeTestCase {
|
||||
|
||||
private static final String DB1 = "db1";
|
||||
private static final String DB2 = "db2";
|
||||
private final ConnectionProvider db1
|
||||
= new XaConnectionProvider(ConnectionProviderBuilder.buildConnectionProvider(DB1));
|
||||
private final ConnectionProvider db2
|
||||
= new XaConnectionProvider(ConnectionProviderBuilder.buildConnectionProvider(DB2));
|
||||
|
||||
@Override
|
||||
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
|
||||
super.configureStandardServiceRegistryBuilder(ssrb);
|
||||
ssrb.addService(MultiTenantConnectionProvider.class, new AbstractMultiTenantConnectionProvider() {
|
||||
|
||||
@Override
|
||||
protected ConnectionProvider getAnyConnectionProvider() {
|
||||
return db1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) {
|
||||
if (DB1.equals(tenantIdentifier)) return db1;
|
||||
if (DB2.equals(tenantIdentifier)) return db2;
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureSessionFactoryBuilder(SessionFactoryBuilder sfb) {
|
||||
super.configureSessionFactoryBuilder(sfb);
|
||||
sfb.applyMultiTenancyStrategy(MultiTenancyStrategy.DATABASE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void cleanupTest() throws Exception {
|
||||
db1.getConnection().close();
|
||||
db2.getConnection().close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiTenancy() throws Exception {
|
||||
final Item item = new Item("my item", "description" );
|
||||
|
||||
long id = withTx(tm, new Callable<Long>() {
|
||||
@Override
|
||||
public Long call() throws Exception {
|
||||
Session s = sessionFactory().withOptions().tenantIdentifier(DB1).openSession();
|
||||
s.getTransaction().begin();
|
||||
s.persist(item);
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
return item.getId();
|
||||
}
|
||||
});
|
||||
for (int i = 0; i < 5; ++i) { // make sure we get something cached
|
||||
withTx(tm, new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
Session s = sessionFactory().withOptions().tenantIdentifier(DB1).openSession();
|
||||
s.getTransaction().begin();
|
||||
Item item2 = s.get(Item.class, id);
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
assertNotNull(item2);
|
||||
assertEquals(item.getName(), item2.getName());
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
// The table ITEMS is not created in DB2 - we would get just an exception
|
||||
// for (int i = 0; i < 5; ++i) { // make sure we get something cached
|
||||
// withTx(tm, new Callable<Void>() {
|
||||
// @Override
|
||||
// public Void call() throws Exception {
|
||||
// Session s = sessionFactory().withOptions().tenantIdentifier(DB2).openSession();
|
||||
// s.getTransaction().begin();
|
||||
// Item item2 = s.get(Item.class, id);
|
||||
// s.getTransaction().commit();
|
||||
// s.close();
|
||||
// assertNull(item2);
|
||||
// return null;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
EntityRegionImpl region = (EntityRegionImpl) sessionFactory().getSecondLevelCacheRegion(Item.class.getName());
|
||||
CloseableIteratorSet keySet = region.getCache().withFlags(Flag.CACHE_MODE_LOCAL).keySet();
|
||||
assertEquals(1, keySet.size());
|
||||
assertEquals("OldCacheKeyImplementation", keySet.iterator().next().getClass().getSimpleName());
|
||||
}
|
||||
|
||||
}
|
48
hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Name.java
vendored
Normal file
48
hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Name.java
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
package org.hibernate.test.cache.infinispan.functional;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Test class with incorrectly defined equals and hashCode.
|
||||
*
|
||||
* @author Radim Vansa <rvansa@redhat.com>
|
||||
*/
|
||||
@Embeddable
|
||||
public class Name implements Serializable {
|
||||
String firstName;
|
||||
String lastName;
|
||||
|
||||
public Name() {}
|
||||
|
||||
public Name(String firstName, String lastName) {
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package org.hibernate.test.cache.infinispan.functional;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.cache.infinispan.entity.EntityRegionImpl;
|
||||
import org.infinispan.commons.util.CloseableIteratorSet;
|
||||
import org.infinispan.context.Flag;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.infinispan.test.TestingUtil.withTx;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author Radim Vansa <rvansa@redhat.com>
|
||||
*/
|
||||
public class NoTenancyTestCase extends SingleNodeTestCase {
|
||||
@Test
|
||||
public void testNoTenancy() throws Exception {
|
||||
final Item item = new Item("my item", "description" );
|
||||
|
||||
long id = withTx(tm, new Callable<Long>() {
|
||||
@Override
|
||||
public Long call() throws Exception {
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.persist(item);
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
return item.getId();
|
||||
}
|
||||
});
|
||||
for (int i = 0; i < 5; ++i) { // make sure we get something cached
|
||||
withTx(tm, new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
Item item2 = s.get(Item.class, id);
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
assertNotNull(item2);
|
||||
assertEquals(item.getName(), item2.getName());
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
EntityRegionImpl region = (EntityRegionImpl) sessionFactory().getSecondLevelCacheRegion(Item.class.getName());
|
||||
CloseableIteratorSet keySet = region.getCache().withFlags(Flag.CACHE_MODE_LOCAL).keySet();
|
||||
assertEquals(1, keySet.size());
|
||||
assertEquals(sessionFactory().getClassMetadata(Item.class).getIdentifierType().getReturnedClass(), keySet.iterator().next().getClass());
|
||||
}
|
||||
|
||||
}
|
41
hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Person.java
vendored
Normal file
41
hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Person.java
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
package org.hibernate.test.cache.infinispan.functional;
|
||||
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Test class using EmbeddedId
|
||||
*
|
||||
* @author Radim Vansa <rvansa@redhat.com>
|
||||
*/
|
||||
@Entity
|
||||
public class Person implements Serializable {
|
||||
@EmbeddedId
|
||||
Name name;
|
||||
|
||||
int age;
|
||||
|
||||
public Person() {}
|
||||
|
||||
public Person(String firstName, String lastName, int age) {
|
||||
name = new Name(firstName, lastName);
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public Name getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(Name name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
|
@ -343,7 +343,7 @@ public class EntityCollectionInvalidationTestCase extends DualNodeTestCase {
|
|||
public void nodeVisited(CacheEntryVisitedEvent event) {
|
||||
log.debug( event.toString() );
|
||||
if ( !event.isPre() ) {
|
||||
String key = String.valueOf(event.getKey());
|
||||
String key = event.getCache().getName() + "#" + event.getKey();
|
||||
log.debug( "MyListener[" + name + "] - Visiting key " + key );
|
||||
// String name = fqn.toString();
|
||||
String token = ".functional.";
|
||||
|
@ -351,7 +351,7 @@ public class EntityCollectionInvalidationTestCase extends DualNodeTestCase {
|
|||
if ( index > -1 ) {
|
||||
index += token.length();
|
||||
key = key.substring( index );
|
||||
log.debug( "MyListener[" + name + "] - recording visit to " + key );
|
||||
log.debug( "MyListener[" + this.name + "] - recording visit to " + key );
|
||||
visited.add( key );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,10 +23,19 @@ import org.hibernate.testing.env.ConnectionProviderBuilder;
|
|||
* @since 3.5
|
||||
*/
|
||||
public class XaConnectionProvider implements ConnectionProvider {
|
||||
private static ConnectionProvider actualConnectionProvider = ConnectionProviderBuilder.buildConnectionProvider();
|
||||
private final static ConnectionProvider DEFAULT_CONNECTION_PROVIDER = ConnectionProviderBuilder.buildConnectionProvider();
|
||||
private final ConnectionProvider actualConnectionProvider;
|
||||
private boolean isTransactional;
|
||||
|
||||
public static ConnectionProvider getActualConnectionProvider() {
|
||||
public XaConnectionProvider() {
|
||||
this(DEFAULT_CONNECTION_PROVIDER);
|
||||
}
|
||||
|
||||
public XaConnectionProvider(ConnectionProvider connectionProvider) {
|
||||
this.actualConnectionProvider = connectionProvider;
|
||||
}
|
||||
|
||||
public ConnectionProvider getActualConnectionProvider() {
|
||||
return actualConnectionProvider;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue