JPA e Hibernate: a consulta não retorna dados. Qual o problema?

8 respostas
C

Olá galera,

Depois de perder várias horas tentando resolver esse problema, eu recorro a vocês. Espero que possam me ajudar. Estou iniciando os estudos em JSF, JPA e Hibernate, e para isso estou desenvolvendo um sisteminha, mas a cada momento encontro um novo problema. Enfim, faz parte!!!

O problema é q a minha consulta não retorna nenhum dado. Não sei o porquê disso? Segue os códigos:

Meu entity:

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;

import java.io.Serializable;

@Entity
public class Login implements Serializable{
	
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue
	private int id;
	
	private String usuario;
	private String senha;
	
	public String getUsuario() {
		return usuario;
	}
	public void setUsuario(String usuario) {
		this.usuario = usuario;
	}
	public String getSenha() {
		return senha;
	}
	public void setSenha(String senha) {
		this.senha = senha;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}

}

Este é meu arquivo persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
    <persistence-unit name="persistenceUnit" 
                      transaction-type="RESOURCE_LOCAL">
        <class>br.com.srpvsp.entity.Login</class>     
        <properties>
        	
        	<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
	        <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
	        <property name="hibernate.connection.username" value="root"/>
	        <property name="hibernate.connection.password" value="root"/>
	        <property name="hibernate.connection.url" value="jdbc:mysql://localhost/livroeletronico"/>
	        <property name="hibernate.max_fetch_depth" value="3"/>
	        <property name="hibernate.format_sql" value="true" />
	        <property name="hibernate.use_sql_comments" value="false" />
	        <property name="hibernate.hbm2ddl.auto" value="create" />
	        <property name="hibernate.show_sql" value="false" />
	        <property name="hibernate.jdbc.batch_size" value="50" />
        	
            <!-- 
            <property name="hibernate.show_sql" value="false" />
            <property name="hibernate.format_sql" value="false" />
 
            <property name="hibernate.connection.driver_class" 
                      value="org.hsqldb.jdbcDriver" />
            <property name="hibernate.connection.url" 
                      value="jdbc:hsqldb:mem:mem:aname" />
            <property name="hibernate.connection.username" value="sa" />
 
            <property name="hibernate.dialect" 
                      value="org.hibernate.dialect.HSQLDialect" />
            <property name="hibernate.hbm2ddl.auto" value="create" />
            -->
        </properties>
    </persistence-unit>
</persistence>

A interface do meu Dao genérico:

import java.io.Serializable;
import java.util.List;

public interface IGenericoDao<T, Id extends Serializable> {
	
	public void atualizar(T entity);
	
	public void remover(T entity);
			
	public T inserir(T entity);	
	
	public List<T> buscarTodos();	
	
	public T buscarPorId(Id id);

}

A implementação do Dao genérico utilizando JPA:

import java.io.Serializable;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PersistenceContext;

public abstract class GenericoDaoImp<T, Id extends Serializable> implements IGenericoDao<T, Id> {

	private Class<T> persistentClass;
	    
    @PersistenceContext
    private EntityManager entityManager;
    
    private EntityManagerFactory emf;
        
	public GenericoDaoImp(Class<T> persistentClass) {
    	this.setEntityManager();    	
    	this.persistentClass = persistentClass;
    }

	
	public Class<T> getPersistentClass() {
		return persistentClass;
	}

	public void setEntityManager() {		
		if (this.entityManager == null)
		{
			if (emf == null){
				emf = Persistence.createEntityManagerFactory("persistenceUnit");
			}	
			
			this.entityManager = emf.createEntityManager();
		}
	}

	public EntityManager getEntityManager() {
		return entityManager;
	}

	public void atualizar(T entity) {		
		this.entityManager.persist(entity);
	}
	
	public abstract List<T> buscarTodos();

	public T buscarPorId(Id id) {
		return this.entityManager.find(this.persistentClass, id);		
	}

	public T inserir(T entity) {
		this.entityManager.persist(entity);
		return entity;
	}

	public void remover(T entity) {
		this.entityManager.remove(entity);		
	}	

}

O meu Dao genérico utilizando o Hibernate:

import java.io.Serializable;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.classic.Session;
import org.hibernate.criterion.Criterion;

public class GenericoHibernateDao<T, Id extends Serializable> extends GenericoDaoImp<T, Id> {
	
	public GenericoHibernateDao(Class<T> clazz){
		super(clazz);
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public List<T> buscarTodos() {	
		 return this.getCriteria().list();
	}
	
	@SuppressWarnings("unchecked")
	public List<T> buscarPorCriterios(List<Criterion> criterions){
		
		Criteria criteria = this.getCriteria();
		 
		 for (Criterion c : criterions) {			 
			 criteria.add(c);
		 }

		 return criteria.list();
	}	
	private Criteria getCriteria(){
		Session session = (Session) super.getEntityManager().getDelegate();

		 Criteria criteria = session.createCriteria(super.getPersistentClass());
		 
		 return criteria;
	}	

}

E aqui está o código que acessa o Dao:

List<Criterion> criterions = new ArrayList<Criterion>();
		GenericoHibernateDao<Login,Long> dao = new GenericoHibernateDao<Login,Long>(Login.class);
				
