Skip to content

Commit fe6fddc

Browse files
committed
HHH-19218 use a stronger hashing function for cache keys
1 parent 6141168 commit fe6fddc

File tree

4 files changed

+58
-12
lines changed

4 files changed

+58
-12
lines changed

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

+10-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,16 @@ public BasicCacheKeyImplementation(
5555
}
5656

5757
private static int calculateHashCode(Object disassembledKey, Type type) {
58-
return type.getHashCode( disassembledKey );
58+
return hash( type.getHashCode( disassembledKey ) );
59+
}
60+
61+
@Internal
62+
public static int hash(int h) {
63+
// Mix the result with the Murmur3 finalising function
64+
h = (h ^ (h >>> 16)) * 0x85ebca6b;
65+
h = (h ^ (h >>> 13)) * 0xc2b2ae35;
66+
h = h ^ (h >>> 16);
67+
return h;
5968
}
6069

6170
public Object getId() {

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public CacheKeyImplementation(
8181
private static int calculateHashCode(Object id, Type type, String tenantId) {
8282
int result = type.getHashCode( id );
8383
result = 31 * result + ( tenantId != null ? tenantId.hashCode() : 0 );
84-
return result;
84+
return BasicCacheKeyImplementation.hash( result );
8585
}
8686

8787
public Object getId() {

hibernate-core/src/test/java/org/hibernate/orm/test/caching/mocked/CacheKeyImplementationHashCodeTest.java

+46-9
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import org.hibernate.boot.Metadata;
1414
import org.hibernate.boot.MetadataSources;
1515
import org.hibernate.boot.SessionFactoryBuilder;
16-
import org.hibernate.cache.internal.CacheKeyImplementation;
1716
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
1817
import org.hibernate.engine.spi.SessionFactoryImplementor;
1918
import org.hibernate.persister.entity.EntityPersister;
@@ -24,6 +23,7 @@
2423
import org.junit.Test;
2524

2625
import static org.junit.Assert.assertFalse;
26+
import static org.junit.Assert.assertTrue;
2727

2828
/**
2929
* @author Gail Badner
@@ -32,37 +32,74 @@ public class CacheKeyImplementationHashCodeTest {
3232

3333
@Test
3434
@JiraKey( value = "HHH-12746")
35-
public void test() {
35+
public void testHashCodeChanges() {
3636
try (ServiceRegistryImplementor serviceRegistry = ServiceRegistryUtil.serviceRegistry()) {
3737
MetadataSources ms = new MetadataSources( serviceRegistry );
3838
ms.addAnnotatedClass( AnEntity.class ).addAnnotatedClass( AnotherEntity.class );
3939
Metadata metadata = ms.buildMetadata();
4040
final SessionFactoryBuilder sfb = metadata.getSessionFactoryBuilder();
4141
try ( SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) sfb.build()) {
42-
CacheKeyImplementation anEntityCacheKey = createCacheKeyImplementation(
42+
Object anEntityCacheKey = createCacheKeyImplementation(
4343
1,
4444
sessionFactory.getRuntimeMetamodels()
4545
.getMappingMetamodel()
4646
.getEntityDescriptor( AnEntity.class ),
47-
sessionFactory
47+
sessionFactory,
48+
"tenant"
4849
);
49-
CacheKeyImplementation anotherEntityCacheKey = createCacheKeyImplementation(
50+
Object anotherEntityCacheKey = createCacheKeyImplementation(
5051
1,
5152
sessionFactory.getRuntimeMetamodels()
5253
.getMappingMetamodel()
5354
.getEntityDescriptor( AnotherEntity.class ),
54-
sessionFactory
55+
sessionFactory,
56+
"tenant"
5557
);
5658
assertFalse( anEntityCacheKey.equals( anotherEntityCacheKey ) );
5759
}
5860
}
5961
}
6062

61-
private CacheKeyImplementation createCacheKeyImplementation(
63+
@Test
64+
@JiraKey( value = "HHH-19218")
65+
public void testMixedHashCode() {
66+
try (ServiceRegistryImplementor serviceRegistry = ServiceRegistryUtil.serviceRegistry()) {
67+
MetadataSources ms = new MetadataSources( serviceRegistry );
68+
ms.addAnnotatedClass( AnEntity.class ).addAnnotatedClass( AnotherEntity.class );
69+
Metadata metadata = ms.buildMetadata();
70+
final SessionFactoryBuilder sfb = metadata.getSessionFactoryBuilder();
71+
try ( SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) sfb.build()) {
72+
Object anEntityCacheKey = createCacheKeyImplementation(
73+
1,
74+
sessionFactory.getRuntimeMetamodels()
75+
.getMappingMetamodel()
76+
.getEntityDescriptor( AnEntity.class ),
77+
sessionFactory,
78+
null
79+
);
80+
assertTrue( (anEntityCacheKey.hashCode() >>> 16) != 0 );
81+
assertTrue( (anEntityCacheKey.hashCode() << 16) != 0 );
82+
83+
Object anotherEntityCacheKey = createCacheKeyImplementation(
84+
1,
85+
sessionFactory.getRuntimeMetamodels()
86+
.getMappingMetamodel()
87+
.getEntityDescriptor( AnotherEntity.class ),
88+
sessionFactory,
89+
"0"
90+
);
91+
assertTrue( (anotherEntityCacheKey.hashCode() >>> 16) != 0 );
92+
assertTrue( (anotherEntityCacheKey.hashCode() << 16) != 0 );
93+
}
94+
}
95+
}
96+
97+
private Object createCacheKeyImplementation(
6298
int id,
6399
EntityPersister persister,
64-
SessionFactoryImplementor sfi) {
65-
return (CacheKeyImplementation) DefaultCacheKeysFactory.staticCreateEntityKey( id, persister, sfi, "tenant" );
100+
SessionFactoryImplementor sfi,
101+
String tenantIdentifier) {
102+
return DefaultCacheKeysFactory.staticCreateEntityKey( id, persister, sfi, tenantIdentifier);
66103
}
67104

68105
@Entity(name = "AnEntity")

hibernate-core/src/test/java/org/hibernate/orm/test/querycache/QueryRestrictedCollectionCachingTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ private static Serializable[] extractCachedCollectionKeys(CacheImplementor cache
131131
final CollectionReadWriteAccess authorsRegionAccess = (CollectionReadWriteAccess) cache.getCollectionRegionAccess( navigableRole );
132132

133133
final MapStorageAccessImpl storageAccess = (MapStorageAccessImpl) authorsRegionAccess.getStorageAccess();
134-
final BasicCacheKeyImplementation cacheKey = new BasicCacheKeyImplementation( ownerKey, role, ownerKey );
134+
final BasicCacheKeyImplementation cacheKey = new BasicCacheKeyImplementation( ownerKey, role, BasicCacheKeyImplementation.hash( ownerKey ) );
135135
final AbstractReadWriteAccess.Item cacheItem = (AbstractReadWriteAccess.Item) storageAccess.getFromData( cacheKey );
136136
assertThat( cacheItem ).isNotNull();
137137

0 commit comments

Comments
 (0)