springframework specification query org left jpaspecificationexecutor examples domain data criteriabuilder complex hibernate spring-boot spring-data-jpa

hibernate - query - spring data jpa specification examples



Cómo usar consultas de criterios en Spring Boot Data Jpa Application (6)

Tengo una aplicación que usa Spring Boot Data jpa. Hasta ahora estoy usando un repositorio como este

public interface StudentRepository extends CrudRepository<StudentEntity, Integer>{ @Query(value = "SELECT s.studentname " +"FROM StudentEntity s, CourseEntity c " +"WHERE s.courseid = c.courseid " +"AND s.courseid IN (SELECT c.courseid " +"FROM CourseEntity c " +"WHERE c.coursename = ?1)") List<String> nameByCourse(String coursename); }

¿Cómo puedo utilizar Criteria Query That Hibernate proporciona para tales casos en una aplicación Spring Boot?


Con Spring-boot-jpa puede usar entityManager casi todas partes. La forma más común es crear una interface propia para métodos personalizados.

public interface StudentCustomRepository { void anyCustomMethod(); Student getStudentByName(String name); }

A continuación, implemente esta interfaz en una clase de servicio en la que pueda autoaumentar y utilizar el entityManager :

@Service public class StudentCustomRepositoryServiceImpl implements StudentCustomRepository { @PersistenceContext private EntityManager em; @Override public void anyCustomMethod(){ //here use the entityManager } @Override StudentEntity getStudentByName(String name){ Criteria crit = em.unwrap(Session.class).createCriteria(StudentEntity.class); crit.add(Restrictions.eq("name", name)); List<StudentEntity> students = crit.list(); return students.get(0); } }

También puede decidir implementar su StudentRepository a su nueva clase StudentCustomRepositoryServiceImpl .


De acuerdo con Spring doc HibernateTemplate :

NOTA: El código de acceso de Hibernate también se puede codificar en estilo Hibernate simple. Por lo tanto, para proyectos recién iniciados, considere adoptar el estilo estándar Hibernate de objetos de acceso a datos de codificación, basado en SessionFactory.getCurrentSession (). Este HibernateTemplate existe principalmente como un asistente de migración para el código de acceso a datos basado en Hibernate 3, para beneficiarse de las correcciones de errores en Hibernate 4.x.

Mientras que según el documento de Hibernate:

El nuevo desarrollo debe centrarse en la API javax.persistence.criteria.CriteriaQuery de JPA. Eventualmente, las características de los criterios específicos de Hibernate serán portados como extensiones de JPA javax.persistence.criteria.CriteriaQuery.

Por lo tanto, es mejor utilizar los criterios de JPQL: consultas de la API de criterios JPA

Ejemplo:

CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<Country> q = cb.createQuery(Country.class); Root<Country> c = q.from(Country.class); q.select(c);

donde entityManager debe estar @Autowired. Para obtener información detallada, consulte el enlace anterior


De los docs

Para enriquecer un repositorio con funcionalidad personalizada, primero define una interfaz y una implementación para la funcionalidad personalizada. Use la interfaz del repositorio que proporcionó para extender la interfaz personalizada.

Definir una interfaz como tal

public interface StudentRepositoryCustom { List<String> nameByCourse(String coursename); }

A continuación, defina una implementación personalizada de esta interfaz como tal

@Service class StudentRepositoryImpl implements StudentRepositoryCustom { @PersistenceContext private EntityManager entityManager; public List<String> nameByCourse(String coursename) { CriteriaBuilder cb = em.getCriteriaBuilder(); //Using criteria builder you can build your criteria queries. } }

Ahora puede extender esta implementación de repositorio personalizado en su repositorio JPA de esa manera.

public interface StudentRepository extends CrudRepository<StudentEntity, Integer>, StudentRepositoryCustom { }

Obtenga más información sobre la consulta de criterios y el generador de criterios here


puede consultar la creación de consultas en la documentación JPA de Spring Data y echar un vistazo a la tabla, JPA le permite crear múltiples Query desde nombres de métodos donde puede evitar el uso de una consulta String


JPA 2 introduce una API de criterios que se puede usar para generar consultas programáticamente.

Puede extender una nueva interfaz desde JpaSpecificationExecutor

public interface CustomerRepository extends CrudRepository<Customer, Long>, JpaSpecificationExecutor { default List<Customer> findCustomers() { return findAll(CustomerSpecs.findCustomers()); }

A continuación, cree las especificaciones de un cliente

public final class CustomerSpecs { public static Specification<Customer> findCustomers() { return new Specification<Customer>() { public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder builder) { LocalDate date = new LocalDate().minusYears(2); return builder.lessThan(root.get("birthday"), date); } }; }

Para más detalles, consulte este documento de primavera aquí

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#specifications


Es muy complicado crear especificaciones utilizando criterios JPA porque la API es muy prolija e intrusiva.

Con el Lambda JDK 8, puede crear consultas muy tipeadas con predicados simples.

@Test public void testSimpleSpec() { String expected = "select e0.id, e0.name " + "from Customer e0 " + "where (e0.regionCode = :p0)"; Consumer<Query<Customer>> regionCode1 = q -> q.where(i -> i.getRegionCode()).eq(1L); NativeSQLResult result = new QueryBuilder() .from(Customer.class) .whereSpec(regionCode1) .select(i -> i.getId()) .select(i -> i.getName()) .to(new NativeSQL()) ; String actual = result.sql(); Assert.assertEquals(expected, actual); Assert.assertEquals(result.params().get("p0"), 1L); }

Puede aislar las condiciones y reutilizar en otras consultas, es decir, especificaciones.

https://github.com/naskarlab/fluent-query

https://github.com/naskarlab/fluent-query-eclipselink