JSF-контроллер, служба и DAO

Я пытаюсь привыкнуть к тому, как работает JSF в отношении доступа к данным (исходя из фона spring)

Я создаю простой пример, который поддерживает список пользователей, у меня есть что-то вроде

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

Тогда "контроллер" имеет что-то вроде

@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? И диспетчер чувствует, что он выполняет некоторую работу службы.

Ответы

Ответ 1

Это правильный способ сделать что-то?

Помимо выполнения бизнес-логики неэффективный способ использования управляемого метода bean и использование слишком широкой управляемой области 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 + сервлет, даже Swing и т.д. Кроме того, контроллер, специфичный для интерфейса ( также называемый "поддержка bean" или "презентатор" ) позволяет вам иметь дело с конкретным интерфейсом с успехом и/или исключительными результатами, например, в случае JSF, отображающем сообщение лиц в случае исключения из службы.

См. также:


В целом, правильный подход будет выглядеть следующим образом:

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

См. также:

Ответ 2

Это dao, ну, собственно, репозиторий, но не слишком беспокоитесь об этой разнице, поскольку он обращается к базе данных, используя контекст persistence.

Вам следует создать класс службы, который обертывает этот метод и где вызывается транзакция.

Иногда классы обслуживания не нужны, но когда у вас есть метод службы, который вызывает многие методы dao, их использование более оправдано.

Обычно я просто создаю услугу, даже если она не нужна, чтобы гарантировать, что шаблоны остаются неизменными, и dao никогда не вводится напрямую.

Это добавляет дополнительный слой абстракции, делающий будущий рефакторинг более гибким.