Hibernate:清理会话

时间:2015-01-15 01:21:41

标签: java multithreading hibernate session thread-safety

假设我有以下内容:

public class DAOFactory {
    @Inject private final SessionFactory factory;
    private final ThreadLocal<Session> session = new ThreadLocal<>();

    // In a nutshell: create an AbstractDAO associated with the session object held by the ThreadLocal above
    public <T> AbstractDAO<T> createObject(Class<T> objectClass) { ... }
}

我遇到的问题是需要关闭这些会话,只有从createObject()创建DAO的线程才能这样做。显然,AbstractDAO不能有一个紧密的例程,因为相同的Session可以与多个AbstractDAO对象相关联,因此DAOFactory必须承担关闭会话的负担。仍然存在悬空Session的风险:如果创建AbstractDAO的主题不再存在,关联的Session如何关闭?

我的一种方法是使用如下清理方法:

public class DAOFactory {
    // createObject() uses Thread.getCurrentThread.getId() and sessionMap.computeIfAbsent()
    private final ConcurrentMap<Long, Session> sessionMap = new ConcurrentHashMap<>();

    public void cleanup() {
        for (Session session : sessionMap.values()) {
            session.close();
        }
        sessionMap.clear();
    }
}

问题是“这种方法有多安全”,“这是一个好主意”,“应该这样做”吗?如果没有,有什么好的选择?

请注意,DAOFactory主要是在考虑某种测试情况的​​情况下创建的:一个线程启动测试运行并创建一个DAOFactory,它可能会产生其他使用它的线程。创建DAOFactory的线程将始终比它产生的任何线程更长,并且将始终是在测试结束时调用cleanup()的线程。

1 个答案:

答案 0 :(得分:0)

手动会话管理不是一个好主意。 Hibernate已经提供了一个SPI,所以你不必自己做。

我建议你开始使用Spring事务管理,它也提供自动会话管理。