Arquivo

Textos com Etiquetas ‘SQL’

Hibernate – Utilizando a api Criteria

27, dezembro, 2009 4 comentários

Esse post faz parte de uma série que estou preparando sobre o hibernate, o primeiro foi sobre a extensão especial Hibernate Spatial e esse segundo irei falar sobre um pouco sobre um poderoso recurso do Hibernate, a API Criteria. Nesse tutorial não irei entrar em detalhes sobre configuração do Hibernate, assume-se que você tem o hibernate pré-configurado, irei apenas falar da API.

Primeiro criaremos nossa entidade exemplo “Cliente” :


package modelo;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

/**
 *
 * @author lucas
 */
@Entity
public class Cliente implements Serializable {

    @Id
    @GeneratedValue
    private int id;
    private String nome;
    private int idade;
    private String cpf;
    private double saldo;

    public String getCpf() {
        return cpf;
    }

    public int getIdade() {
        return idade;
    }

    public void setIdade(int idade) {
        this.idade = idade;
    }

    public void setCpf(String cpf) {
        this.cpf = cpf;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public double getSaldo() {
        return saldo;
    }

    public void setSaldo(double saldo) {
        this.saldo = saldo;
    }
}

Até aqui nada de novo, marcamos a classe com a anotação @Entity, para indicar que é uma entidade e marcamos o atributo id com as anotações @Id e @GeneratedValue, a primeira diz que esse atributo é a chave primaria e segunda que seu valor será gerado automaticamente. O cliente também tem um atributo saldo, que representará um valor de saldo, tecnicamente o cliente não deveria possuir um saldo e sim um objeto conta e a conta possuir um saldo, porém como o objetivo desse tutorial é demonstrar a api Criteria, não me apeguei a regras de modelagem OO.

Agora criaremos a classe HibernateUtil, que irá conter um método estático que devolve um objeto Session. Com essa classe não precisaremos ficar instanciando o objeto Session toda vez que precisarmos acessar o banco. O próprio netbeans tem um assistente que gera automaticamente essa classe.


package util;

import org.hibernate.Session;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.SessionFactory;

/**
 * Hibernate Utility class with a convenient method to get Session object.
 *
 * @author lucas
 */
public class HibernateUtil {
    private static final SessionFactory sessionFactory;

    static {
        try {
            sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static Session getSession() {
        return sessionFactory.openSession();
    }
}

Agora criaremos um Dao genérico com os métodos padrão em todos os DAO’s, evitando assim o trabalho de implementar os mesmos métodos em todos os DAO’s.


package Dao;

import org.hibernate.Session;
import org.hibernate.Transaction;
import util.HibernateUtil;

/**
 *
 * @author lucas
 */
public class Dao<T> {

    private Class classe;
    private Session session;

    protected Session getSession() {
        return session;
    }

    public Dao(Class classe) {
        this.session = HibernateUtil.getSession();
        this.classe = classe;
    }

    public void salvar(T objeto){
        session.save(objeto);
    }

    public void remover(T objeto){
        Transaction ts = session.beginTransaction();
        session.save(objeto);
        ts.commit();
    }

    public void atualizar(T objeto){
        Transaction ts = session.beginTransaction();
        session.update(objeto);
        ts.commit();
    }

    public T load(long id){
        return (T) session.load(classe, id);
    }
}

Utilizamos na declaração da classe o tipo parametrizado T (de type), indicando que essa classe terá um tipo de Objeto.

No seu construtor, ela receberá um objeto que definirá o tipo usado na classe e utiliza o HibernateUtil para receber uma session. Observe que o método getSession() do Dao genérico é protected pois suas classes filhas precisarão acessa-lo para seus próprios métodos.

Agora criaremos o ClienteDao, que herdará todos os métodos do Dao genérico, sendo assim não será necessário criar os métodos básicos (Salvar, Atualzar, Remover e Carregar).


package Dao;

import java.util.Collection;
import modelo.Cliente;
import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

/**
 *
 * @author lucas
 */
public class ClienteDao extends Dao<Cliente> {

    public ClienteDao(){
        super(Cliente.class);
    }

    public Collection<Cliente> buscaPorNome(String nome){
        Criteria c = getSession().createCriteria(Cliente.class);
        c.add(Restrictions.ilike("nome", nome));
        c.addOrder(Order.asc("idade"));
        return c.list();
    }

    public int qtdeTotalCliente(){
        Criteria c = getSession().createCriteria(Cliente.class);
        c.setProjection(Projections.rowCount());
        return (Integer) c.uniqueResult();
    }

    public int totalSaldo(){
        Criteria c = getSession().createCriteria(Cliente.class);
        c.setProjection(Projections.sum("saldo"));
        return (Integer) c.uniqueResult();
    }
}

Agora conheceremos o poder da API Criteria.
No método buscaPorNome, é recebido como parametro uma String que representa o nome do Cliente a ser buscado.
Em seguida é criado o objeto Criteria, através do método createCriteria() e esse recebe como argumento o tipo de objeto a ser pesquisado, como o objeto está mapeado para uma tabela do banco (eu não demonstrei aqui como mapear, porque como disse não é o objetivo do artigo) a API Criteria já sabe exatamente em qual(is) tabela(s) buscar.
Na linha seguinte utilizamos o método add() para refirnarmos a busca, no nosso caso adicionamos uma restrição através do ilike() do objeto Restrictions e passamos dois parâmetros o primeiro é o campo que será aplicada a restrição e o segundo o valor da restrição. Então no nosso caso informamos que queremos apenas os registros com o campo nome igual ao valor da variável nome.
Para melhorar ainda mais a busca, podemos definir a ordem que os objetos será apresentados. Para isso na linha seguinte usamos o método addOrder() e usamos o objeto Order para definir a ordem, que no nosso caso será o campo idade.
Na linha seguinte é usado o método list() que retorna uma lista de objetos que se encaixa no perfil informado ou null caso não encontre nada.

No método qtdeTotalCliente() é retornado um inteiro com a quantidade total de registro de Clientes salvos no banco. Para isso é utilizado o método setProjection e é passado como parâmetro o que queremos fazer, no caso utilizamos o método rowCount() do Projections para contar a quantidade de registros.
Para finalizar usamos o uniqueResult() para retornar a quantidade de registros.

E para finalizar o artigo, no totalSaldo() estamos utilizando também o setProjection para somar os valores de um determinado campo de todos os registros do banco, para isso utilizamos o método sum() do objeto Projections

Bom, no geral é isso. A API Criteria é muito poderosa, podemos ser utilizada para realizar (quase) todas as queries que você desejar, porém muita gente acha mais rápido e produtivo escrever as queries utilizando a HQL (Hibernate Querie Language) que irei mostrar no próximo artigo.

Categories: Hibernate, Java, SQL Tags: , ,

Pra quem quer aprender SQL

9, abril, 2009 3 comentários

Bom pessoal, para quem tem interesse em aprender SQL, tá aí um excelente ebook (em inglês) gratuito: “SQL for Web Nerds”

http://philip.greenspun.com/sql/

Um material muito completo e de excelente qualidade, escrito por Philip Greenspun.  Estou querendo montar um projeto de tradução do ebook para o português, caso alguem se interesse, entre em contato.

Categories: SQL Tags: