我正在尝试为以下场景找到最佳解决方案:我有一个必须代理的实体A.问题是当我这样做只是通过扩展类A,使一个抽象代理将其所有行为委托给包装的实体,我最终得到了大量从该实体继承的未使用的字段。但至少它不会改变持久性的工作方式。
为了不这样做,我创建了一个抽象超类,它只包含抽象方法(公共和受保护,这就是为什么我没有使用接口)并使它成为实体和所有实体的超类代理。这个解决方案看起来效果最好,但在持久性问题上会遇到很多麻烦......
我想依赖我的应用层中的抽象超类(因为它不区分代理A和非代理A)但是Hibernate不会让我 - 实体实例不能与之关系抽象类,因为持久化上下文不知道它。当然,我可以贬低实体类,但它会破坏目的......
有没有办法让Hibernate为自己贬低实体?我的意思是我可以在任何地方使用抽象类,但Hibernate会知道它实际上是实体类......
public abstract class AbstractA {
public abstract void doSomethingOnA();
}
@Entity
public class EntityA extends AbstractA {
@Id
private Long id;
@Column(name="column_in_a")
private SomethingA somethingA;
@Override
public void doSomethingOnA() {
somethingA.doSomething();
}
}
public class ProxiedA extends AbstractA {
private AbstractA wrappee;
@Override
public void doSomethingOnA() {
doSomethingFirst();
wrappee.doSomethingOnA();
}
}
问题是我想在持久性方面使用AbstractA而不是EntityA。问题是,当另一个实体声明一个AbstractA类型的字段时,Hibernate将失败。我知道为什么,问题是如何处理它?</ p>
谢谢!
答案 0 :(得分:1)
我倾向于创建一个界面,例如User。然后我将有一个名为UserBean的POJO和一个实现该接口的实体调用UserEntity。然后,您可以执行以下两项操作之一:在实体中使用构造函数获取bean,使用createBean方法从实体创建bean。我没有在bean类中放置实体的构造函数,因为在我的场景中我有一个没有JPA访问权限的层,因此bean不能对实体有任何了解。
Hibernate或任何JPA提供程序都会知道它何时获得真正的UserEntity,并且如果您不小心向其发送了UserBean,它会正确地抱怨。通常我甚至没有这些实现相同的接口。这样我就可以强制执行我不会在持久性边界上意外发送UserEntity而不是UserBean。
然后,我可能会误解你的问题,因为代理这个词有很多含义。例如,您可能正在谈论延迟加载代理作为实体的属性。或者你可能在谈论远程代理。
答案 1 :(得分:1)
如果没有看到代码,理解您所描述的内容将是一项挑战。但在阅读完您的描述后,这里有一些想法:
EntityA
会导致许多不需要的成员,那么您的子类就不会觉得它确实是一个子类。子类的一个实例实际上是 EntityA
的一个实例,实际上只是专门化行为并可能扩展EntityA
父类的成员变量。EntityA
的许多字段,那么您将遇到“不需要的”关系属性可能需要特殊处理或某种工作的问题在子类对象中进行编码。同样,没有代码可以审查是很难具体的,但听起来你可能想要从重构EntityA
和你的抽象类共有的成员,包括变量和操作开始共同的父类。然后可以对父类进行注释以包含映射到列的真实实体属性。从那里,您可以使用简单的Java继承和一个Hibernate继承模式来完成您的实现:
<class>
标记定义,不需要额外的处理来处理多态,因为Hibernate将扫描持久化类并了解超类或接口。<union-subclass>
标记进行定义,在不需要多态查询和使用时({{1})效果最佳可能涉及非持久性接口的查询(听起来可能是您的情况)。UNION
标记进行定义。 <joined-subclass>
标记定义,是最简单且性能最佳的,因为所有子类都映射到单个table,但仅在为子类定义的唯一列可能为<subclass>
时才有效。