我是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中的setter?
我在某处读到你不应该使用与JPA实体和JSF模型bean相同的bean(因为JSF会重复调用可能影响JPA的getter),但我想知道是否有一种更简单的方法可以帮助避免这种代码重复。特别是当你有一个大型模型的应用程序,并且在许多情况下,视图bean中不需要任何特殊的东西,看起来这可能会非常麻烦。
答案 0 :(得分:4)
鉴于我的JPA实体模型和我想在视图中使用的模型大部分时间完全相同,是否有办法避免必须创建一批getter& amp; PageBean中的setter?
我没有看到在实体周围使用包装器的意义,并且添加这样的层确实是重复的。只需使用JSF页面中的实体即可。是的,这会在视图和域之间引入某种耦合,但通常,修改数据库通常意味着在视图上添加或删除字段。换句话说,我不会购买“解耦”参数,并且我已经编写了足够的额外层,映射代码,样板代码等,以便在可能的情况下采用简单的方法。
我在某处读到你不应该使用与JPA实体和JSF模型bean相同的bean(因为JSF会重复调用可能影响JPA的getter)
如果你能提供引用我会感兴趣但是如果某个地方出现问题,包装类(委托对实体的委托)不会改变任何东西。
以防万一,其他一些资源:
答案 1 :(得分:2)
这不是代码重复。没有算法重复。业务逻辑仍在一个地方。
您的bean正在做的只是将View连接到Domain模型。这很好,它是MVC模式的一部分。
如果您使用JPA实体作为支持bean,那么您将破坏MVC模式。例如,如果有一天而不是显示普通String
,则需要向此Date
添加String
,因为视图需要这样(即接口要求),您要写吗?这个视图逻辑在JPA类中?这没有意义,混合域模型和视图模型。
另一方面,为什么视图必须知道域的实现方式?如果域值格式发生变化怎么办? (例如,出于性能原因,您在de Database中保存时间戳字符串而不是日期类)。你需要做的只是重写支持bean中的方法,它需要时间戳并使其适应日期,所以一切都会像以前一样工作。只是JPA课程之外的一个变化。如果你在JPA类中使用它,你最终只会在一个类中维护逻辑(接口逻辑和域逻辑)。
如果您想开发新视图(例如移动版),该怎么办?你要为JPA课程添加更多代码吗?最好保持JPA不变,并为移动版本创建另一个Bean(扩展两个视图的公共bean)。
如果在这之后,你仍然想不写getter和setter,你可以做
#{myBean.page.title}
你需要的只是支持bean内的getPage()
。