Classe de conexão hibernate da erro ao usar Fetch LAZY

2 respostas
furacao123

Aew Galera blz

Estou desenvolvendo uma aplicação Desktop usando Hibernate e estou enfrentando problemas com a minha classe GenericDAO para gerenciar as sessões, sempre usei na web e nunca tive problemas pois fazia um filtro que controlava a sessão.
Vou postar o código da minha classe Util e o Generic DAO para analisar e me ajudarem.

Classe HibernateUtil
public class HibernateUtil {

    private static final long serialVersionUID = 1L;
    private static HibernateUtil hbUtil;
    private SessionFactory sessionFactory;

    private HibernateUtil() {

          sessionFactory = new AnnotationConfiguration()
               .setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect")
               .setProperty("hibernate.connection.driver_class", "org.postgresql.Driver")
               .setProperty("hibernate.connection.url", "jdbc:postgresql://192.168.0.101:5432/template1")
               .setProperty("hibernate.connection.username", "postgres")
               .setProperty("hibernate.connection.password", "postgres")
               .setProperty("hibernate.hbm2ddl.auto", "false")
               .setProperty("hibernate.show_sql", "false")
               .setProperty("hibernate.format_sql", "true")
               .setProperty("hibernate.c3p0.acquire_increment", "1")
               .setProperty("hibernate.c3p0.idle_test_period", "300")
               .setProperty("hibernate.c3p0.max_size", "5")
               .setProperty("hibernate.c3p0.max_statements", "50")
               .setProperty("hibernate.c3p0.min_size", "5")
               .setProperty("hibernate.c3p0.timeout", "300")
               .setProperty("hibernate.current_session_context_class", "thread")
               .addAnnotatedClass(Empresa.class)
               .addAnnotatedClass(Cliente.class)
               .addAnnotatedClass(Venda.class)
               .addAnnotatedClass(Fornecedor.class)

               .buildSessionFactory();
    }

    public Session getSession() {
        Session toReturn = sessionFactory.openSession();
        toReturn.beginTransaction();
        return toReturn;
    }
    // aqui eu tentei fazer um singleton improvisado mas não mudou nada
    public static HibernateUtil getInstance() {
        if(hbUtil == null) {
            hbUtil = new HibernateUtil();
        }
        return hbUtil;
    }
Meu GenericDAO
public abstract class GenericDAO {

    protected Session getSession(){
        return HibernateUtil.getInstance().getSession();
    }

protected <T extends Serializable> List<T> getPureList(Class<T> classToCast, String query, Object[]... parametros) {
        Session ses = getSession();
        Query qr = ses.createQuery(query);
        for(Object[] param : parametros) {
            qr.setString(param[0].toString(), param[1].toString().concat("%"));
        }
        List<T> retorno = qr.list();
        ses.getTransaction().commit();
        //se eu tiro essa linha eu consigo usar o Fetch como LAZY mas ae a sessao nunca é fechada   
        ses.close();
        return retorno;
    }

protected <T extends Serializable> T getPurePojo(Class<T> classtoSearch, Serializable key) {
        Session ses = getSession();
        Serializable retorno = (Serializable) ses.get(classtoSearch, key);
        ses.getTransaction().commit();
        //se eu tiro essa linha eu consigo usar o Fetch como LAZY mas ae a sessao nunca é fechada
        ses.close();
        return (T) retorno;
    }

protected void salvaOuAtualizaPojo(Serializable pojo) {
        Session ses = getSession();
        ses.saveOrUpdate(pojo);
        ses.getTransaction().commit();
        //se eu tiro essa linha eu consigo usar o Fetch como LAZY mas ae a sessao nunca é fechada
        ses.close();
    }
}
e aqui o meu DAO comum
public class EmpresaDAO extends GenericDAO {

    public Empresa getById(String id) {
      return getPurePojo(Empresa.class, id);
   }

   public List<Empresa> getAll() {
      return getPureList(Empresa.class, "FROM Empresa empresa");
   }

}
e aqui meu bean com as anotações do relacionamento
@OneToMany(mappedBy="empresa", fetch=FetchType.LAZY)
    @Cascade(CascadeType.ALL)
    private Collection<Venda> Venda;

    @OneToMany(mappedBy="empresa",fetch=FetchType.LAZY)
    @Cascade(CascadeType.ALL)
    private Collection<Cliente> cliente;

Se eu tiro a linha onde fecha a sessao eu consigo trabalhar normalmente dessa forma, mas isso é recomendado? qual a melhor maneira para gerenciar essas sessões e trabalhar com LAZY??

se eu nao tiro essa linha onde fecha a sessão eu sou obrigado a usar o Fetch como EAGER e apenas um OnToMany no bean pois se nao da erro de multiple bags.

Como resolvo esse problema desktop?

Obrigado.

2 Respostas

Jair_Rillo_Junior

Como você mesmo disse, se você fechar a Sessão o LAZY não vai funcionar, isso é o comportamento normal, pois o LAZY nada mais é que um PROXY que quando é executado ele busca as informações “reais” no banco de dados, e para isso o objeto tem que estar gerenciado (e session aberta).

Existem algumas maneiras de resolver isso, vai depender do que se encaixar melhor para voce

  • Manter o objeto gerenciado e só fechar a session quando você parar de trabalhar com ele
  • Depois que carregar o objeto, carrega também as Collection necessárias (Hibernate.initialize()) antes de fechar a session
  • Utiliza um objeto TO (Transfer Object), para copiar os dados do objeto gerenciado para esse objeto.

A princípio eu penso nessas 3 opções. Na maioria dos casos, eu creio que a opção 2 é a mais adequada.

Espero ter ajudado

furacao123

mas no esquema que eu fiz de não fechar a session, vou enfrentar algum problema? pois na minha classe HibernateUtil faço a verificação se a session ja existe, no caso a session ficara aberta até o fechamento do programa, acontece algum problema de acesso ao banco?

Criado 19 de março de 2010
Ultima resposta 19 de mar. de 2010
Respostas 2
Participantes 2