【问题标题】:how to avoid model code duplication with JSF and JPA如何避免与 JSF 和 JPA 的模型代码重复
【发布时间】:2010-07-13 08:11:02
【问题描述】:

我是 JSF 的新手,想知道我是否做对了。假设我有一个简单的 CMS,可以编写页面。

首先,我定义了一个名为 Page 的 JPA 实体:

@Entity
public class Page {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column
  private Long id;

  @Column private String title;

  @Column private String content;

  // getters & setters ...

}

然后我想在一个视图中创建Page-s。为此,看起来我需要某种页面 bean。现在我处理的事情是这样的:

@Model
public class PageBean {

  private Page page = new Page();

    public String getTitle() {
      return page.getTitle();
    }

    public void setTitle(String title) {
      page.setTitle(title);
    }

    // rest of properties & getters & setters ...

    public void save() {
      // persist using EntityManager
    }
 }

我的问题如下:鉴于我的 JPA 实体模型和我想在视图中使用的模型大部分时间完全相同,有没有办法避免必须创建一批 getter & PageBean 中的设置器?

我在某处读到你不应该使用与 JPA 实体和 JSF 模型 bean 相同的 bean(因为 JSF 会重复调用可能影响 JPA 的 getter),但我想知道是否没有更简单的方法可以帮助避免这种代码重复。尤其是当您的应用程序具有大型模型并且在许多情况下不需要视图 bean 中的任何特殊内容时,看起来这会变得非常麻烦。

【问题讨论】:

    标签: jsf jpa code-duplication


    【解决方案1】:

    [...] 鉴于我的 JPA 实体模型和我想在视图中使用的模型大部分时间完全相同,有没有办法避免必须在其中创建一批 getter 和 setter PageBean?

    我看不出在实体周围使用 包装器 并添加这样的层确实是重复。只需使用 JSF 页面中的实体。是的,这会在视图和域之间引入某种耦合,但一般来说,修改数据库通常意味着在视图上添加或删除字段。换句话说,我不相信“解耦”的说法,而且我已经编写了足够多的额外层、映射代码、样板代码等,以尽可能支持简单的方法。

    我在某处读到你不应该使用与 JPA 实体和 JSF 模型 bean 相同的 bean(因为 JSF 会重复调用可能影响 JPA 的 getter)

    如果您可以提供参考,我会很感兴趣,但如果某处出现问题,包装类(委托对实体的调用)不会改变任何东西。

    以防万一,一些额外的资源:

    【讨论】:

      【解决方案2】:

      这不是代码重复。没有重复的算法。业务逻辑仍在一处。

      您的 bean 所做的只是将视图连接到域模型。这很好,它是 MVC 模式的一部分。

      如果您使用 JPA 实体作为支持 bean,那么您将打破 MVC 模式。例如,如果有一天你不需要显示一个普通的String 而不是显示一个普通的Date 到这个String,因为视图需要这样(即接口要求),你是否要在 JPA 中编写这个视图逻辑班级?这没有意义,混合领域模型和视图模型。

      另一方面,为什么视图必须知道域是如何实现的?如果域值格式发生变化怎么办? (例如,出于性能原因,您在数据库中保存时间戳字符串而不是日期类)。您需要做的只是重写支持 bean 中的方法,它将获取时间戳并将其调整为 Date,以便一切都可以像以前一样工作。在 JPA 类之外只有一个变化。如果你在 JPA 类中拥有它,你最终会在一个类中维护这两种逻辑(接口逻辑和域逻辑)。

      如果您想开发一个新视图(例如移动版)怎么办?您要向 JPA 类添加更多代码吗?最好保持 JPA 原样并为移动版本创建另一个 Bean(为两个视图扩展一个公共 bean)。

      如果在这之后,你仍然不想写getter和setter,你可以这样做

      #{myBean.page.title}
      

      您只需要在 backing bean 中添加一个 getPage()

      【讨论】:

      • #{myBean.page.title} 正是他所需要的,并且已经足以作为完整的答案。大多数 JSF/EL 入门者不知道“深度链接”getter 的能力,因此认为有必要扁平化/锤击托管 bean 中的实体。
      • 我从一开始就知道他想要什么。但是我认为,一旦您意识到自己在做什么及其含义,就应该能够进行深度链接。这就是为什么我在答案之前写了“免责声明”部分。我在支持 bean 中使用了很多深度链接,但是在访问域模型中的字段时,我会考虑两次。
      猜你喜欢
      • 2016-02-29
      • 1970-01-01
      • 1970-01-01
      • 2021-11-07
      • 2011-08-29
      • 1970-01-01
      • 2021-04-28
      • 2011-04-16
      相关资源
      最近更新 更多