07 Aplicação Web com VRaptor 4 – Criando nosso Repositório (DAO)

Oi, como vai você?

Eu voltei e agora é pra ficar, porque aqui, aqui é meu lugar . . .

Bora para mais um artigo? Hoje vamos configurar nosso acesso ao banco de dados, no post anterior, criamos o modelo da nossa aplicação, existe também o post em que criamos o nosso persistence.xml, lembra? Ainda não viu? Passa lá então.

E lembre-se você pode e deve acompanhar os códigos pelo meu github, segue o link ai em baixo:

https://github.com/pedro-hos/aprendendo-vraptor

 Vamos lá então, criaremos hoje a classe que ficará responsável pelo nosso acesso aos dados, certo tatu? Muitos chamam de DAO, acrônimo para Data Access Object, mas pode também ser chamado de Repository, ou seja, será nosso repositório onde vamos trabalhar com os dados. No fundo é a mesma coisa que o DAO, não se assuste ok?

Aqui no post faremos algo mais requintado, vamos criar uma classe abstrata com os principais métodos de tratamento de dados como o save, update, delete, etc

A primeira coisa que você, nobre rapaz ( ou moça, porque não? né?), deve fazer é colocar no pom.xml o seguinte trecho:

<dependency>
     <groupId>org.jboss.spec.javax.transaction</groupId>
     <artifactId>jboss-transaction-api_1.2_spec</artifactId>
     <version>1.0.0.Final</version>
     <scope>provided</scope>
</dependency>

Ela é muito importante, já que será esta dependência que ficará incumbida de cuidar das transações com o banco de dados, evitando assim que tenhamos que nos preocupar com esse tipo de coisa. Ah, repare ali que ele esta com o <scope>…</scope>, provided, ou seja o WildFly cuida da parada para gente.

Agora vamos para o Java, crie uma classe abstrata chamada Repository, dentro do pacote br.com.pedroHos.model.repositories.

Depois da classe criada, vamos colocar o tipo Genérico  <T>, só colocar na frente do nome da classe <T>. Não pretendo aqui explicar como funciona isso, mas basicamente quando formos estender a classe devemos passar um tipo para ela.

Feito isso, devemos também anotar a classe com @Stateless, já que ela não guarda estado. A classe ficará assim:

package br.com.pedroHos.model.repositories;

import javax.ejb.Stateless;

@Stateless
public abstract class Repository<T> {
     // Métodos . . .
}

Vamos agora fazer o Inject do EntityManager, ele é o cara que fará todo o tramite com o banco para gente, dentro da classe coloque o trecho a seguir:

@PersistenceContext(unitName = "meus-contatos-ds")
protected EntityManager em;

O EntityManager e a anotação @PersistenceContext são importados do pacote javax.persistence

Um detalhe legal, viu a anotação PersistenceContext? Passamos um unitName para ela, o “meus-contatos-ds”, ele deve ser exatamente,  o mesmo que colocamos no post do persistence.xml, dessa maneira já injetamos o EntityManager.

Vamos agora, criar os métodos propriamente ditos, são eles:

  • void novo( T entidade ): Ele vai persistir os objetos no banco, legal né? Tem uma coisa mais legal ainda, reparaste no T ali no parâmetro? Pois é, estamos passando o Tipo ali, assim ele será o mesmo que passarmos no momento que estendemos a ela;
  • void remover(T entidade): Exatamente o que você pensou, garoto esperto, esse método deleta/remove a parada do BD;
  • List<T> todos(): Vai nos trazer todos os objetos do tipo T que estão salvos;
  • T comId(long id): Traz um tipo específico, com um determinado id passado como parâmetro;
  • T atualizar(T entidade): Este aqui faz o merge e retorna o objeto T atualizado.

