Estrutura de DAO para suportar lazy do Hibernate

5 respostas
luciano_castilho

Ola a todos(as)!

Estou tendo problemas ao utilizar o Hibernate para recuperar objetos que contém listas com outros objetos, pois nessa operação todos os objetos das listas também são recuperados do banco, deixando a consulta muito lenta e por vezes ocorrendo OutOfMemory!

Descobri que a propriedade “lazy” poderia resolver o problema, pois carregaria os objetos das listas somente quando fossem utilizados, porém nos testes práticos vi que isso só funciona se a session do hibernate permanecer aberta até o final da utilização dos objetos recuperados.

O problema é que na estrutura dos DAOs que uso para implementar a persistência, em cada método é obtida uma session e após o processamento ela é fechada.

Não estou conseguindo imaginar uma forma para que, somente depois que os resultados forem mostrados a session seja fechada, ainda mais porque esses DAOs são chamados de dentro de Actions do Struts e os resultados mostrados por tag-lib no JSP.

Gostaria de pedir ajuda para colegas que já tiveram esse problema, para fazer uma implementação que permita o uso de lazy com o Hibernate utilizando DAOs, toda a ajuda é bem-vinda.

Mui agradecido.
Luciano Castilho

:arrow: Segue o código de um DAO para exemplificar a implementação atual. (repare que em cada método a session é obtida de uma classe singletown e após o processamento a session é fechada, não permitindo assim o uso de “lazy”)

public class CidadeDAO {

  private SessionFactory sessionFactory;

	public CidadeDAO() {
		try {
			sessionFactory = HibernateUtil.getSessionFactory();
		} catch (HibernateException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public List getList() throws HibernateException {
		Session session = sessionFactory.openSession();
		List list = session.find("from Cidade");
		session.close();
		return list;
	}

	public void save(Cidade cidade) throws HibernateException {
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		try {
			session.saveOrUpdate(cidade);
			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			throw e;
		} finally {
			session.close();
		}
	}

	public void delete(Cidade cidade) throws HibernateException {
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		try {
			session.delete(cidade);
			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			throw e;
		} finally {
			session.close();
		}
	}

  public Cidade getById(Integer Id) throws HibernateException {
		Session session = sessionFactory.openSession();
		Cidade cidade = (Cidade) session.get(Cidade.class, Id);
		session.close();
		return cidade;
	}

	public List getListByNome(String nome) throws HibernateException {
		Session session = sessionFactory.openSession();
		List list = session.find(
                  "from Cidade cidade where lower(cidade.nome) like ?", nome.toLowerCase() + "%", Hibernate.STRING);
		session.close();
		return list;
	}

}

5 Respostas

_fs

O Struts possui interceptors?

Pergunto isso pois com WebWork basta criar um interceptor que abre a sessão e só a fecha depois que a view foi renderizada.

brunocosta

Em struts geralmente se usa um servlet filter, que abre a sessão, executa as actions e fecha a sessão… como descrito no Hibernate In Action… o código do método doFilter que eu uso aqui é +/- esse:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

       try {

           HibernateUtil.getSession();

            chain.doFilter(request, response);
            HibernateService.commitTransaction();

        } finally {
            HibernateService.closeSession();
        }

    }

No HibernateUtil, o método getSession abre uma sessão e a seta para um ThreadLocal, assim, getSession retorna a sessão para a thread atual, exatamente como descrito no Hibernate In Action.
Daí é só usar Session session = HibernateUtil.getSession() nos daos…

R

Como fazer isso em programas Swing, sem esses esquemas de filtros, de interceptors?
Não uso nenhum framework para desenvolvimento MVC.

_fs

Sem um “esquema” fica difícil/horrível. Se sua aplicação não suporta filters e interceptors não consigo imaginar a dor que deva ser aplicar constraints de segurança e coisas desse tipo.

Bom, de qualquer forma, vai ter que fazer na mão através da classe que chama os métodos no DAO.

R

E que tipo de esquema eu poderia utilizar em um desenvolvimento em swing?

Criado 29 de julho de 2005
Ultima resposta 1 de ago. de 2005
Respostas 5
Participantes 4