And*_*gin 153 java proxy hibernate jpa lazy-loading
在Hibernate期间Session,我正在加载一些对象,并且由于延迟加载,其中一些被加载为代理.一切都好,我不想把懒人装完.
但后来我需要通过RPC将一些对象(实际上是一个对象)发送到GWT客户端.碰巧这个具体对象是代理.所以我需要把它变成一个真实的对象.我在Hibernate中找不到类似"实现"的方法.
如何知道他们的类和ID,将一些对象从代理转换为实际?
目前,我看到的唯一解决方案是从Hibernate的缓存中驱逐该对象并重新加载它,但由于许多原因它真的很糟糕.
Boz*_*zho 227
这是我正在使用的方法.
public static <T> T initializeAndUnproxy(T entity) {
if (entity == null) {
throw new
NullPointerException("Entity passed for initialization is null");
}
Hibernate.initialize(entity);
if (entity instanceof HibernateProxy) {
entity = (T) ((HibernateProxy) entity).getHibernateLazyInitializer()
.getImplementation();
}
return entity;
}
Run Code Online (Sandbox Code Playgroud)
Vla*_*cea 32
正如我在本文中解释的那样,自Hibernate ORM 5.2.10以来,你可以这样做:
Object unproxiedEntity = Hibernate.unproxy(proxy);
Run Code Online (Sandbox Code Playgroud)
在Hibernate 5.2.10之前.最简单的方法是使用Hibernate内部实现提供的unproxy方法PersistenceContext:
Object unproxiedEntity = ((SessionImplementor) session)
.getPersistenceContext()
.unproxy(proxy);
Run Code Online (Sandbox Code Playgroud)
小智 13
我编写了以下代码来清除代理中的对象(如果它们尚未初始化)
public class PersistenceUtils {
private static void cleanFromProxies(Object value, List<Object> handledObjects) {
if ((value != null) && (!isProxy(value)) && !containsTotallyEqual(handledObjects, value)) {
handledObjects.add(value);
if (value instanceof Iterable) {
for (Object item : (Iterable<?>) value) {
cleanFromProxies(item, handledObjects);
}
} else if (value.getClass().isArray()) {
for (Object item : (Object[]) value) {
cleanFromProxies(item, handledObjects);
}
}
BeanInfo beanInfo = null;
try {
beanInfo = Introspector.getBeanInfo(value.getClass());
} catch (IntrospectionException e) {
// LOGGER.warn(e.getMessage(), e);
}
if (beanInfo != null) {
for (PropertyDescriptor property : beanInfo.getPropertyDescriptors()) {
try {
if ((property.getWriteMethod() != null) && (property.getReadMethod() != null)) {
Object fieldValue = property.getReadMethod().invoke(value);
if (isProxy(fieldValue)) {
fieldValue = unproxyObject(fieldValue);
property.getWriteMethod().invoke(value, fieldValue);
}
cleanFromProxies(fieldValue, handledObjects);
}
} catch (Exception e) {
// LOGGER.warn(e.getMessage(), e);
}
}
}
}
}
public static <T> T cleanFromProxies(T value) {
T result = unproxyObject(value);
cleanFromProxies(result, new ArrayList<Object>());
return result;
}
private static boolean containsTotallyEqual(Collection<?> collection, Object value) {
if (CollectionUtils.isEmpty(collection)) {
return false;
}
for (Object object : collection) {
if (object == value) {
return true;
}
}
return false;
}
public static boolean isProxy(Object value) {
if (value == null) {
return false;
}
if ((value instanceof HibernateProxy) || (value instanceof PersistentCollection)) {
return true;
}
return false;
}
private static Object unproxyHibernateProxy(HibernateProxy hibernateProxy) {
Object result = hibernateProxy.writeReplace();
if (!(result instanceof SerializableProxy)) {
return result;
}
return null;
}
@SuppressWarnings("unchecked")
private static <T> T unproxyObject(T object) {
if (isProxy(object)) {
if (object instanceof PersistentCollection) {
PersistentCollection persistentCollection = (PersistentCollection) object;
return (T) unproxyPersistentCollection(persistentCollection);
} else if (object instanceof HibernateProxy) {
HibernateProxy hibernateProxy = (HibernateProxy) object;
return (T) unproxyHibernateProxy(hibernateProxy);
} else {
return null;
}
}
return object;
}
private static Object unproxyPersistentCollection(PersistentCollection persistentCollection) {
if (persistentCollection instanceof PersistentSet) {
return unproxyPersistentSet((Map<?, ?>) persistentCollection.getStoredSnapshot());
}
return persistentCollection.getStoredSnapshot();
}
private static <T> Set<T> unproxyPersistentSet(Map<T, ?> persistenceSet) {
return new LinkedHashSet<T>(persistenceSet.keySet());
}
}
Run Code Online (Sandbox Code Playgroud)
我在RPC服务的结果(通过方面)上使用此函数,并且它从代理中递归清除所有结果对象(如果它们未初始化).
小智 12
尝试使用 Hibernate.getClass(obj)
小智 8
我推荐JPA 2的方式:
Object unproxied = entityManager.unwrap(SessionImplementor.class).getPersistenceContext().unproxy(proxy);
Run Code Online (Sandbox Code Playgroud)
从Hiebrnate 5.2.10开始,您可以使用Hibernate.proxy方法将代理转换为真实实体:
MyEntity myEntity = (MyEntity) Hibernate.unproxy( proxyMyEntity );
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
86146 次 |
| 最近记录: |