Query nativa con Spring Data
En esta entrada vamos a tratar como podemos crear una query nativa con Spring Data en JPA. Aunque Spring Data nos facilita mucho la gestión y utilización de queries en nuestras aplicaciones en Spring Boot en muchas ocasiones necesitamos hacer uso de alguna query un poco más compleja o custom, y para esos casos haremos uso de una query nativa.
¿Qué es una Query nativa con Spring Data?
Cuando hacemos uso de JPA a través de Spring Data, este nos envuelve y elimina el boilerplate de la gestión y creación de queries a través de un cómodo DSL o JPQL.
Por defecto, al añadir la anotación @Query en una sentencia en Spring, esta se va a transformar directamente en el lenguaje JPQL (Java Persistence Query Language), el cual esta inspirado en SQL.
Pero cuando queremos crear alguna query más compleja o que no podemos realizar con JPQL, hacemos uso de SQL para crear una query nativa.
Una Query nativa en Spring Data es una query tal cual la haríamos en SQL.
¿Cómo crear una Query Nativa con Spring Data?
Para crear una query nativa en Spring, tenemos que realizar tres pasos:
- Añadir la anotación @Query
- Añadir el atributo nativeQuery a true.
- Definir la sentencia SQL
Vamos a ver una definición de un query en Spring Data como nativeQuery.
public interface UserRepository extends CrudRepository<User, Long>, PagingAndSortingRepository<User, Long> { @Query(value="select * from user u where u.name= :name", nativeQuery=true) List<User> getUsersByName(String name); }
Una vez realizado este paso, únicamente tenemos que inyectar el repositorio y pasar por parámetro de la llamada al método el nombre que queremos buscar.
Por ejemplo:
List<User> users = authorRepository.getAuthorsByFirstName("Janssen");
Limitaciones en el uso de Queries Nativas en Spring Data
Al hacer uso de Queries nativas tenemos que tener en cuenta las siguientes acciones que nos van a limitar:
- Spring Data no soporta ordenaciones dinámicas cuando se realiza una query nativa.
- Al hacer uso de una Query nativa nos tenemos que asegurar que nuestro motor de BBDD es capaz de procesar esa query.
- La paginación no es directa, sino que tienes que además tenemos que hacer una countQuery para obtener el número de registros.
Paginación y Ordenación con Query Nativa
Cuando hacemos uso de Spring Data, tenemos la opción de paginar haciendo uso del objeto Pageable, en el que indicamos la ordenación y paginación. Pero en cambio al hacer una query nativa pasamos un objeto Pageable pero no obtenemos de manera automática la paginación.
Al utilizar Queries Nativas necesitamos hacer dos pasos para conseguir la paginación, aún así sigue siendo muy sencillo de aplicar. Vamos a verlo con la query del punto anterior:
public interface UserRepository extends CrudRepository<User, Long>, PagingAndSortingRepository<User, Long> { @Query(value="select * from user u where u.name= ?1", countQuery = "select count(id) from user u where u.name= ?1", nativeQuery = true) Page<User> getUsersByNamePagination(String name, Pageable page); }
El countQuery se aplicará únicamente para Page. Si no queremos devolver Page y queremos, por ejemplo, devolver una lista ordenada, podríamos hacer algo como lo siguiente:
@Query(value="SELECT u.* " + "FROM user u " + "WHERE p.created_date is null OR u.created_date> ?1" + "ORDER BY u.id \n#pageable\n", nativeQuery=true) public List<User> findUsersNew(LocalDate dateToFind,Pageable pageable);
Al igual que pasa con la paginación, tampoco podemos hacer una ordenación dinámica con el sort, la manera para ordenar sería la que hemos visto antes, haciendo uso de ORDER BY.
Conclusión
Aunque la mayor parte de consultas, actualizaciones e inserciones en BBDD se puede gestionar con JPQL, en alguna ocasiones necesitaremos realizar una query nativa con Spring Data. Aunque, como hemos visto el uso de Queries Nativas añade complejidad al código y además añade unas limitaciones ya que el framework no las gestiona.
Si necesitas más información puedes escribirnos un comentario o un correo electrónico a refactorizando.web@gmail.com o también nos puedes contactar por nuestras redes sociales Facebook o twitter y te ayudaremos encantados!