线程在HIbernate

时间:2015-11-06 15:42:43

标签: hibernate session

我有一个jsf项目,当你点击一个链接进入页面时,会调用一个运行查询来填充所述页面上显示的列表的方法。

但是,当我在两个打开的标签页或两个不同的浏览器同时打开链接时,其中一个似乎正在关闭会话而另一个仍在工作,我得到了例外

 Servlet.service() for servlet [Faces Servlet] in context with path [/wplexeo] threw exception [Session is closed!] with root cause

这是代码。调用的方法是每次调用时打开和关闭会话的execuNamedQuery。我虽然ThreadLocal应该避免这种情况,或者我现在不应该关闭会议。

 private static ThreadLocal<Session> sessions = new ThreadLocal<Session>();
 private static ThreadLocal<Transaction> transactions = new ThreadLocal<Transaction>();
 private static SessionFactory sessionFactory;

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

public List<? extends Entity> executesNamedQuery(final String query, final Map<String, Object> parameters)
    throws DaoHibernateException
{
    this.openSessionAndBeginTransaction();
    final Query namedQuery = this.session.getNamedQuery(query);
    if (parameters != null)
    {
        for (final String paramName : parameters.keySet())
        {
            namedQuery.setParameter(paramName, parameters.get(paramName));
        }
    }
    final List<? extends Entity> result = namedQuery.list();
    this.commitTransactionAndCloseSession();
    return result;
}
  private void openSessionAndBeginTransaction() throws DaoHibernateException
{
    this.session = HibernateUtil.openSession();
    try
    {
        this.transaction = HibernateUtil.beginTransaction();
    }
    catch (final HibernateException e)
    {
        System.out.println(e.getCause());
        throw new DaoHibernateException(ExceptionType.ABRIR_TRANSACAO, e, null);
    }
}




 public static Session openSession()
{
    HibernateUtil.sessions.set(HibernateUtil.sessionFactory.openSession());
    return HibernateUtil.sessions.get();
}

 public static Transaction beginTransaction()
{
    HibernateUtil.transactions.set(currentSession().beginTransaction());
    return HibernateUtil.transactions.get();
}

 private void commitTransactionAndCloseSession() throws DaoHibernateException
{
    try
    {
        this.transaction.commit();
    }
    catch (final HibernateException e)
    {
       throw new DaoHibernateException(ExceptionType.COMITTAR_TRANSACAO, e, null);
    }
    finally
    {
        HibernateUtil.closeCurrentSession();
    }
}

/**
 * Fecha a Session corrente
 */
public static void closeCurrentSession()
{
    HibernateUtil.sessions.get().close();
    HibernateUtil.sessions.set(null);
}

我是否在错误的时间关闭了会话?我该什么时候关闭它?我是以错误的方式使用ThreadLocal吗?我现在没有改变数据,只是检索,所以我应该可以让两个用户同时进入同一页面吗?

1 个答案:

答案 0 :(得分:2)

我没有运行并测试过这段代码。根据我对Hibernate及其会话和事务工作方式的理解,我认为下面的代码应该可以帮助您实现目标。 Reference credit

import java.util.List;
import java.util.Map;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.metamodel.domain.Entity;

public final class HibernateTLDao {
    private static final ThreadLocal<Session> threadSession = new ThreadLocal<Session>();
    private static final ThreadLocal<Transaction> threadTransaction = new ThreadLocal<Transaction>();
    private static SessionFactory sessionFactory;

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

    public List<? extends Entity> executesNamedQuery(final String query, final Map<String, Object> parameters) {
        beginTransaction();
        final Query namedQuery = threadSession.get().getNamedQuery(query);
        if (parameters != null) {
            for (final String paramName : parameters.keySet()) {
                namedQuery.setParameter(paramName, parameters.get(paramName));
            }
        }
        @SuppressWarnings("unchecked")
        final List<? extends Entity> result = namedQuery.list();
        commitTransaction();
        return result;
    }

    public static Session getCurrentSession() {
        Session s = threadSession.get();
        try {
            if (s == null || !s.isOpen()) {
                s = sessionFactory.openSession();
                threadSession.set(s);
            }
        } catch (HibernateException ex) {
            ex.printStackTrace();
        }
        return s;
    }

    public static void closeSession() {
        try {
            final Session s = threadSession.get();
            if (s != null && s.isOpen()) {
                s.close();
            }
        } catch (HibernateException ex) {
            ex.printStackTrace();
        } finally {
            threadSession.set(null);
        }
    }

    public static void beginTransaction() {
        Transaction tx = threadTransaction.get();
        try {
            if (tx != null && !tx.isActive()) {
                tx = null;
                threadTransaction.set(null);
            }
            if (tx == null) {
                if (threadSession.get() != null && threadSession.get().isOpen()) {
                    threadSession.get().close();
                    threadSession.set(null);
                }
                tx = getCurrentSession().beginTransaction();
                threadTransaction.set(tx);
            }
        } catch (HibernateException ex) {
            ex.printStackTrace();
        } finally {
            if (threadSession.get() == null || !threadSession.get().isOpen()) {
                getCurrentSession();
            } else {
                threadSession.get().clear();
            }
        }
    }

    public static void commitTransaction() {
        final Transaction tx = threadTransaction.get();
        try {
            if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) {
                Session s = getCurrentSession();
                s.flush();
                tx.commit();
            }
        } catch (HibernateException ex) {
            rollbackTransaction();
            ex.printStackTrace();
        } finally {
            threadTransaction.set(null);
            closeSession();
        }
    }

    public static void rollbackTransaction() {
        final Transaction tx = threadTransaction.get();
        try {
            if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) {
                tx.rollback();
            }
        } catch (HibernateException ex) {
            ex.printStackTrace();
        } finally {
            threadTransaction.set(null);
            closeSession();
        }
    }
}