Aprendendo Spring: #5 – JpaRepository

Fala aí galera, tudo certo?

Vou escrever hoje, sobre repository em Spring Boot.

Mas antes, caso seja seu primeiro contato com Spring Boot e não acompanhou os posts anteriores, seguem abaixo os links. São leituras recomendadas:

Dependências

Para usarmos repository em uma aplicação Spring Boot, primeiramente será necessário adicionar a dependência Starter Data JPA e de algum banco de dados (H2) .

Se tiver usando Maven, no arquivo pom.xml adicione estas linhas:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>

Caso esteja usando o Gradle, adicione a linha abaixo no arquivo build.gradle:

//
compile('org.springframework.boot:spring-boot-starter-data-jpa')
runtime('com.h2database:h2')
//

Configuração

Precisamos fazer a configuração de banco para que possamos persistir os objetos. Neste post usarei o banco de dados H2. Este BD é um banco em memória bem simples. Para maiores informações sobre o H2 consulte o Wikipédia.

Utilizei YAML para configurar o H2:

spring:
jpa:
hibernate:
ddl-auto: create-drop
naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
database-platform: org.hibernate.dialect.H2Dialect
show-sql: true
datasource:
url: jdbc:h2:mem:exemploparte2;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
username: sa
password:
driverClassName: org.h2.Driver
h2:
console:
enabled: true

Implementação

Configuração pronta, vamos agora modela a entidade Cliente para que possamos persisti-la. Ela será bem simples, o nome da tabela será “CLIENTE” e possuirá apenas os atributos id, nome e rg:

@Entity
@Table(name = "CLIENTE")
public class Cliente {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
private String nome;
@Column
private String rg;
public Long getId() {
return id;
}
public String getNome() {
return nome;
}
public String getRg() {
return rg;
}
public void setId(final Long pId) {
id = pId;
}
public void setNome(final String pNome) {
nome = pNome;
}
public void setRg(final String pRg) {
rg = pRg;
}
}

Agora criaremos o repository. O Spring Boot por intermédio do Spring Data, nos auxilia muito deste quesito, já que ele possui implementações default de repository, assim o que precisamos fazer é basicamente criar uma interface.

Esta interface tem que estender a interface do Spring Data chamada JpaRepository. Vejamos o exemplo abaixo:

@Repository
public interface ClienteRepository extends JpaRepository<Cliente, Long> {
// não preciso definir nenhum método ainda!
}

Na linha 1 anotei a classe com @Repository, esta anotação é apenas uma wrapper para @Component, que diz ao Spring Boot que essa classe deve estar disponível para ser injetada, funciona como anotação tipificadora.

Mas o mais importante desta interface está na linha 2. Como disse anteriormente, a interface deve estender JpaRepository, nela devemos informar qual é a entidade quer será persistida e qual o tipo do id da entidade. Talvez você nem precise declarar nenhum método, pois só que fazer isso, o repository já ganhou implementação de vários métodos:

  • findAll;
  • findOne;
  • save;
  • existis…

Mas estes métodos podem não ser suficientes. E se eu precisar fazer uma buscar clientes por RG? Simples basta fazermos o seguinte:

@Repository
public interface ClienteRepository extends JpaRepository<Cliente, Long> {
public Cliente findByRg(String pRg);
}

Pronto, a implementação do findByRg fica a cargo do Spring Boot! Todos os atributos mapeados na entidade podem ser usados, no caso a entidade Cliente tem um atributo rg, por isso quando criamos findByRg o Spring sabe exatamente qual atributo usar na query.

É possível também pesquisar com varias condições, suponha que tenhamos que pesquisar por RG e nome do Cliente. Para isto, na declaração do método usamos a palavra reservada And, desta forma a declaração ficaria assim:

@Repository
public interface ClienteRepository extends JpaRepository<Cliente, Long> {
public Cliente findByRg(String pRg);
public Cliente findByRgAndNome (String pRg, String pNome);
}

Nota: A ordem dos paramentos devem respeitar a ordem dos atributos na declaração do método.

