HHH-11097 - Performance problem if cached entity has attribute state with an expensive toString() method (LOB, etc)
This commit is contained in:
parent
a00a30f488
commit
c7c9e42145
|
@ -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 + "})";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue