HHH-8961 Reduce allocation cost of org.hibernate.cache.spi.CacheKey instances
Remove tenantId field from CacheKey: use a different type when tenants are needed. Also remove the Type as we should be able to rely on the entityOrRoleName String.
This commit is contained in:
parent
0f0a95e2b8
commit
539866b773
54
hibernate-core/src/main/java/org/hibernate/cache/internal/TenantAwareCacheKey.java
vendored
Normal file
54
hibernate-core/src/main/java/org/hibernate/cache/internal/TenantAwareCacheKey.java
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2014, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.cache.spi.CacheKey;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Variation of CacheKey to be used when multi-tenancy is applied.
|
||||
* The tenantId field was not simply added to the superclass because of performance considerations:
|
||||
* CacheKey instances are have a very high allocation frequency and this field would enlarge the
|
||||
* size by 50%.
|
||||
*
|
||||
* @author Sanne Grinovero
|
||||
*/
|
||||
public class TenantAwareCacheKey extends CacheKey {
|
||||
|
||||
private final String tenantId;
|
||||
|
||||
public TenantAwareCacheKey(Serializable id, Type type, String entityOrRoleName, SessionFactoryImplementor factory, String tenantId) {
|
||||
super( id, type, entityOrRoleName, factory, tenantId );
|
||||
this.tenantId = tenantId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTenantId() {
|
||||
return tenantId;
|
||||
}
|
||||
|
||||
}
|
|
@ -33,14 +33,20 @@ import org.hibernate.type.Type;
|
|||
* Allows multiple entity classes / collection roles to be stored in the same cache region. Also allows for composite
|
||||
* keys which do not properly implement equals()/hashCode().
|
||||
*
|
||||
* Note on performance: this class is allocated very heavily!
|
||||
* Make sure the allocation cost stays as low as possible:
|
||||
* if you need to add fields for not-so-common use cases,
|
||||
* it's probably better to create an ad-hoc implementation
|
||||
* extending this one.
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
* @author Sanne Grinovero
|
||||
*/
|
||||
public class CacheKey implements Serializable {
|
||||
|
||||
private final Serializable key;
|
||||
private final Type type;
|
||||
private final String entityOrRoleName;
|
||||
private final String tenantId;
|
||||
private final int hashCode;
|
||||
|
||||
/**
|
||||
|
@ -58,16 +64,25 @@ public class CacheKey implements Serializable {
|
|||
final Serializable id,
|
||||
final Type type,
|
||||
final String entityOrRoleName,
|
||||
final String tenantId,
|
||||
final SessionFactoryImplementor factory) {
|
||||
this.key = id;
|
||||
this.type = type;
|
||||
this.entityOrRoleName = entityOrRoleName;
|
||||
this.tenantId = tenantId;
|
||||
this.hashCode = calculateHashCode( type, factory );
|
||||
this( id, type, entityOrRoleName, factory, null );
|
||||
}
|
||||
|
||||
private int calculateHashCode(Type type, SessionFactoryImplementor factory) {
|
||||
/**
|
||||
* Used by subclasses: need to specify a tenantId
|
||||
*/
|
||||
protected CacheKey(
|
||||
final Serializable id,
|
||||
final Type type,
|
||||
final String entityOrRoleName,
|
||||
final SessionFactoryImplementor factory,
|
||||
final String tenantId) {
|
||||
this.key = id;
|
||||
this.type = type;
|
||||
this.hashCode = calculateHashCode( type, factory, tenantId );
|
||||
}
|
||||
|
||||
private int calculateHashCode(Type type, SessionFactoryImplementor factory, String tenantId) {
|
||||
int result = type.getHashCode( key, factory );
|
||||
result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0);
|
||||
return result;
|
||||
|
@ -77,12 +92,8 @@ public class CacheKey implements Serializable {
|
|||
return key;
|
||||
}
|
||||
|
||||
public String getEntityOrRoleName() {
|
||||
return entityOrRoleName;
|
||||
}
|
||||
|
||||
public String getTenantId() {
|
||||
return tenantId;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -97,10 +108,10 @@ public class CacheKey implements Serializable {
|
|||
//hashCode is part of this check since it is pre-calculated and hash must match for equals to be true
|
||||
return false;
|
||||
}
|
||||
//Warning: this equals implementation needs to work correctly also for the subclass
|
||||
final CacheKey that = (CacheKey) other;
|
||||
return EqualsHelper.equals( entityOrRoleName, that.entityOrRoleName )
|
||||
&& type.isEqual( key, that.key )
|
||||
&& EqualsHelper.equals( tenantId, that.tenantId );
|
||||
return EqualsHelper.equals( getTenantId(), that.getTenantId() )
|
||||
&& type.isEqual( key, that.key );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -108,9 +119,4 @@ public class CacheKey implements Serializable {
|
|||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// Used to be required for OSCache
|
||||
return entityOrRoleName + '#' + key.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.hibernate.ScrollableResults;
|
|||
import org.hibernate.SessionEventListener;
|
||||
import org.hibernate.SessionException;
|
||||
import org.hibernate.SharedSessionContract;
|
||||
import org.hibernate.cache.internal.TenantAwareCacheKey;
|
||||
import org.hibernate.cache.spi.CacheKey;
|
||||
import org.hibernate.engine.jdbc.LobCreationContext;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
|
@ -329,7 +330,13 @@ public abstract class AbstractSessionImpl
|
|||
|
||||
@Override
|
||||
public CacheKey generateCacheKey(Serializable id, Type type, String entityOrRoleName) {
|
||||
return new CacheKey( id, type, entityOrRoleName, getTenantIdentifier(), getFactory() );
|
||||
final String tenantIdentifier = getTenantIdentifier();
|
||||
if ( tenantIdentifier == null ) {
|
||||
return new CacheKey( id, type, entityOrRoleName, getFactory() );
|
||||
}
|
||||
else {
|
||||
return new TenantAwareCacheKey( id, type, entityOrRoleName, getFactory(), tenantIdentifier );
|
||||
}
|
||||
}
|
||||
|
||||
private transient JdbcConnectionAccess jdbcConnectionAccess;
|
||||
|
|
|
@ -119,11 +119,11 @@ public class CacheImpl implements CacheImplementor {
|
|||
}
|
||||
|
||||
private CacheKey buildCacheKey(Serializable identifier, EntityPersister p) {
|
||||
// have to assume non tenancy
|
||||
return new CacheKey(
|
||||
identifier,
|
||||
p.getIdentifierType(),
|
||||
p.getRootEntityName(),
|
||||
null, // have to assume non tenancy
|
||||
sessionFactory
|
||||
);
|
||||
}
|
||||
|
@ -197,11 +197,11 @@ public class CacheImpl implements CacheImplementor {
|
|||
}
|
||||
|
||||
private CacheKey buildCacheKey(Serializable ownerIdentifier, CollectionPersister p) {
|
||||
// have to assume non tenancy
|
||||
return new CacheKey(
|
||||
ownerIdentifier,
|
||||
p.getKeyType(),
|
||||
p.getRole(),
|
||||
null, // have to assume non tenancy
|
||||
sessionFactory
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue