Si hallas alguna incompatibilidad con tu código o proyecto, recuerda probar siempre en un ambiente de testing antes añadir el código al trabajo final.
Solución:
Tendrá que hacer una llamada explícita a la colección perezosa para poder inicializarla (la práctica común es llamar .size()
para este propósito). En Hibernate hay un método dedicado para esto (Hibernate.initialize()
), pero JPA no tiene equivalente de eso. Por supuesto, deberá asegurarse de que se realice la invocación, cuando la sesión aún esté disponible, así que anote su método de controlador con @Transactional
. Una alternativa es crear una capa de servicio intermedia entre el controlador y el repositorio que podría exponer métodos que inicializan colecciones perezosas.
Actualizar:
Tenga en cuenta que la solución anterior es fácil, pero da como resultado dos consultas distintas a la base de datos (una para el usuario y otra para sus funciones). Si desea lograr un mejor rendimiento, agregue el siguiente método a su interfaz de repositorio Spring Data JPA:
public interface PersonRepository extends JpaRepository
@Query("SELECT p FROM Person p JOIN FETCH p.roles WHERE p.id = (:id)")
public Person findByIdAndFetchRolesEagerly(@Param("id") Long id);
Este método utilizará la cláusula fetch join de JPQL para cargar rápidamente la asociación de roles en un solo viaje de ida y vuelta a la base de datos y, por lo tanto, mitigará la penalización de rendimiento en la que incurren las dos consultas distintas en la solución anterior.
Aunque esta es una publicación anterior, considere usar @NamedEntityGraph (Javax Persistence) y @EntityGraph (Spring Data JPA). La combinación funciona.
Ejemplo
@Entity
@Table(name = "Employee", schema = "dbo", catalog = "ARCHO")
@NamedEntityGraph(name = "employeeAuthorities",
attributeNodes = @NamedAttributeNode("employeeGroups"))
public class EmployeeEntity implements Serializable, UserDetails
// your props
y luego el repositorio de primavera como se muestra a continuación
@RepositoryRestResource(collectionResourceRel = "Employee", path = "Employee")
public interface IEmployeeRepository extends PagingAndSortingRepository
@EntityGraph(value = "employeeAuthorities", type = EntityGraphType.LOAD)
EmployeeEntity getByUsername(String userName);
tienes algunas opciones
- Escriba un método en el repositorio que devuelva una entidad inicializada como sugirió RJ.
Más trabajo, mejor rendimiento.
- Use OpenEntityManagerInViewFilter para mantener la sesión abierta durante toda la solicitud.
Menos trabajo, normalmente aceptable en entornos web.
- Use una clase auxiliar para inicializar entidades cuando sea necesario.
Menos trabajo, útil cuando OEMIV no está disponible, por ejemplo, en una aplicación Swing, pero también puede ser útil en implementaciones de repositorio para inicializar cualquier entidad de una sola vez.
Para la última opción, escribí una clase de utilidad, JpaUtils para iniciar entidades en alguna profundidad.
Por ejemplo:
@Transactional
public class RepositoryHelper
@PersistenceContext
private EntityManager em;
public void intialize(Object entity, int depth)
JpaUtils.initialize(em, entity, depth);
Aquí tienes las comentarios y calificaciones
Al final de la post puedes encontrar los informes de otros programadores, tú de igual forma eres capaz insertar el tuyo si te apetece.