【问题标题】:Hibernate, sub-classing and the visitor patternHibernate、子分类和访问者模式
【发布时间】:2012-08-14 23:27:48
【问题描述】:

我可能使用了错误的词,所以当我说业务对象 (BO) 时,我的意思是一个类,它引用了通过 Hibernate 映射到数据库表的类以及业务逻辑。

我面临的问题是在不使用反射或 instanceof 的情况下为子类实例化正确的 BO。

例如,假设我有一个 Pen-table,其中单个引用 Animal-table,而 Animal-table 又具有两个子表 Cat 和 Dog(都是一对一的引用)。这些类看起来有点像这样:

public class Pen {
    private Animal a;
    // Getters and setters
}
public class Animal {
    // Getters and setters
}
public class Dog extends Animal {
    // Getters and setters
}
public class Cat extends Animal {
    // Getters and setters
}
public class PenBO {
    private Pen p;
    public AnimalBO getAnimalBO() { ... }
}
public interface Action {
    void visit(DogBO dbo);
    void visit(CatBO cbo);
}
public class Sound implements Action {
    void visit(DogBO dbo) { ... }
    void visit(CatBO cbo) { ... }
}
public interface AnimalBO {
    void accept(Sound s);
}
public class DogBO implements AnimalBO {
    Dog d;
    void accept(Sound s) {
        s.visit(this);
    }
}
public class CatBO implements AnimalBO {
    Cat c;
    void accept(Sound s) {
        s.visit(this);
    }
}

然后我只使用 BO 在 BO 的 get-methods 中像这样实例化它们:

Pen p = ... // Get or load from database 
PenBO pbo = new PenBO();
pbo.setPen(p);

然后我使用这样的类:

pbo.getAnimalBO().accept(new Sound());

这是我正在研究的 getAnimalBO 方法。我希望它根据 Pen 的 Animal-instance 返回正确的 BO 实例。

我“可以”使用 instanceof 检查当前 Pen 中的实际 Animal,但这显然不是很漂亮。我正在考虑的另一种选择是使用反射来获取类名并在之后添加“BO”并获取它的实例,但是它也很丑陋。

我尝试在 getAnimalBO 周围包装另一个访问者模式,但它无法选择正确的访问方法而不进行强制转换,我不想将接受方法添加到非 BO 类中。

如果没有聪明的方法让该方法有效地发挥作用,那么核心问题是什么?我还没有真正找到 Hibernate 的任何最佳实践。 Hibernate 和访问者模式的一些示例只是将接受方法添加到映射的类中,这不是很好......

【问题讨论】:

    标签: hibernate visitor-pattern table-per-subclass


    【解决方案1】:

    您的问题实际上只是一个与继承有关的 OO 问题,并且从一个类层次结构转换为并行层次结构。您已经解决了这个和 Hibernate 映射的数据库建模,显然您的访问者实现没有任何问题。只是您不想将访问者模式应用于映射的类层次结构,因此您在两个层次结构之间转换时给自己造成了问题。

    就目前情况而言,您的部分代码将不得不负责知道CatBO 对应于Cat 等,以及知道Pen 对象的Animal 属性是否实际上是@ 987654325@,那么包含PenBO 对象的AnimalBO 属性实际上将是CatBO。鉴于此,它必须能够确定返回的Animal 实例的类型,所以我看不出如何避免使用instanceof 或反射之一。你对instanceof有什么异议?我同意,获取类名并附加“BO”的反射是非常讨厌和丑陋的,尽管它显然可以工作。但是,在这种情况下,恕我直言,单一方法的职责是通过使用instanceof 并选择正确的BO 类来获取Animal 并返回合适的AnimalBO,这并不是一件坏事。

    我要问的问题是,为什么您要从一个类层次结构映射到另一个这样的层次结构。您说过您不想想要accept 方法添加到映射的类中,并且它“不好”,但您没有t证明你为什么会有这种感觉。它是否比您已经提出的选择更糟糕?通过将访问者模式添加到映射的类层次结构中,您实际上并没有在其中嵌入任何业务逻辑,您只是使用访问者模式启用跨层次结构的业务逻辑应用程序。因此,您的业务逻辑层包含简单、通用的访问者实现,您的映射类或域层是 POJO 加上基本的访问者实现,并且您确实拥有我认为您想要的很好的干净分离。

    【讨论】:

    • 感谢您的回答!很抱歉,我没有给出不想使用 instanceof 或 relfection 的理由。在添加新课程或必须留下新课程最后需要“BO”的注释时,它需要一个额外的地方来更新,这是很正常的。我认为您对映射类中的接受方法也提出了一个很好的观点,我可能会接受它。在映射的类中只使用 getter 和 setter 来创建一个额外的 BO 类并为每个新的 Animal 子类添加一个 instanceof 并不重要。
    猜你喜欢
    • 2017-06-29
    • 1970-01-01
    • 2022-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-20
    • 2022-12-04
    • 1970-01-01
    相关资源
    最近更新 更多