Bom, os métodos são estes, basta colocar o trecho de código abaixo dentro da classe:

    public void novo(T entidade) {
        em.persist(entidade);
    }

    public void remover(T entidade) {
        em.remove(entidade);
    }

    public List<T> todos() {
        CriteriaQuery<Object> cq = em.getCriteriaBuilder().createQuery();
        cq.select(cq.from(tipo));
        return (List<T>) em.createQuery(cq).getResultList();
    }

    public T comId(long id) {
        return em.find(tipo, id);
    }

    public T atualizar(T entidade) {
        return em.merge(entidade);
    }

Agora precisamos fazer com que a classe descubra qual o tipo do objeto que esta sendo passado, em uma discussão no grupo do livro Design Patterns com Java: Projeto orientado a objetos guiado por padrões, Eduardo Guerra propôs uma solução para o problema, vamos aplicar a solução dada por ele então.

Na Classe declare um novo atributo chamado tipo, do tipo Class<T>, ele deve chamar o método retornaTipo(), que vamos implementar agorinha. Teremos algo assim:


private Class<T> retornaTipo() {
        Class<?> clazz = this.getClass();
        
        while (!clazz.getSuperclass().equals(Repository.class)) {
            clazz = clazz.getSuperclass();
        }
        
        ParameterizedType tipoGenerico = (ParameterizedType) clazz.getGenericSuperclass();
        return (Class<T>) tipoGenerico.getActualTypeArguments()[0];
    }

// . . . Outros métodos e trens

Com isso fechamos esta classe, ela ficará no final assim:

[gist https://gist.github.com/pedro-hos/4a5073f28f432dadb15d /]

Antes de continuar, gostaria de agradecer ao meu amigo William Siqueira, da série Aprendendo Java, por ter feito este código junto comigo.

Para finalizar hoje, vamos criar a classe Contatos, que estende Repository, ele deve ficar dentro do pacote: package br.com.pedroHos.model.repositories.contato;

A Classe deve ser anotada @Stateless, certo tatu?

Com a classe criada, vamos estender Repository, e o tipo que vamos passar é a entidade Contato, que criamos no outro post sobre modelos. Com isso, já temos todos os métodos da Classe Repository.

Vai ficar assim ó:

package br.com.pedroHos.model.repositories.contato;

import javax.ejb.Stateless;

import br.com.pedroHos.model.entities.contato.Contato;
import br.com.pedroHos.model.repositories.Repository;

@Stateless
public class Contatos extends Repository<Contato> { }

Pronto, agora terminamos, simples né?

Por hoje era isso, até a próxima pessoal!

Anúncios

7 comentários

  1. Pingback: Aplicação Web com VRaptor 4 – Introdução | Pedro Hos
  2. Pingback: Aplicação Web com VRaptor 4 – Contato Controller | Pedro Hos
  3. Luciano · abril 30, 2015

    Meu wildfly da a seguinte mensagem:
    Session bean implementation class MUST be public, not abstract and not final – br.edu.utfpr.pb.questionarioacademico.repository.common.Repository won’t be considered as a session bean, since it doesn’t meet that requirement.
    Pode interferir em algo?

    • Pedro Henrique de Oliveira Silva · maio 1, 2015

      Luciano, obrigado pelo contato. Acredito que tenha algum método da classe Repository deve ser public e não abstract ou final. Poderia me mostrar o código?

      • Luciano · maio 1, 2015

        Opa Pedro.
        Obrigado pela atenção cara.
        A classe é a mesma do post, e pela mensagem do warn o que da pra entender é que é a classe que não deveria ser abstract: “Session bean implementation class MUST be public” – enfase no “class”.
        Mas assim, é só um warn as coisas estão funcionando a princípio, minha dúvida é se isso no futuro pode interferir em algo.

      • Pedro Henrique de Oliveira Silva · maio 1, 2015

        Acredito que não interfira em nada não. Mas qualquer coisa grita ae. Abraços

  4. Pingback: 01 Aplicação Web com VRaptor 4 – Introdução | Pedro Hos

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 )

Imagem do Twitter

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

Foto do Facebook

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

Foto do Google+

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

Conectando a %s