Hibernate Utilizando a api Criteria
01 package modelo;
02
03 import java.io.Serializable;
04 import javax.persistence.Entity;
05 import javax.persistence.GeneratedValue;
06 import javax.persistence.Id;
07
08 /**
09 *
10 * @author Thiago Fonseca
11 */
12 @Entity
13 public class Cliente implements Serializable {
14
15 @Id
16 @GeneratedValue
17 private int id;
18 private String nome;
19 private int idade;
20 private String cpf;
21 private double saldo;
22
23 public String getCpf() {
24 return cpf;
25 }
26
27 public int getIdade() {
28 return idade;
29 }
30
31 public void setIdade(int idade) {
32 this.idade = idade;
33 }
34
35 public void setCpf(String cpf) {
36 this.cpf = cpf;
37 } 38
39 public int getId() {
40 return id;
41 }
42
43 public void setId(int id) {
44 this.id = id;
45 }
46
47 public String getNome() {
48 return nome;
49 }
50
51 public void setNome(String nome) {
52 this.nome = nome;
53 }
54
55 public double getSaldo() {
56 return saldo;
57 }
58
59 public void setSaldo(double saldo) {
60 this.saldo = saldo;
61 }
62 }
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.
01 package util;
02
03 import org.hibernate.Session;
04 import org.hibernate.cfg.AnnotationConfiguration;
05 import org.hibernate.SessionFactory;
06
07 /** 08
* Hibernate Utility class with a convenient method to get Session
object.
09 *
10 * @author Thiago Fonseca
11 */
12 public class HibernateUtil {
13 private static final SessionFactory sessionFactory;
14
15 static {
16 try {
17
sessionFactory = new
AnnotationConfiguration().configure().buildSessionFactory();
18 } catch (Throwable ex) {
19 throw new ExceptionInInitializerError(ex);
20 }
21 }
22
23 public static Session getSession() {
24 return sessionFactory.openSession();
25 }
26 }
01 package Dao;
02
03 import org.hibernate.Session;
04 import org.hibernate.Transaction;
05 import util.HibernateUtil;
06
07 /**
08 *
09 * @author Thiago Fonseca
10 */
11 public class Dao<T> {
12
13 private Class classe;
14 private Session session;
15
16 protected Session getSession() {
17 return session;
18 }
19
20 public Dao(Class classe) {
21 this.session = HibernateUtil.getSession();
22 this.classe = classe;
23 }
24
25 public void salvar(T objeto){
26 session.save(objeto);
27 }
28
29 public void remover(T objeto){
30 Transaction ts = session.beginTransaction();
31 session.save(objeto);
32 ts.commit();
33 }
34
35 public void atualizar(T objeto){
36 Transaction ts = session.beginTransaction();
37 session.update(objeto);
38 ts.commit();
39 }
40
41 public T load(long id){
42 return (T) session.load(classe, id);
43 }
44 }
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).
01 package Dao;
02
03 import java.util.Collection;
04 import modelo.Cliente;
05 import org.hibernate.Criteria;
06 import org.hibernate.criterion.Order;
07 import org.hibernate.criterion.Projections;
08 import org.hibernate.criterion.Restrictions;
09 10 /**
11 *
12 * @author Thiago Fonseca
13 */
14 public class ClienteDao extends Dao<Cliente> {
15
16 public ClienteDao(){
17 super(Cliente.class);
18 }
19
20 public Collection<Cliente> buscaPorNome(String nome){
21 Criteria c = getSession().createCriteria(Cliente.class);
22 c.add(Restrictions.ilike("nome", nome));
23 c.addOrder(Order.asc("idade"));
24 return c.list();
25 }
26
27 public int qtdeTotalCliente(){
28 Criteria c = getSession().createCriteria(Cliente.class);
29 c.setProjection(Projections.rowCount());
30 return (Integer) c.uniqueResult();
31 }
32
33 public int totalSaldo(){
34 Criteria c = getSession().createCriteria(Cliente.class);
35 c.setProjection(Projections.sum("saldo"));
36 return (Integer) c.uniqueResult();
37 }
38 } [quote]
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 iguais ao valor da variável nome.
Para melhorar ainda mais a busca, podemos definir a ordem que os objetos serão 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.