JSF控制器,服务和DAO

PDS*_*tat 32 jsf dao ejb jpa java-ee

我正在尝试习惯JSF如何处理数据(来自弹簧背景)

我正在创建一个维护用户列表的简单示例,我有类似的东西

<h:dataTable value="#{userListController.userList}" var="u">
    <h:column>#{u.userId}</h:column>
    <h:column>#{u.userName}</h:column>
</h:dataTable>
Run Code Online (Sandbox Code Playgroud)

然后"控制器"有类似的东西

@Named(value = "userListController")
@SessionScoped
public class UserListController {
    @EJB
    private UserListService userListService;

    private List<User> userList;

    public List<User> getUserList() {
        userList = userListService.getUsers();
        return userList;
    }
}
Run Code Online (Sandbox Code Playgroud)

而"服务"(虽然看起来更像是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();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是正确的做事方式吗?我的术语是对的吗?"服务"感觉更像是DAO?控制器感觉它正在做一些服务工作.

Bal*_*usC 68

这是正确的做事方式吗?

除了在托管bean getter方法中执行业务逻辑效率低下的方法,并使用过宽的托管bean范围外,它看起来还不错.如果将服务调用从getter方法移动到@PostConstruct方法并使用@RequestScoped@ViewScoped代替@SessionScoped,则看起来会更好.

也可以看看:


我的术语是对的吗?

没关系.只要您与它保持一致并且代码以合理的方式可读.只有你命名类和变量的方式有点尴尬(不合逻辑和/或重复).举例来说,我个人会用users,而不是userList和使用var="user"代替var="u",并用idname,而不是userIduserName.此外,"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>
Run Code Online (Sandbox Code Playgroud)
@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;
    }

}
Run Code Online (Sandbox Code Playgroud)
@Stateless
public class UserService {

    @PersistenceContext
    private EntityManager em;

    public List<User> listAll() {
        return em.createQuery("SELECT u FROM User u", User.class).getResultList();
    }

}
Run Code Online (Sandbox Code Playgroud)

您可以在这里找到一个真正的世界启动项目,利用规范的Java EE/JSF/CDI/EJB/JPA实践:Java EE启动应用程序.

也可以看看:

  • @LyK:您不应该在前端的所有会话中缓存DB结果.您应该将它们缓存在后端的单个位置.JPA提供二级缓存可能性.另外一个优点是,它准确地知道何时使高速缓存的实体无效. (4认同)
  • @Tiny:也许这个答案有助于理解 DAO 模式背后的原始意图:http://stackoverflow.com/questions/7070467/dao-and-jdbc-relation/ (2认同)

Nim*_*sky 6

它是一个dao,实际上是一个存储库,但不要太担心这种差异,因为它使用持久化上下文访问数据库.

您应该创建一个服务类,它包装该方法并且是调用事务的位置.

有时服务类感觉不必要,但是当你有一个调用许多dao方法的服务方法时,更有必要使用它们.

我通常最终只是创建服务,即使它确实没有必要,以确保模式保持不变,并且dao永远不会直接注入.

这增加了额外的抽象层,使未来的重构更加灵活.


归档时间:

查看次数:

25541 次

最近记录:

5 年,10 月 前