【问题标题】:Proxy pattern when an Entity is to be proxied?代理实体时的代理模式?
【发布时间】:2014-01-25 14:29:58
【问题描述】:

我正在尝试为以下情况找到最佳解决方案:我有一个必须代理的实体 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 将失败。我知道为什么,问题是如何处理?

谢谢!

【问题讨论】:

    标签: java hibernate jpa proxy


    【解决方案1】:

    我倾向于创建一个界面,例如 User.然后我将有一个名为 UserBean 的 POJO 和一个名为 UserEntity 的实体,它们都实现了该接口。然后您可以做以下两件事之一:在实体中有一个构造函数来获取 bean 和一个 createBean 方法来从实体创建 bean。我没有在 bean 类中放置实体的构造函数,因为在我的场景中,我有一个没有 JPA 访问权限的层,因此 bean 无法了解实体。

    Hibernate 或任何 JPA 提供者都会知道它何时获得了真正的 UserEntity,并且如果您不小心向它发送了 UserBean,它们会正确地抱怨。很多时候我什至没有这些实现相同的接口。这样我就可以强制我不会意外地发送 UserEntity 而不是 UserBean 跨越持久性边界。

    再一次,我可能会误解你的问题,因为代理这个词有很多含义。例如,您可以将延迟加载代理作为实体的属性进行讨论。或者您可能正在谈论远程代理。

    【讨论】:

      【解决方案2】:

      在没有看到代码的情况下,很难理解您所描述的内容。但是看完你的描述,有一些想法:

      • 从面向对象的角度来看,如果扩展EntityA 会导致许多不需要的成员,那么您的子类不会感觉它是真正的子类。子类的实例实际上应该是EntityA 的实例,实际上只是专门化行为并可能扩展EntityA 父类的成员变量。
      • 从持久性的角度来看,如果您的子类不打算使用构成EntityA 的许多字段,您将面临“不需要的”关系属性可能需要特殊处理或某种变通方法的问题在您的子类对象中编码。

      再一次,如果没有代码审查就很难具体化,但听起来您可能希望首先将 EntityA 和您的抽象类共有的成员(变量和操作)重构为一个共同的父类班级。然后可以注释父类以包含映射到列的真实实体属性。从那里,您可以使用简单的 Java 继承和 Hibernate 继承模式之一来完成您的实现:

      • Table per concrete subclass,可以在 Hibernate xml 映射中使用 <class> 标记定义,不需要额外的处理来处理多态性,因为 Hibernate 将扫描持久类并了解超类或接口。
      • Table per concrete subclass with unions,可以在 Hibernate xml 映射中使用 <union-subclass> 标记定义,当您不需要多态查询并使用(基于UNION)可能涉及非- 持久接口(听起来可能是您的情况)。
      • Table per concrete subclass with joins,可以在 Hibernate xml 映射中使用 <joined-subclass> 标记定义,如果您想要(或必须使用)完全规范化的数据库模式,这是最好的选择。
      • Table per class hierarchy,可以在 Hibernate xml 映射中使用 <subclass> 标记定义,是最简单且性能最好的,因为所有子类都映射到单个表,但会仅当为子类定义的唯一列可能是 NULL 时才有效。

      【讨论】:

      • 问题是我提到的那些代理不能被持久化。它们被包裹在没有任何兄弟实体的单个实体周围。请查看我更新的问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 2011-10-12
      • 2014-05-23
      • 1970-01-01
      • 2011-03-04
      • 1970-01-01
      相关资源
      最近更新 更多