HHH-16545 PersistenceUtil.MetadataCache needs to be threadsafe
This commit is contained in:
parent
c4a3fbe550
commit
11982572bd
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.jpa.internal.util;
|
package org.hibernate.jpa.internal.util;
|
||||||
|
|
||||||
|
import java.io.ObjectStreamException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
@ -16,7 +17,7 @@ import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
|
||||||
import jakarta.persistence.spi.LoadState;
|
import jakarta.persistence.spi.LoadState;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
@ -411,24 +412,42 @@ public final class PersistenceUtilHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache hierarchy and member resolution in a weak hash map
|
* Cache hierarchy and member resolution, taking care to not leak
|
||||||
|
* references to Class instances.
|
||||||
*/
|
*/
|
||||||
//TODO not really thread-safe
|
public static final class MetadataCache implements Serializable {
|
||||||
public static class MetadataCache implements Serializable {
|
|
||||||
private transient Map<Class<?>, ClassMetadataCache> classCache = new WeakHashMap<>();
|
|
||||||
|
|
||||||
|
private final ClassValue<ClassMetadataCache> metadataCacheClassValue;
|
||||||
|
|
||||||
private void readObject(java.io.ObjectInputStream stream) {
|
public MetadataCache() {
|
||||||
classCache = new WeakHashMap<>();
|
this( new MetadataClassValue() );
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassMetadataCache getClassMetadata(Class<?> clazz) {
|
//To help with serialization: no need to serialize the actual metadataCacheClassValue field
|
||||||
ClassMetadataCache classMetadataCache = classCache.get( clazz );
|
private MetadataCache(ClassValue<ClassMetadataCache> metadataCacheClassValue) {
|
||||||
if ( classMetadataCache == null ) {
|
this.metadataCacheClassValue = metadataCacheClassValue;
|
||||||
classMetadataCache = new ClassMetadataCache( clazz );
|
}
|
||||||
classCache.put( clazz, classMetadataCache );
|
|
||||||
}
|
Object writeReplace() throws ObjectStreamException {
|
||||||
return classMetadataCache;
|
//Writing a different instance which doesn't include the cache
|
||||||
|
return new MetadataCache(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object readResolve() throws ObjectStreamException {
|
||||||
|
//Ensure we do instantiate a new cache instance on deserialization
|
||||||
|
return new MetadataCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassMetadataCache getClassMetadata(final Class<?> clazz) {
|
||||||
|
return metadataCacheClassValue.get( clazz );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class MetadataClassValue extends ClassValue<ClassMetadataCache> {
|
||||||
|
@Override
|
||||||
|
protected ClassMetadataCache computeValue(final Class type) {
|
||||||
|
return new ClassMetadataCache( type );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue