如何使用 JSF 和 JPA 避免模型代码重复

发布于 2024-09-09 08:58:12 字数 1011 浏览 11 评论 0原文

我是 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 实体模型和我想在视图中使用的模型大多数时候完全相同,是否有一种方法可以避免创建一批吸气剂和PageBean 中的设置器?

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

I'm new to JSF and am wondering if I got things right. Let's say I have a simple CMS that makes it possible to write pages.

First, I define a JPA entity called Page:

@Entity
public class Page {

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

  @Column private String title;

  @Column private String content;

  // getters & setters ...

}

Then I would like in a view to create Page-s. For that, it looks like I need a page bean of some sort. For now I handled things like this:

@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
    }
 }

My question is the following one: given that my JPA entity model and the model I want to use in the views are most of the time exactly the same, is there a way of avoiding to have to create a batch of getters & setters in the PageBean?

I read somewhere that you should not use a same bean as JPA entity and JSF model bean (because JSF does repeated calls to getters that may affect JPA), yet I do wonder if there is not a simpler way that would help avoiding this kind of code duplication. Especially when you've got an application with a large model and in many instances do not require anything special in the view beans, it looks like this can get quite cumbersome.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

新一帅帅 2024-09-16 08:58:12

[...] 鉴于我的 JPA 实体模型和我想在视图中使用的模型大多数时候完全相同,是否有办法避免创建一批 getter 和 getter? PageBean 中的设置器?

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

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

如果您可以提供一个引用,但提供一个包装类(将调用委托给如果某个地方出现问题,实体)不会改变任何事情。

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

[...] given that my JPA entity model and the model I want to use in the views are most of the time exactly the same, is there a way of avoiding to have to create a batch of getters & setters in the PageBean?

I don't see the point of using a wrapper around an Entity and adding such a layer is indeed duplication. Just use the entity from your JSF page. Yes, this introduce some sort of coupling between the view and the domain but, in general, modifying the database usually means adding or removing fields on the view. In other words, I don't buy the "decoupling" argument and I've written enough extra layers, mapping code, boilerplate code, etc to favor the simple approach when possible.

I read somewhere that you should not use a same bean as JPA entity and JSF model bean (because JSF does repeated calls to getters that may affect JPA)

I'd be interested if you could provide a reference but a wrapper class (delegating calls to the entity) is not going to change anything if there is a problem somewhere.

Just in case, some additional resources:

倾`听者〃 2024-09-16 08:58:12

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

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

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

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

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

如果在完成这一切之后,您仍然不想编写 getter 和 setter,您

#{myBean.page.title}

只需在支持 bean 中使用 getPage() 即可。

It's not code duplication. The are no algorithms duplicated. The business logic is still in one place.

What your bean is doing is just connecting the View to the Domain model. This is good, it's part of the MVC pattern.

If you were using your JPA entity as your backing bean, you would be breaking the MVC pattern. For example, if one day instead of displaying a plain String you would need to add a Date to this String because the view requires so (i.e. interface requirements), are you going to write this view logic inside the JPA class? That does not make sense, mixing domain model and view model.

On the other hand, why the view has to know about how the domain is implemented? What if the domain values format change? (For example you save a timestamp String instead a date class in de Database for performance reasons). All you would need to do is just rewrite the method in the backing bean, it would take the timestamp and adapt it to a Date so everything would work as it was before. Just one change outside the JPA class. If you had it in the JPA class you would end up maintaining both logics in just one class (interface logic and domain logic).

What if you want to develop a new view (for example for mobile version)? Are you gonna add even more code to the JPA class? It would be better to keep the JPA as it was and create another Bean (that extends a common bean for both views) for the mobile version.

If after all this, you still want to not to write the getters and setters, you can do

#{myBean.page.title}

all you need is a getPage() inside the backing bean.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文