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.