Spring Data JPA @ Modificación de anotación

1. Introducción

En este breve tutorial, aprenderemos cómo crear consultas de actualización con la anotación Spring Data JPA @Query . Lo lograremos usando la anotación @Modifying .

Primero, actualizaremos nuestra memoria y veremos cómo hacer consultas usando Spring Data JPA. Después de eso, profundizaremos en el uso de @Query y @Modifying anotaciones. Finalmente, veremos cómo administrar el estado de nuestro contexto de persistencia cuando usamos consultas de modificación.

2. Consultar en Spring Data JPA

Primero, recapitulemos los 3 mecanismos que Spring Data JPA proporciona para consultar datos en una base de datos :

  • Métodos de consulta
  • @Query anotación
  • Implementación de repositorio personalizado

Creemos una clase de usuario y un repositorio JPA de Spring Data coincidente para ilustrar estos mecanismos:

@Entity @Table(name = "users", schema = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String name; private LocalDate creationDate; private LocalDate lastLoginDate; private boolean active; private String email; }
public interface UserRepository extends JpaRepository {}

El mecanismo de métodos de consulta nos permite manipular los datos derivando las consultas de los nombres de los métodos:

List findAllByName(String name); void deleteAllByCreationDateAfter(LocalDate date);

En este ejemplo, podemos encontrar una consulta que recupera usuarios por sus nombres, o aún una consulta que elimina usuarios que tienen una fecha de creación posterior a cierta fecha.

En cuanto a la anotación @Query , nos brinda la posibilidad de escribir una consulta JPQL o SQL específica en la anotación @Query :

@Query("select u from User u where u.email like '%@gmail.com'") List findUsersWithGmailAddress();

En este fragmento de código, podemos ver una consulta que recupera usuarios que tienen una dirección de correo electrónico @ gmail.com .

El primer mecanismo nos permite recuperar o eliminar datos. En cuanto al segundo, nos permite ejecutar prácticamente cualquier consulta. Sin embargo, para las consultas de actualización, debemos agregar la anotación @Modifying . Este será el tema de este tutorial.

3. Uso de la anotación @Modifying

La anotación @Modifying se usa para mejorar la anotación @Query para ejecutar no solo las consultas SELECT, sino también las consultas INSERT , UPDATE , DELETE e incluso DDL .

Juguemos un poco con esta anotación y veamos de qué está hecha.

Primero, veamos un ejemplo de una consulta @Modifying UPDATE:

@Modifying @Query("update User u set u.active = false where u.lastLoginDate < :date") void deactivateUsersNotLoggedInSince(@Param("date") LocalDate date);

Aquí, estamos desactivando a los usuarios que no iniciaron sesión desde una fecha determinada.

Probemos con otro en el que eliminaremos usuarios desactivados:

@Modifying @Query("delete User u where u.active = false") int deleteDeactivatedUsers();

Como podemos ver, este método devuelve un número entero. Es una característica de Spring Data JPA @Modifying queries que nos proporciona la cantidad de entidades actualizadas.

Debemos tener en cuenta que la ejecución de una consulta de eliminación con @Query funciona de forma diferente a partir de la primavera de datos JPA deleteBy métodos de consulta derivados de nombre. Este último primero obtiene las entidades de la base de datos y luego las elimina una por una. Por lo tanto, esto significa que se llamará al método de ciclo de vida @PreRemove en esas entidades. Sin embargo, con el primero, se ejecuta una única consulta en la base de datos.

Finalmente, agreguemos una columna eliminada a nuestra tabla USERS con una consulta DDL :

@Modifying @Query(value = "alter table USERS.USERS add column deleted int(1) not null default 0", nativeQuery = true) void addDeletedColumn();

Desafortunadamente, el uso de consultas de modificación deja obsoleto el contexto de persistencia subyacente. Sin embargo, es posible gestionar esta situación. Ese es el tema de la siguiente sección.

4. Gestión del contexto de persistencia

Si nuestra consulta de modificación cambia las entidades contenidas en el contexto de persistencia, este contexto se vuelve obsoleto. Una forma de gestionar esta situación es despejar el contexto de persistencia. Al hacer eso, nos aseguramos de que el contexto de persistencia obtenga las entidades de la base de datos la próxima vez.

Sin embargo, no tenemos que llamar explícitamente al método clear () en EntityManager . Podemos usar la propiedad clearAutomatically de la anotación @Modifying :

@Modifying(clearAutomatically = true)

De esa manera, nos aseguramos de que el contexto de persistencia se borre después de la ejecución de nuestra consulta.

Pero, ¿qué pasaría si nuestro contexto de persistencia contuviera cambios profundos? Por lo tanto, borrarlo significaría eliminar los cambios no guardados. Afortunadamente, hay otra propiedad de la anotación que podemos usar: flushAutomatically :

@Modifying(flushAutomatically = true)

Ahora, EntityManager se vacía antes de que se ejecute nuestra consulta.

5. Conclusión

Con esto concluye este breve artículo sobre la anotación @Modifying . Hemos visto cómo usar esta anotación para ejecutar consultas de actualización como INSERT, UPDATE, DELETE e incluso DDL . Después de eso, aprendimos cómo administrar el estado del contexto de persistencia con las propiedades clearAutomatically y flushAutomatically .

Como de costumbre, el código completo de este artículo está disponible en GitHub.