Spring-Data JPA & Modifying Queries
O Spring Framework possuí sub-projetos bem interessantes, entre eles, há o Spring-Data JPA. O Spring-Data JPA tem como foco a camada de persistencia em uma aplicação Java. Este projeto é baseado no padrão de projetos Repository e reduz muito a quantidade de código que deve ser escrito durante o desenvolvimento de uma aplicação.
Um dos pontos positivos do Spring-Data JPA é a possibilidade de herança de métodos pre-implementados como o save()
, usado para inserir e alterar registros no banco de dados, e alguns métodos de consultas como findOne()
e findAll()
. Nas interfaces, as consultas podem ser realizadas por meio do uso de palavras chaves (Keywords) ou de instruções via JPQL por meio da anotação @Query
.
Se você já trabalhou com o Spring-Data JPA, já deve saber que métodos não são implementados, ou seja, se cria a assinatura dos métodos na interface do tipo Repository e o Spring-Data fica com a responsabilidade da “implementação” destes métodos em tempo de execução.
Mas se os métodos não são implementados pelo desenvolvedor, e sim apenas a assinatura deles, como criar métodos de update ou delete, específicos para uma dada situação? Bem, para isso, o Spring-Data fornece a anotação @Modifying
, a qual veremos como utilizar neste tutorial.
1. A anotação @Modifying
A anotação @Modifying
deve ser utilizada em conjunto com a anotação @Query
. Na anotação @Query
se adiciona a JPQL em questão, referente a operação de update ou delete, conforme a Listagem 1. E a anotação @Modifying
será usada apenas para informar ao Spring-Data que a @Query
não possuí um método de consulta, mas sim, um método de escrita.
package com.mballem.tutorial.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import com.mballem.tutorial.entity.User;
public interface UserRepository extends JpaRepository<user, long=""> {
@Modifying
@Transactional(readOnly = false)
@Query("update User u set u.age = ?1 where u.id = ?2")
int updateAge(Integer age, Long id);
@Modifying
@Transactional(readOnly = false)
@Query("delete from User u where u.fullName like ?1")
int deleteByFullName(String fullName);
}
Na Listagem 1 você pode ver que a interface UserRepository
tem dois métodos utilizando a anotação @Modifying
. O primeiro método, updateAge()
, tem como objetivo alterar a idade a partir de uma chave primaria. Veja que, os parametros informados são o novo valor para o campo age
e o id
para localizar a linha na tabela a ser modificada. Desta foram, a anotação @Query
não foi utilizada para uma consulta, mas sim para uma operação de escrita. Já o método deleteByFullName()
tem como objetivo, excluir uma linha no banco de dados a partir do parametro fullName
.
Tando as operação de update ou delete, são operações que poderiam ser realizadas a partir de métodos herdados da interface JpaRepository
. Porém, a assinatura dos métodos herdados são muito especificas. Para trabalhar com o update, o único parametro aceito é o objeto da entidade envolvida na operação. E para usar o delete, os parametros são ou o objeto da entidade ou o identificodor deste objeto. Então, caso queira alterar estes parametros, como no método deleteByFullName()
, a saída é usar @Modifying
e @Query
com sua instrução de delete. E é claro, se quiser uma operação de delete ou update diferente das já fornecidas pelo Spring-Data, vai precisar usar então a @Modifying
.
Outro ponto importante que deve ser levado em conta é o uso da anotação @Transactional
com o atributo readOnly
setado como false
. Isto porque, todas as interfaces que herdam JpaRepository
são por padrão do tipo readOnly = true
, ou seja, todos os métodos que você assinar na interface, serão do tipo leitura e não de escrita. Então, para evitar uma exceção na transação dos métodos anotados com @Modifying
, é preciso inserir a @Transactional(readOnly = false)
, para dizer que esta transação não será para leitura e sim de escrita.
Referencias:
Documentação Modifying Queries – http://docs.spring.io/spring-data/jpa/docs/1.9.0.RELEASE/reference/html/#jpa.modifying-queries