JSF Controller 、服务和 DAO

标签 jsf jakarta-ee jpa ejb dao

我正在尝试习惯 JSF 在访问数据方面的工作方式(来自 spring 背景)

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

<h:dataTable value="#{userListController.userList}" var="u">
    <h:column>#{u.userId}</h:column>
    <h:column>#{u.userName}</h:column>
</h:dataTable>

然后“ Controller ”有类似的东西

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

    private List<User> userList;

    public List<User> getUserList() {
        userList = userListService.getUsers();
        return userList;
    }
}

“服务”(虽然它看起来更像是一个 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();
    }
}

这是正确的做事方式吗?我的术语正确吗? “服务”感觉更像是 DAO? Controller 感觉它正在执行服务的一些工作。

最佳答案

Is this the correct way of doing things?

除了在托管 bean getter 方法中以低效的方式执行业务逻辑以及使用太宽的托管 bean 范围之外,它看起来还不错。如果将服务调用从 getter 方法移至 @PostConstruct 方法,并使用 @RequestScoped@ViewScoped 而不是 @SessionScoped,看起来会更好。

另请参阅:

<小时/>

Is my terminology right?

没关系。只要您与它保持一致并且代码可以以合理的方式可读。只是您命名类和变量的方式有点尴尬(不合逻辑和/或重复)。例如,我个人会使用 users 而不是 userList,使用 var="user" 而不是 var="u",并使用 idname 而不是 userIduserName。此外,“UserListService”听起来好像只能处理用户列表,而不是一般用户。我宁愿使用“UserService”,这样您也可以使用它来创建、更新和删除用户。

另请参阅:

<小时/>

The "service" feels more like a DAO?

它并不完全是一个 DAO。基本上,JPA 才是真正的 DAO。以前,当 JPA 不存在时,每个人都自行开发 DAO 接口(interface),以便即使底层实现(“普通的旧”JDBC 或“好旧”Hibernate 等)发生变化,服务方法也可以继续使用它们。服务方法的真正任务是透明地管理事务。这不是 DAO 的责任。

另请参阅:

<小时/>

And the controller feels like it's doing some of the job of the service.

我可以想象它在这个相对简单的设置中做到了这一点。然而, Controller 实际上是前端的一部分而不是后端。该服务是后端的一部分,应该以这样的方式设计,以使其在所有不同前沿中都可以重复使用,例如JSF,JAX-RS,“Plain” JSP+Servlet,什至摇摆,挥杆等。此外,此外,此外,前端特定的 Controller (也称为“Backing Bean”或“Beacking Bean”或“Edrestrer”)允许您列出列为“成功”和“exclort and Offort in Casef”的示例。服务。

另请参阅:

<小时/>

总而言之,正确的方法如下:

<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 .

另请参阅:

关于JSF Controller 、服务和 DAO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38828482/

相关文章:

java - JSF/JPA 值绑定(bind)表达式未设置实体 bean 的属性

java - 如何防止使用 Hibernate 的 Java 应用程序丢失更新?

java - 处理 JPA 的附加字段

java - 由于某种原因,JSP 文档输出 XML 而不是 HTML

java - 如何设置 <p :selectOneMenu 的默认值

java - SessionMap 不保存 JSF 对象

java - 有没有办法自动更新jpa中的实体类?

java - 使用单选按钮组时的疑问(JSF 2.0)

java - JPA/hibernate : schema generation with multiple persistence units

使用多线程的 Java Rest 客户端