![](/img/trans.png)
[英]Hibernate: How to test a JPA/Hibernate Predicate instance?
[英]JPA/Hibernate instance of not working
想象一种情况:
@javax.persistence.Inheritance(strategy=javax.persistence.InheritanceType.JOINED)
@javax.persistence.DiscriminatorColumn
@javax.persistence.Entity
@javax.persistence.Table(name="PARENT")
public abstract class Parent{
...
}
@javax.persistence.Entity
@javax.persistence.Table(name="A")
public class A extends Parent{
...
}
@javax.persistence.Entity
@javax.persistence.Table(name="B")
public class B extends Parent{
...
}
Parent p = new A();
现在我们称之为:
p instance of A
总是返回假!!
在 OpenJPA 上工作正常!
我应该提交错误吗? 休眠 4.3.10
这很可能是因为休眠状态返回了代理。
为什么这样做呢? 要实现延迟加载,框架需要拦截您的方法调用,这些方法返回延迟加载的对象或对象列表。 这样做是为了可以首先从数据库加载对象,然后允许您的方法运行。 Hibernate通过创建代理类来做到这一点。 如果您在调试中检查类型,则应该能够看到实际类型是生成的类,它不是从基类扩展的。
如何解决呢? 我曾经遇到这个问题,成功地使用了访问者模式,而不是使用instanceof
。 它确实增加了额外的复杂性,因此不是每个人都喜欢的模式,但是恕我直言,这是比使用instanceof
更干净的方法。
如果使用instanceof
则通常会以if...else
阻止检查不同类型。 随着添加更多类型,您将不得不重新访问每个这些块。 访问者模式的优势在于,条件逻辑内置于您的类层次结构中,因此,如果添加更多类型,则可以减少使用这些类的任何地方的更改。
在实现访客模式时,我发现本文很有用。
这是因为Hibernate在支持代理方法的同时使用了运行时代理和OpenJPA,而是倾向于编译时或运行时字节码增强。
看到:
http://openjpa.apache.org/entity-enhancement.html
//Hibernate
Entity e = repository.load(entityId); // may return a proxy
//OpenJPA
Entity e = repository.load(entityId); //will return an (enhanced) actual instance of E
Hibernate返回代理对象。 而不是实现Visitor模式(如描述在这里 ),你可以使用isAssignableFrom()
你要测试的类方法( https://docs.oracle.com/javase/8/docs/api/java/lang/ Class.html#isAssignableFrom-java.lang.Class- )。
不确定,但是我认为这会起作用。
public static boolean instanceOf(Object object, Class<?> superclass) {
return superclass.isAssignableFrom(Hibernate.getClass(object));
}
您可以尝试取消代理您的对象:
/**
*
* @param <T>
* @param entity
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T initializeAndUnproxy(T entity) {
if (entity == null) {
// throw new NullPointerException("Entity passed for initialization is null");
return null;
}
Hibernate.initialize(entity);
if (entity instanceof HibernateProxy) {
entity = (T) ((HibernateProxy) entity).getHibernateLazyInitializer().getImplementation();
}
return entity;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.