		List<Login> list = dao.buscarTodos();

O resultado dessa consulta é um objeto List vazio, sem dados. Qual o problema? O que está errado? O projeto executa sem erros, mas nada do resultado da consulta vir.

8 Respostas

L

ai vem a pergunta... qual o real sentido de se ter um Dao Tipado quando se usa hibernate ?? tipagem forte ?? ok ok... mas será que vale a pena ??

quando vc começar a usar, e ver que tem que manipular 3 ou Entidades diferente em uma mesma lógica de programação, instanciar 3 daos diferentes, usar 3 daos, quando podia fazer tudo em 1 ? ... vai começar a ver, que Daos tipados são mais para JDBC...

eu mudei meu approche e hoje uso um único Dao...

se sua ideia é para ter querys personalizadas eu volto a perguntar, e pq associar elas ao dao ?? e fazer essa amarração que dificulta o uso ?? pense na solução abaixo:

public interface GenericDao {
   public <T> T persist(T entity);
   public <T> T merge(T entity);
   public void remove(Object entity);
   public void refresh(Object entity);
   public <T> List<T> list(Class<T> target);
   public <T> T findById(Class<T> target,Serializable id);
   public <T> T findByExample(T example);
   public <T> List<T> listByExample(T example);
   public <T> T unique(DetachedCriteria dc);
   public <T> List<T> list(DetachedCriteria dc);
   public void commit();
   public void rollback();
   public void beginTransaction();
   public boolean isTransactionActive();
   public void close();
   public boolean isOpen();
}

agora você pode pensar, poxa vida, e onde eu guardo minha queries ?? ... crie objetos para cada classe quer guarda Queries, e crie uma fachada para as Queries....

veja a ideia...

public interface Query<R> {
   //executa esta query em um dao especifico, onde R é o retorno esperado
   R queryOn(GenericDao dao);
}

como criar uma query para listar ?

public class HibernateQueryList<T> implements Query<List<T>> {
   private final DetachedCriteria dc;
   public HibernateQueryList(DetachedCriteria dc) {
      this.dc = dc;
   }
   
   public List<T> queryOn(GenericDao dao) {
      return dao.list(dc);
   }
}

agora digamos que eu precise de algumas consultas para produto, como por Id, por data, quantidade, etc etc...

public class ProdutoQueries {
   public Query<Produto> byId(final Integer id) {
      return new Query<Produto>() {
         public Produto queryOn(GenericDao dao) {
            return dao.findById(Produto.class,id);
         }
      };
   }
   
   public Query<List<Produto>> listByQuantidade(Integer quantidade) {
      DetachedCriteria dc = DetachedCriteria.forClass(Produto.class);
      dc.add(Restrictions.eq("quantidade", quantidade);
      return new HibernateQueryList<Produto>(dc);
   }

   //e assim por diante...
}

ok.... mas lembrar o nome de cada classe que guarda as queries é um saco, mesmo que o nome seja TipoQueries, como no caso de ProdutoQueries ... pra este caso criamos a fachada de queries

public class Queries {
   public static ProdutoQueries forProduto() {
      return new ProdutoQueries();
   }
   public static PessoaQueries forPessoa() {
      return new PessoaQueries();
   }
    //etc etc
}

agora vê como fica legal de usar...

GenericDao dao = getDao(); //abstraindo como o dão chega...

Produto p12 = Queries.forProduto().byId(12).queryOn(dao);

List<Produto> pZeradosNoEstoque = Queries.forProduto().listByQuantidade(0).queryOn(dao);

List<Pessoa> homens = Queries.forPessoa().listBySexo(Sexo.MASCULINO).queryOn(dao);

e assim fica tudo mais fluente... pense nessa ideia...

C

Obrigada, Lavieri. Mas ainda preciso identificar e entender o problema com o meu código. Alguém tem sugestões sobre o que está ocorrendo?

L

muda essas propriedades

<property name="hibernate.show_sql" value="false" /> <property name="hibernate.format_sql" value="false" />

de false pra true

executa a query, e cola aqui o HQL que vai ser impresso

C

Lavieri,

Alterei as propriedades que indicou, mas o HQL não foi impresso na console. São exibidas outras diversas informações.

L

camilaoc:
Lavieri,

Alterei as propriedades que indicou, mas o HQL não foi impresso na console. São exibidas outras diversas informações.

algo estranho então… verifique se algum try{} catch{} ta engolindo alguma exceção… pois como vc da um list() em um criteria, uma consulta HQL deve ser gerada…

ligue em dbug mode, coloque um break point antes da consulta, e va rastreando… ele não ta executando a query, o que esta errado…

no código aqui colocado parece não ter problema.

C

Já debuguei diversas vezes, e também não adicionei o bloco try-catch. Debuguei novamente, mas nenhuma exceção é leventada. O curioso é que se eu tenho dados na minha tabela, ao executar a aplicação e utilizar tal tabela os dados são apagados. Tento inserir dados pelo método insert do EntityManager e nenhum dado é inserido na tabela. Caraca! Que loucura! Deve ser algum problema no arquivo de configuração, mas não consigo edentificar o que é.

L

é isso mesmo ^^

troca esse linha

para

a de cima, cria o banco a cada vez que vc starta a aplicação, a de baixo só cria tabelas que estiverem faltando, ou atualiza algo =P

C

Lavieri,

Caraca!!! Era isso mesmo! Já consigo realizar as consultas, agora só preciso resolver o meu problema com o insert que ainda não tá rolando. Bem, vou verificar aqui. Valeu! Se as coisas não caminharem, voltarei a postar aqui. Obrigada!!!

P.S.: Estou aguardo o post no seu BLOG.

Até mais!!!

Criado 29 de outubro de 2009
Ultima resposta 30 de out. de 2009
Respostas 8
Participantes 2