Org.hibernate.SessionException: Session is closed!

2 respostas
T

Pessoal, to implementando um CRUD aqui, e estou com o este problema:

org.hibernate.SessionException: Session is closed!

O Hibernate informa que a Session esta fechada, mas ao que vejo, não é o que acontece.

Tenho uma JSP que chama o metodo SaveCurso na Fachada, que chama o controlador e o DAOCurso(metodo insert).

Como no começo de cada metodo do DAO eu chamo o getSession(que abre sempre a Session) não sei pq ele informa que a Session está fechada.

Classe HibernateUtil

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package br.com.university.utils;

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

/**
 *
 * @author Thiago
 */
public class HibernateUtil {

    private static SessionFactory sessionFactory;
    private static Session session;

    static{
         AnnotationConfiguration confs = new AnnotationConfiguration().configure();
        sessionFactory = confs.buildSessionFactory();
    }

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

    public static void closeSession(){
        session.close();
    }

    public static void commitTransaction(){
        session.getTransaction().commit();
    }

    public static void closeSessionFactory(){
        sessionFactory.close();
    }

}

Classe DAOGeneric

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package br.com.university.data;

import br.com.university.utils.HibernateUtil;
import org.hibernate.Session;

/**
 *
 * @author Thiago
 */
public abstract class DAOGeneric {

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

    void closeSession(){
        HibernateUtil.getSession();
    }
    void commitTransaction(){
        HibernateUtil.commitTransaction();
    }

}

Classe DAOCurso

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package br.com.university.data;

import br.com.university.model.Curso;
import java.util.List;

/**
 *
 * @author Thiago
 */
public class DAOCurso extends DAOGeneric implements IDAOGeneric<Curso>{

    public void remove(Integer pk) {
        this.getSession().delete(this.search(pk));
        this.closeSession();
    }

    public Curso search(Integer pk) {
        Curso curso = (Curso) this.getSession().get(Curso.class, pk);
        this.closeSession();
        return curso;
    }

    public void edit(Curso entity) {
        this.getSession().update(entity);
        this.closeSession();
    }

    public void insert(Curso entity) {
        this.getSession().save(entity);
        this.commitTransaction();
        this.closeSession();
    }

    public List<Curso> list(){
        List<Curso> list = this.getSession().createQuery("from Curso curso").list();
        this.commitTransaction();
        this.closeSession();
        return list;
    }

}

2 Respostas

doravan

Cara, vc tá fechando a Factory.
A factory só pode ser fechada quando a aplicação for fechada, ou novas sessions não poderão ser criadas.
Sugiro que você crie um Singleton para manusear a factory e a session.
Assim você só fecha a session quando a aplicação encerrar.

Aí vai o meu modelo pro database service.

public class DatabaseService{

	private SessionFactory factory;
	private Session session;
	
	private DatabaseService(){
		AnnotationConfiguration configuration = new AnnotationConfiguration();
		configuration
		.setProperty("hibernate.connection.driver_class", "com.mysql.jdbc.Driver")	
		.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect")
		.setProperty("hibernate.connection.url", "jdbc:mysql://localhost/banco")
		.setProperty("hibernate.connection.username", "root")
		.setProperty("hibernate.connection.password", "senha")
		
		.setProperty("hibernate.connection.provider_class", "org.hibernate.connection.C3P0ConnectionProvider")
		.setProperty("hibernate.c3p0.min_size", "5")
		.setProperty("hibernate.c3p0.max_size", "20")
		.setProperty("hibernate.c3p0.acquire_increment", "5")
		.setProperty("hibernate.c3p0.max_statements", "50")
		.setProperty("hibernate.c3p0.timeout", "1800")
		.setProperty("hibernate.c3p0.idle_test_period", "500")

		.setProperty("hibernate.hbm2ddl.auto", "auto")
		.setProperty("show_sql", "true")
		.setProperty("format_sql", "true")
		.addAnnotatedClass(Objeto.class);
		
		factory = configuration.buildSessionFactory();
		session = factory.openSession();
	}
	
	private static class SingletonHolder{
		private final static DatabaseService instance = new DatabaseService();
	}
	
	public static DatabaseService getInstance() {
		return SingletonHolder.instance;
	}
	
	public Session getSession(){
		return session;
	}
        
        //só chame esse método quando sua aplicação for encerrada.
        public void close(){
		session.close();
		factory.close();
	}

}

nos daos você utiliza o seguinte

private final Session session = DatabaseService.getInstance().getSession();

public void save(Object object){
		Transaction tx = session.beginTransaction();
		session.save(object);
		tx.commit();
}

coloque as libs do c3p0 na pasta da sua aplicação, ele é um ótimo gerenciador de pool de conexões.
Você vai ganhar muito em desempenho dessa forma, e vai evitar erros de session is closed e afins.

Dê preferência à configuração programática, uma vez que sua aplicação fica muito mais limpa.

T

Cara, vlw, depois de tanto mexer na aplicação descobri que era isso mesmo, mas valeu a dica.

Abraços!

Criado 6 de março de 2011
Ultima resposta 9 de mar. de 2011
Respostas 2
Participantes 2