Estoy haciendo una aplicación de la primavera de arranque práctica.
Tengo 3 entidades (editado como se recomienda):
class User extends EntityModelTemplate {
String username; //unique
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
List<UserRoles> userRoles;
}
@IdClass(UserRolesKey.class)
class UserRoles {
@Id
@ManyToOne
@JoinColumn(name = "user_id")
User user;
@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "role_id")
Role role;
}
class Role extends EntityModelTemplate{
String role;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "role")
List<UserRoles> userRoles;
}
Yo quería hacer una sola llamada de DB, que se vendería por usuario junto con papeles de manera he intentado usar Especificaciones. He leído la documentación y ejemplos buscado en línea antes de llegar a algo que debería funcionar como lo quería.
método de servicio (editado como se recomienda):
public UserDTO getUserForSecurityCheck(String username) throws UsernameNotFoundException {
log.info("Repository call start!");
Optional<User> user = userRepo.findOne(Specification.where(UserSpecifications.usernameEquals(username)));
log.info("Repository call end!");
return user.map(UserDTO::new).orElseThrow(() -> new UsernameNotFoundException("Username "+username+" not found!"));
}
Especificación:
public static Specification<User> usernameEquals(String username){
return (root, query, criteriaBuilder) -> {
( (Join<Object, Object>) root.fetch(User_.USER_ROLES)).fetch(UserRoles_.ROLE);
return criteriaBuilder.equal(root.get(User_.USERNAME), username);
};
}
Funciona perfectamente, excepto Hibernate realiza dos llamadas DB.
(editar)
Los primeros selecciona uno único que se necesita el uso de dos combinaciones, donde nombre de usuario = (Que es bastante largo, por lo tanto, a corto, versión corta). Que es exactamente lo que quería que hiciera. Pero entonces se hace una segunda llamada que literalmente hace Select * (excepto UserRoles) del usuario, donde user_id = ?.
¿Por qué?
A pesar de que todavía soy un principiante en la codificación en general, estaba bastante seguro de haber entendido cómo el trabajo de especificación y de hibernación. Conceptos básicos, por lo menos. Obviamente yo no.
Por lo tanto, mi pregunta es: ¿Se supone que hacer dos llamadas DB o qué estoy haciendo mal?
Gracias por adelantado.
He encontrado mi error y estoy bastante avergonzado por no darse cuenta de inmediato: Usuario en UserRoles se carga con entusiasmo por defecto. Esa fue la segunda llamada. Lo cambié a perezoso y que está funcionando según lo previsto.
Si no fuera por M.Deinum preguntando por una colección perezosa, me he dado cuenta de que no habría en un millón de años.