Skip to content

Commit 2f1b67b

Browse files
rvansasebersole
authored andcommitted
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
1 parent bcf38a0 commit 2f1b67b

36 files changed

+671
-106
lines changed

hibernate-core/src/main/java/org/hibernate/cache/internal/CacheDataDescriptionImpl.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.hibernate.cache.spi.CacheDataDescription;
1212
import org.hibernate.mapping.Collection;
1313
import org.hibernate.mapping.PersistentClass;
14+
import org.hibernate.type.Type;
1415
import org.hibernate.type.VersionType;
1516

1617
/**
@@ -22,19 +23,21 @@ public class CacheDataDescriptionImpl implements CacheDataDescription {
2223
private final boolean mutable;
2324
private final boolean versioned;
2425
private final Comparator versionComparator;
26+
private final Type keyType;
2527

2628
/**
2729
* Constructs a CacheDataDescriptionImpl instance. Generally speaking, code should use one of the
2830
* overloaded {@link #decode} methods rather than direct instantiation.
29-
*
3031
* @param mutable Is the described data mutable?
3132
* @param versioned Is the described data versioned?
3233
* @param versionComparator The described data's version value comparator (if versioned).
34+
* @param keyType
3335
*/
34-
public CacheDataDescriptionImpl(boolean mutable, boolean versioned, Comparator versionComparator) {
36+
public CacheDataDescriptionImpl(boolean mutable, boolean versioned, Comparator versionComparator, Type keyType) {
3537
this.mutable = mutable;
3638
this.versioned = versioned;
3739
this.versionComparator = versionComparator;
40+
this.keyType = keyType;
3841
}
3942

4043
@Override
@@ -52,6 +55,11 @@ public Comparator getVersionComparator() {
5255
return versionComparator;
5356
}
5457

58+
@Override
59+
public Type getKeyType() {
60+
return keyType;
61+
}
62+
5563
/**
5664
* Builds a CacheDataDescriptionImpl from the mapping model of an entity class.
5765
*
@@ -65,8 +73,8 @@ public static CacheDataDescriptionImpl decode(PersistentClass model) {
6573
model.isVersioned(),
6674
model.isVersioned()
6775
? ( (VersionType) model.getVersion().getType() ).getComparator()
68-
: null
69-
);
76+
: null,
77+
model.getIdentifierProperty().getType());
7078
}
7179

7280
/**
@@ -82,8 +90,8 @@ public static CacheDataDescriptionImpl decode(Collection model) {
8290
model.getOwner().isVersioned(),
8391
model.getOwner().isVersioned()
8492
? ( (VersionType) model.getOwner().getVersion().getType() ).getComparator()
85-
: null
86-
);
93+
: null,
94+
model.getKey().getType());
8795
}
8896

8997
}

hibernate-core/src/main/java/org/hibernate/cache/internal/DefaultCacheKeysFactory.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
package org.hibernate.cache.internal;
88

9+
import org.hibernate.cache.spi.CacheKeysFactory;
910
import org.hibernate.engine.spi.SessionFactoryImplementor;
1011
import org.hibernate.engine.spi.SessionImplementor;
1112
import org.hibernate.persister.collection.CollectionPersister;
@@ -48,7 +49,7 @@ public static Object createEntityKey(Object id, EntityPersister persister, Sessi
4849
}
4950

5051
public static Object createNaturalIdKey(Object[] naturalIdValues, EntityPersister persister, SessionImplementor session) {
51-
return new OldNaturalIdCacheKey( naturalIdValues, persister, session );
52+
return new OldNaturalIdCacheKey( naturalIdValues, persister.getPropertyTypes(), persister.getNaturalIdentifierProperties(), persister.getRootEntityName(), session );
5253
}
5354

5455
public static Object getEntityId(Object cacheKey) {
@@ -62,4 +63,36 @@ public static Object getCollectionId(Object cacheKey) {
6263
public static Object[] getNaturalIdValues(Object cacheKey) {
6364
return ((OldNaturalIdCacheKey) cacheKey).getNaturalIdValues();
6465
}
66+
67+
public static CacheKeysFactory INSTANCE = new CacheKeysFactory() {
68+
@Override
69+
public Object createCollectionKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) {
70+
return DefaultCacheKeysFactory.createCollectionKey(id, persister, factory, tenantIdentifier);
71+
}
72+
73+
@Override
74+
public Object createEntityKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) {
75+
return DefaultCacheKeysFactory.createEntityKey(id, persister, factory, tenantIdentifier);
76+
}
77+
78+
@Override
79+
public Object createNaturalIdKey(Object[] naturalIdValues, EntityPersister persister, SessionImplementor session) {
80+
return DefaultCacheKeysFactory.createNaturalIdKey(naturalIdValues, persister, session);
81+
}
82+
83+
@Override
84+
public Object getEntityId(Object cacheKey) {
85+
return DefaultCacheKeysFactory.getEntityId(cacheKey);
86+
}
87+
88+
@Override
89+
public Object getCollectionId(Object cacheKey) {
90+
return DefaultCacheKeysFactory.getCollectionId(cacheKey);
91+
}
92+
93+
@Override
94+
public Object[] getNaturalIdValues(Object cacheKey) {
95+
return DefaultCacheKeysFactory.getNaturalIdValues(cacheKey);
96+
}
97+
};
6598
}

hibernate-core/src/main/java/org/hibernate/cache/internal/OldNaturalIdCacheKey.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import org.hibernate.engine.spi.SessionImplementor;
1616
import org.hibernate.internal.util.ValueHolder;
1717
import org.hibernate.internal.util.compare.EqualsHelper;
18-
import org.hibernate.persister.entity.EntityPersister;
1918
import org.hibernate.type.EntityType;
2019
import org.hibernate.type.Type;
2120

@@ -41,24 +40,22 @@ public class OldNaturalIdCacheKey implements Serializable {
4140

4241
/**
4342
* Construct a new key for a caching natural identifier resolutions into the second level cache.
44-
*
4543
* @param naturalIdValues The naturalIdValues associated with the cached data
46-
* @param persister The persister for the entity
44+
* @param propertyTypes
45+
* @param naturalIdPropertyIndexes
4746
* @param session The originating session
4847
*/
4948
public OldNaturalIdCacheKey(
5049
final Object[] naturalIdValues,
51-
final EntityPersister persister,
50+
Type[] propertyTypes, int[] naturalIdPropertyIndexes, final String entityName,
5251
final SessionImplementor session) {
5352

54-
this.entityName = persister.getRootEntityName();
53+
this.entityName = entityName;
5554
this.tenantId = session.getTenantIdentifier();
5655

5756
this.naturalIdValues = new Serializable[naturalIdValues.length];
5857

5958
final SessionFactoryImplementor factory = session.getFactory();
60-
final int[] naturalIdPropertyIndexes = persister.getNaturalIdentifierProperties();
61-
final Type[] propertyTypes = persister.getPropertyTypes();
6259

6360
final int prime = 31;
6461
int result = 1;
@@ -93,7 +90,7 @@ private void initTransients() {
9390
public String initialize() {
9491
//Complex toString is needed as naturalIds for entities are not simply based on a single value like primary keys
9592
//the only same way to differentiate the keys is to included the disassembled values in the string.
96-
final StringBuilder toStringBuilder = new StringBuilder( entityName ).append( "##NaturalId[" );
93+
final StringBuilder toStringBuilder = new StringBuilder().append( entityName ).append( "##NaturalId[" );
9794
for ( int i = 0; i < naturalIdValues.length; i++ ) {
9895
toStringBuilder.append( naturalIdValues[i] );
9996
if ( i + 1 < naturalIdValues.length ) {
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.cache.internal;
8+
9+
import org.hibernate.cache.spi.CacheKeysFactory;
10+
import org.hibernate.engine.spi.SessionFactoryImplementor;
11+
import org.hibernate.engine.spi.SessionImplementor;
12+
import org.hibernate.persister.collection.CollectionPersister;
13+
import org.hibernate.persister.entity.EntityPersister;
14+
15+
/**
16+
* Factory that does not fill in the entityName or role
17+
*
18+
* @author Radim Vansa &lt;[email protected]&gt;
19+
*/
20+
public class SimpleCacheKeysFactory implements CacheKeysFactory {
21+
22+
public static CacheKeysFactory INSTANCE = new SimpleCacheKeysFactory();
23+
24+
@Override
25+
public Object createCollectionKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) {
26+
return id;
27+
}
28+
29+
@Override
30+
public Object createEntityKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) {
31+
return id;
32+
}
33+
34+
@Override
35+
public Object createNaturalIdKey(Object[] naturalIdValues, EntityPersister persister, SessionImplementor session) {
36+
// natural ids always need to be wrapped
37+
return new OldNaturalIdCacheKey(naturalIdValues, persister.getPropertyTypes(), persister.getNaturalIdentifierProperties(), null, session);
38+
}
39+
40+
@Override
41+
public Object getEntityId(Object cacheKey) {
42+
return cacheKey;
43+
}
44+
45+
@Override
46+
public Object getCollectionId(Object cacheKey) {
47+
return cacheKey;
48+
}
49+
50+
@Override
51+
public Object[] getNaturalIdValues(Object cacheKey) {
52+
return ((OldNaturalIdCacheKey) cacheKey).getNaturalIdValues();
53+
}
54+
}

hibernate-core/src/main/java/org/hibernate/cache/spi/CacheDataDescription.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
import java.util.Comparator;
1010

11+
import org.hibernate.type.Type;
12+
1113
/**
1214
* Describes attributes regarding the type of data to be cached.
1315
*
@@ -37,4 +39,10 @@ public interface CacheDataDescription {
3739
* @return The comparator for versions, or {@code null}
3840
*/
3941
public Comparator getVersionComparator();
42+
43+
/**
44+
* @return Type of the key that will be used as the key in the cache, or {@code null} if the natural comparison
45+
* ({@link Object#hashCode()} and {@link Object#equals(Object)} methods should be used.
46+
*/
47+
Type getKeyType();
4048
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.cache.spi;
8+
9+
import org.hibernate.engine.spi.SessionFactoryImplementor;
10+
import org.hibernate.engine.spi.SessionImplementor;
11+
import org.hibernate.persister.collection.CollectionPersister;
12+
import org.hibernate.persister.entity.EntityPersister;
13+
14+
/**
15+
* @author Radim Vansa &lt;[email protected]&gt;
16+
*/
17+
public interface CacheKeysFactory {
18+
Object createCollectionKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier);
19+
20+
Object createEntityKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier);
21+
22+
Object createNaturalIdKey(Object[] naturalIdValues, EntityPersister persister, SessionImplementor session);
23+
24+
Object getEntityId(Object cacheKey);
25+
26+
Object getCollectionId(Object cacheKey);
27+
28+
Object[] getNaturalIdValues(Object cacheKey);
29+
}

hibernate-core/src/test/java/org/hibernate/cache/spi/NaturalIdCacheKeyTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
6262
});
6363

6464
final OldNaturalIdCacheKey key = (OldNaturalIdCacheKey) DefaultCacheKeysFactory.createNaturalIdKey( new Object[] {"a", "b", "c"}, entityPersister, sessionImplementor );
65-
65+
6666
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
6767
final ObjectOutputStream oos = new ObjectOutputStream(baos);
6868
oos.writeObject(key);

0 commit comments

Comments
 (0)