我试图习惯JSF如何处理数据(来自春天的背景)
我正在创建一个维护用户列表的简单示例,我有类似
的内容<h:dataTable value="#{userListController.userList}" var="u">
<h:column>#{u.userId}</h:column>
<h:column>#{u.userName}</h:column>
</h:dataTable>
然后&#34;控制器&#34;有类似
的东西@Named(value = "userListController")
@SessionScoped
public class UserListController {
@EJB
private UserListService userListService;
private List<User> userList;
public List<User> getUserList() {
userList = userListService.getUsers();
return userList;
}
}
&#34;服务&#34; (虽然看起来更像是DAO)
public class UserListService {
@PersistenceContext
private EntityManager em;
public List<User> getUsers() {
Query query = em.createQuery("SELECT u from User as u");
return query.getResultList();
}
}
这是正确的做事方式吗?我的术语是对的吗? &#34;服务&#34;感觉更像是DAO?控制器感觉它正在做一些服务工作。
答案 0 :(得分:64)
这是正确的做事方式吗?
除了在托管bean getter方法中执行业务逻辑效率低下的方法,并且使用过宽的托管bean范围外,它看起来还不错。如果您将服务调用从getter方法移至@PostConstruct
方法并使用@RequestScoped
或@ViewScoped
代替@SessionScoped
,则效果会更好。
我的术语是对的吗?
没关系。只要您与它保持一致并且代码以合理的方式可读。只有你命名类和变量的方式有点尴尬(不合逻辑和/或重复)。例如,我个人会使用users
代替userList
,而使用var="user"
代替var="u"
,并使用id
和name
代替userId
和userName
。此外,“UserListService”听起来似乎只能处理用户列表而不是一般用户。我宁愿使用“UserService”,因此您也可以使用它来创建,更新和删除用户。
“服务”感觉更像是DAO?
这不完全是DAO。基本上,JPA就是真正的DAO。以前,当JPA不存在时,每个人都会调出DAO接口,这样服务方法就可以继续使用它们,即使底层实现(“普通旧的”JDBC,或“老旧的”Hibernate等)发生了变化。服务方法的真正任务是透明地管理事务。这不是DAO的责任。
控制器感觉它正在做一些服务工作。
我可以想象它在这个相对简单的设置中做到了。但是,控制器实际上是前端的一部分而不是后端。该服务是后端的一部分,应该以这样的方式设计,它可以在所有不同的前端重复使用,例如JSF,JAX-RS,“普通”JSP + Servlet,甚至Swing等。此外,特定于前端的控制器(也称为“支持bean”或“presenter”)允许您以特定于前端的方式处理成功和/或异常结果,例如在JSF的情况下,如果从服务抛出异常,则显示faces消息。
总而言之,正确的方法如下:
<h:dataTable value="#{userBacking.users}" var="user">
<h:column>#{user.id}</h:column>
<h:column>#{user.name}</h:column>
</h:dataTable>
@Named
@RequestScoped // Use @ViewScoped once you bring in ajax (e.g. CRUD)
public class UserBacking {
private List<User> users;
@EJB
private UserService userService;
@PostConstruct
public void init() {
users = userService.listAll();
}
public List<User> getUsers() {
return users;
}
}
@Stateless
public class UserService {
@PersistenceContext
private EntityManager em;
public List<User> listAll() {
return em.createQuery("SELECT u FROM User u", User.class).getResultList();
}
}
你可以在这里找到一个真正的世界启动项目,利用规范的Java EE / JSF / CDI / EJB / JPA实践:Java EE kickoff app。
答案 1 :(得分:6)
这是一个dao,well actually a repository但是不要太担心这种差异,因为它正在使用持久化上下文访问数据库。
您应该创建一个服务类,它包装该方法并且是调用事务的位置。
有时服务类感觉不必要,但是当你有一个调用许多dao方法的服务方法时,更有必要使用它们。
我通常最终只是创建服务,即使它确实没有必要,以确保模式保持不变,并且dao永远不会直接注入。
这增加了额外的抽象层,使未来的重构更加灵活。