Além da palavra reservada And, você pode usar:

  • Or;
  • OrderBy;
  • Asc e Desc;
  • Count, Sum, Avg;

Vendo estas implementações, você pode pensar que Spring Boot funciona muito bem, quando preciso fazer queries simples. Mas isto não é verdade, é possível usar fazer queries mais refinadas, neste caso a anotação @Query, pode ajudar bastante.

@Query recebe no value uma String, que nada mais é q a query que será executada. Você pode optar em usar JPql ou SQL nativo, como pode ser visto no exemplo abaixo:

@Repository
public interface ClienteRepository extends JpaRepository<Cliente, Long> {
public Cliente findByRg(String pRg);
public Cliente findByRgAndNome (String pRg, String pNome);
/**
* Usando JPql
* @param pPrimeiroNome
* @return lista de clientes com primeiro nome igual ao informado
*/
@Query("SELECT c FROM Cliente c WHERE c.nome like ?1%")
public List<Cliente> findAllByFirstName(String pPrimeiroNome);
/**
* Usando SQL nativo
* @param pUltimoNome
* @return lista de clientes com último nome igual ao informado
*/
@Query(value = "SELECT * FROM CLIENTE c WHERE c.NOME like %?1", nativeQuery = true)
public List<Cliente> findAllByLastName(String pUltimoNome);
}

Para mais informação sobre a anotação @Query acesse a documentação do String Data.

Criei teste para realmente saber se o repository funciona:

@RunWith(SpringRunner.class)
@SpringBootTest
public class RepositoryApplicationTests {
@Autowired
ClienteRepository repository;
@Test
public void testRepository(){
repository.save(new Cliente("Maria Oliveira","123456789"));
repository.save(new Cliente("José da Silva","987654321"));
repository.save(new Cliente("Maria da Silva","999999999"));
final List<Cliente> todos = repository.findAll();
System.out.println(todos);
Assert.assertEquals(3, todos.size());
final Cliente maria = repository.findByRg("123456789");
System.out.println(maria);
Assert.assertEquals("Maria Oliveira", maria.getNome());
final List<Cliente> marias = repository.findAllByFirstName("Maria");
System.out.println(marias);
Assert.assertEquals(2, marias.size());
final List<Cliente> silvas = repository.findAllByLastName("Silva");
System.out.println(silvas);
Assert.assertEquals(2, silvas.size());
}
}

Por fim deixo exemplo de usa de repository, executando uma query complexa (vários joins) e retornando uma lista de entidades:

public interface TimeRepository extends JpaRepository<Time, Long> {
@Query(value = "SELECT t.* FROM time t "
+ "cross JOIN boleiro_time bt, boleiro b "
+ "WHERE t.id = bt.id_time "
+ "AND bt.id_boleiro = b.id "
+ "AND b.id_usuario = ?1 "
+ "AND (t.id_gerente = ?1 "
+ " OR bt.id_boleiro IN (SELECT b2.id FROM boleiro b2 WHERE b2.id_usuario= ?1)"
+ ")", nativeQuery = true)
List<Time> findByIdUsuario(Long pIdUsuario);
}

Para mais informação sobre Spring Data, não deixe de consultar a documentação oficial. Este post tem por objetivo apenas mostrar um pouquinho do potencial de “fodático” framework.

Deixo também o link do GitHub, caso alguém queira baixar o fonte do projeto.

Até mais pessoal.

um comentário

  1. Excelente tópico, adorei e aprendi bastante, obrigado por compartilhar estes ensinamentos.
    Uma dúvida, como posso pesquisar no banco de dados uma informação que esteja gravada assim no banco de dados “Matematica” e no campo pesquisa, o usuário pesquisa matematica, ou MATEMATICA, tentei por o like “%:dadoProcurado%” porem como citei se o usuario procura por matematica minusculo ele não acha, pra achar o usuario tem que utilizar Mate por exemplo, para poder achar, lembro que no criteria do hibernate existe um comando que ele utiliza para não importar o que pesquisar, seria este MatchMode.ANYWHERE.
    Novamente, obrigado pelo tópico.
    Desde já
    Eder

    Curtir

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s

%d blogueiros gostam disto: