HHH-11097 - Performance problem if cached entity has attribute state with an expensive toString() method (LOB, etc)

This commit is contained in:
Steve Ebersole 2016-09-13 17:00:02 -05:00
parent a00a30f488
commit c7c9e42145
7 changed files with 49 additions and 6 deletions

View File

@ -18,7 +18,6 @@ import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PreLoadEvent;
import org.hibernate.event.spi.PreLoadEventListener;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.TypeHelper;
@ -29,8 +28,9 @@ import org.hibernate.type.TypeHelper;
*/
public class StandardCacheEntryImpl implements CacheEntry {
private final Serializable[] disassembledState;
private final String subclass;
private final String disassembledStateText;
private final Object version;
private final String subclass;
/**
* Constructs a StandardCacheEntryImpl
@ -57,12 +57,18 @@ public class StandardCacheEntryImpl implements CacheEntry {
session,
owner
);
subclass = persister.getEntityName();
this.disassembledStateText = TypeHelper.toLoggableString(
state,
persister.getPropertyTypes(),
session.getFactory()
);
this.subclass = persister.getEntityName();
this.version = version;
}
StandardCacheEntryImpl(Serializable[] state, String subclass, Object version) {
StandardCacheEntryImpl(Serializable[] state, String disassembledStateText, String subclass, Object version) {
this.disassembledState = state;
this.disassembledStateText = disassembledStateText;
this.subclass = subclass;
this.version = version;
}
@ -163,6 +169,6 @@ public class StandardCacheEntryImpl implements CacheEntry {
@Override
public String toString() {
return "CacheEntry(" + subclass + ')' + ArrayHelper.toString( disassembledState );
return "CacheEntry(" + subclass + " {" + disassembledStateText + "})";
}
}

View File

@ -13,6 +13,7 @@ import java.util.Set;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.TypeHelper;
/**
* Structured CacheEntry format for entities. Used to store the entry into the second-level cache
@ -48,7 +49,12 @@ public class StructuredCacheEntry implements CacheEntryStructure {
for ( int i = 0; i < names.length; i++ ) {
state[i] = (Serializable) map.get( names[i] );
}
return new StandardCacheEntryImpl( state, subclass, version );
return new StandardCacheEntryImpl(
state,
TypeHelper.toLoggableString( state, subclassPersister.getPropertyTypes(), factory ),
subclass,
version
);
}
@Override

View File

@ -38,4 +38,5 @@ public class BlobType extends AbstractSingleColumnStandardBasicType<Blob> {
protected Blob getReplacement(Blob original, Blob target, SharedSessionContractImplementor session) {
return session.getJdbcServices().getJdbcEnvironment().getDialect().getLobMergeStrategy().mergeBlob( original, target, session );
}
}

View File

@ -10,6 +10,7 @@ import java.io.Serializable;
import java.util.Map;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
import org.hibernate.tuple.NonIdentifierAttribute;
@ -360,4 +361,18 @@ public class TypeHelper {
return trimmed;
}
}
public static String toLoggableString(
Object[] state,
Type[] types,
SessionFactoryImplementor factory) {
final StringBuilder buff = new StringBuilder();
for ( int i = 0; i < state.length; i++ ) {
if ( i > 0 ) {
buff.append( ", " );
}
buff.append( types[i].toLoggableString( state[i], factory ) );
}
return buff.toString();
}
}

View File

@ -61,6 +61,11 @@ public class BlobTypeDescriptor extends AbstractTypeDescriptor<Blob> {
super( Blob.class, BlobMutabilityPlan.INSTANCE );
}
@Override
public String extractLoggableRepresentation(Blob value) {
return value == null ? "null" : "BLOB{...}";
}
@Override
public String toString(Blob value) {
final byte[] bytes;

View File

@ -55,6 +55,11 @@ public class ClobTypeDescriptor extends AbstractTypeDescriptor<Clob> {
super( Clob.class, ClobMutabilityPlan.INSTANCE );
}
@Override
public String extractLoggableRepresentation(Clob value) {
return value == null ? "null" : "CLOB{...}";
}
public String toString(Clob value) {
return DataHelper.extractString( value );
}

View File

@ -55,6 +55,11 @@ public class NClobTypeDescriptor extends AbstractTypeDescriptor<NClob> {
super( NClob.class, NClobMutabilityPlan.INSTANCE );
}
@Override
public String extractLoggableRepresentation(NClob value) {
return value == null ? "null" : "NCLOB{...}";
}
public String toString(NClob value) {
return DataHelper.extractString( value );
}