Saltar al contenido

Spring Data JPA y NamedEntityGraphs

Solución:

Nos encontramos con un problema similar e ideamos varias posibles soluciones, pero no parece haber una solución elegante para lo que parece ser un problema común.

1) Prefijos. Data jpa ofrece varios prefijos (buscar, obtener, …) para un nombre de método. Una posibilidad es utilizar diferentes prefijos con diferentes gráficos con nombre. Este es el menor trabajo, pero oculta el significado del método al desarrollador y tiene un gran potencial para causar algunos problemas no obvios con la carga de las entidades incorrectas.

@Repository
@Transactional
public interface UserRepository extends CrudRepository<User, Integer>, UserRepositoryCustom {
    @EntityGraph(value = "User.membershipYearsAndPreferences", type = EntityGraphType.LOAD)
    User findByUserID(int id);

    @EntityGraph(value = "User.membershipYears", type = EntityGraphType.LOAD)
    User readByUserId(int id);
}

2) CustomRepository. Otra posible solución es crear métodos de consulta personalizados e inyectar EntityManager. Esta solución le brinda la interfaz más limpia para su repositorio porque puede nombrar sus métodos con algo significativo, pero es una cantidad significativa de complejidad para agregar a su código para proporcionar la solución Y está tomando manualmente el administrador de entidades en lugar de usar Spring Magic.

interface UserRepositoryCustom {
    public User findUserWithMembershipYearsById(int id);
}

class UserRepositoryImpl implements UserRepositoryCustom {
    @PersistenceContext
    private EntityManager em;
    @Override
    public User findUserWithMembershipYearsById(int id) {
        User result = null;
        List<User> users = em.createQuery("SELECT u FROM users AS u WHERE u.id = :id", User.class)
                .setParameter("id", id)
                .setHint("javax.persistence.fetchgraph", em.getEntityGraph("User.membershipYears"))
                .getResultList();
        if(users.size() >= 0) {
            result = users.get(0);
        }
        return result;
    }
}

@Repository
@Transactional
public interface UserRepository extends CrudRepository<User, Integer>, UserRepositoryCustom {
    @EntityGraph(value = "User.membershipYearsAndPreferences", type = EntityGraphType.LOAD)
    User findByUserID(int id);
}

3) JPQL. Esencialmente, esto es simplemente renunciar a los gráficos de entidades con nombre y usar JPQL para manejar sus combinaciones por usted. No ideal en mi opinión.

@Repository
@Transactional
public interface UserRepository extends CrudRepository<User, Integer>, UserRepositoryCustom {
    @EntityGraph(value = "User.membershipYearsAndPreferences", type = EntityGraphType.LOAD)
    User findByUserID(int id);

    @Query("SELECT u FROM users WHERE u.id=:id JOIN??????????????????????????")
    User findUserWithTags(@Param("id") final int id);
}

Optamos por la opción 1 porque es la implementación más simple, pero esto significa que cuando usamos nuestros repositorios tenemos que mirar los métodos de recuperación para asegurarnos de que estamos usando el que tiene el gráfico de entidad correcto. Buena suerte.

Fuentes:

  • JPA EntityGraph con diferentes vistas usando Spring
  • https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods

No tengo suficiente reputación para publicar todas mis fuentes. Perdón 🙁

Tuvimos el mismo problema y creamos una extensión Spring Data JPA para resolverlo:

https://github.com/Cosium/spring-data-jpa-entity-graph

Esta extensión permite pasar EntityGraph con nombre o construido dinámicamente como un argumento de cualquier método de repositorio.

Con esta extensión, tendría este método disponible de inmediato:

List<Complaint> findAll(Sort sort, EntityGraph entityGraph);

Y poder llamarlo con un EntityGraph seleccionado en tiempo de ejecución.

Usar @EntityGraph Juntos con @Query

@Repository
public interface ComplaintRepository extends JpaRepository<Complaint, Long>{

   @EntityGraph(value = "allJoinsButMessages" , type=EntityGraphType.FETCH)
   @Query("SELECT c FROM Complaint ORDER BY ..")
   @Override
   List<Complaint> findAllJoinsButMessages();

   @EntityGraph(value = "allJoins" , type=EntityGraphType.FETCH)
   @Query("SELECT c FROM Complaint ORDER BY ..")
   @Override
   List<Complaint> findAllJoin();

   ...

}

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *