datos - Controlador JSF, Servicio y DAO
jsf primefaces tutorial (2)
Estoy tratando de acostumbrarme a cómo funciona JSF con respecto al acceso a datos (proveniente de un fondo de primavera)
Estoy creando un ejemplo simple que mantiene una lista de usuarios, tengo algo como
<h:dataTable value="#{userListController.userList}" var="u">
<h:column>#{u.userId}</h:column>
<h:column>#{u.userName}</h:column>
</h:dataTable>
Entonces el "controlador" tiene algo como
@Named(value = "userListController")
@SessionScoped
public class UserListController {
@EJB
private UserListService userListService;
private List<User> userList;
public List<User> getUserList() {
userList = userListService.getUsers();
return userList;
}
}
Y el "servicio" (aunque parece más un DAO) tiene
public class UserListService {
@PersistenceContext
private EntityManager em;
public List<User> getUsers() {
Query query = em.createQuery("SELECT u from User as u");
return query.getResultList();
}
}
¿Es esta la forma correcta de hacer las cosas? ¿Es correcta mi terminología? El "servicio" se siente más como un DAO? Y el controlador siente que está haciendo parte del trabajo del servicio.
¿Es esta la forma correcta de hacer las cosas?
Además de realizar la lógica de negocios de la manera ineficiente en un método getter de bean administrado, y usar un alcance de bean administrado demasiado amplio, se ve bien.
Si mueve la llamada de servicio del método getter a un método
@PostConstruct
y usa
@RequestScoped
o
@ViewScoped
lugar de
@SessionScoped
, se verá mejor.
Ver también:
¿Es correcta mi terminología?
Está bien.
Siempre y cuando sea coherente con él y el código sea legible de manera sensata.
Solo su forma de nombrar clases y variables es algo incómoda (ilógica y / o duplicación).
Por ejemplo, yo personalmente usaría
users
lugar de
userList
, y usaría
var="user"
lugar de
var="u"
, y usaría
id
y
name
lugar de
userId
y
userName
.
Además, un "UserListService" parece que solo puede tratar con listas de usuarios en lugar de usuarios en general.
Prefiero usar "UserService" para que también pueda usarlo para crear, actualizar y eliminar usuarios.
Ver también:
El "servicio" se siente más como un DAO?
No es exactamente un DAO. Básicamente, JPA es el verdadero DAO aquí. Anteriormente, cuando JPA no existía, todos crecían interfaces DAO caseras para que los métodos de servicio puedan seguir usándolas incluso cuando cambia la implementación subyacente (JDBC "simple" o "Hibernate" bueno, etc.). La verdadera tarea de un método de servicio es gestionar de manera transparente las transacciones. Esta no es responsabilidad del DAO.
Ver también:
- Encontré JPA, o igual, no aliente el patrón DAO
- Relación DAO y JDBC?
- ¿Cuándo es necesario o conveniente usar Spring o EJB3 o todos juntos?
Y el controlador siente que está haciendo parte del trabajo del servicio.
Me imagino que hace eso en esta configuración relativamente simple. Sin embargo, el controlador es de hecho parte de la interfaz, no del servidor. El servicio es parte del backend que debe diseñarse de tal manera que sea reutilizable en todos los frentes diferentes, como JSF, JAX-RS, JSP + Servlet "simple", incluso Swing, etc. Además, el controlador específico de la interfaz ( también llamado "bean de respaldo" o "presentador") le permite tratar de manera específica a la interfaz con el éxito y / o resultados excepcionales, como en el caso de JSF que muestra un mensaje de rostros en caso de una excepción lanzada desde un servicio.
Ver también:
En general, el enfoque correcto sería el siguiente:
<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();
}
}
Puede encontrar aquí un proyecto de lanzamiento del mundo real aquí utilizando las prácticas canónicas Java EE / JSF / CDI / EJB / JPA: la aplicación de lanzamiento Java EE .
Ver también:
- Creación de páginas de detalles maestros para entidades, cómo vincularlas y qué ámbito de bean elegir
- Pasar un bean pojo administrado JSF2 a EJB o poner lo que se requiere en un objeto de transferencia
- El filtro no inicializa EntityManager
- javax.persistence.TransactionRequiredException en una aplicación de facelet pequeña
Es un dao, bueno en realidad un repositorio, pero no se preocupe demasiado por esa diferencia, ya que está accediendo a la base de datos utilizando el contexto de persistencia.
Debe crear una clase de servicio, que envuelva ese método y es donde se invocan las transacciones.
A veces, las clases de servicio se sienten innecesarias, pero cuando tiene un método de servicio que llama a muchos métodos dao, su uso está más garantizado.
Normalmente termino simplemente creando el servicio, incluso si se siente innecesario, para asegurar que los patrones permanezcan igual y que el dao nunca se inyecte directamente.
Esto agrega una capa adicional de abstracción que hace que la futura refactorización sea más flexible.