`
personbeta
  • 浏览: 159970 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

HibernateSessionFactory与ThreadLocal

    博客分类:
  • java
 
阅读更多

 

  1. 相关知识

 

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;

/**
 * Configures and provides access to Hibernate sessions, tied to the
 * current thread of execution.  Follows the Thread Local Session
 * pattern, see {@link http://hibernate.org/42.html }.
 */
public class HibernateSessionFactory {

    /** 
     * Location of hibernate.cfg.xml file.
     * Location should be on the classpath as Hibernate uses  
     * #resourceAsStream style lookup for its configuration file. 
     * The default classpath location of the hibernate config file is 
     * in the default package. Use #setConfigFile() to update 
     * the location of the configuration file for the current session.   
     */
    private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
	private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
    private  static Configuration configuration = new Configuration();    
    private static org.hibernate.SessionFactory sessionFactory;
    private static String configFile = CONFIG_FILE_LOCATION;

	static {
    	try {
			configuration.configure(configFile);
			sessionFactory = configuration.buildSessionFactory();
		} catch (Exception e) {
			System.err
					.println("%%%% Error Creating SessionFactory %%%%");
			e.printStackTrace();
		}
    }
    private HibernateSessionFactory() {
    }
	
	/**
     * Returns the ThreadLocal Session instance.  Lazy initialize
     * the <code>SessionFactory</code> if needed.
     *
     *  @return Session
     *  @throws HibernateException
     */
    public static Session getSession() throws HibernateException {
        Session session = (Session) threadLocal.get();

		if (session == null || !session.isOpen()) {
			if (sessionFactory == null) {
				rebuildSessionFactory();
			}
			session = (sessionFactory != null) ? sessionFactory.openSession()
					: null;
			threadLocal.set(session);
		}

        return session;
    }

	/**
     *  Rebuild hibernate session factory
     *
     */
	public static void rebuildSessionFactory() {
		try {
			configuration.configure(configFile);
			sessionFactory = configuration.buildSessionFactory();
		} catch (Exception e) {
			System.err
					.println("%%%% Error Creating SessionFactory %%%%");
			e.printStackTrace();
		}
	}

	/**
     *  Close the single hibernate session instance.
     *
     *  @throws HibernateException
     */
    public static void closeSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
        threadLocal.set(null);

        if (session != null) {
            session.close();
        }
    }

	/**
     *  return session factory
     *
     */
	public static org.hibernate.SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	/**
     *  return session factory
     *
     *	session factory will be rebuilded in the next call
     */
	public static void setConfigFile(String configFile) {
		HibernateSessionFactory.configFile = configFile;
		sessionFactory = null;
	}

	/**
     *  return hibernate configuration
     *
     */
	public static Configuration getConfiguration() {
		return configuration;
	}

}

 

 

以上为HibernateSessionFactory的源代码,对Session的处理使用了ThreadLocal

ThreadLocal的相关知识可见:http://blog.csdn.net/qjyong/article/details/2158097

 

因为HibernateSessionFactory工具类使用了ThreadLocal保存Session,所以在同一线程内,只要还没有调用Session.close(),那么每次调用HibernateSessionFactory.getSession()时,获取到的Session都是同一个。

 

2. 遇到的问题

 

一个Tomcat+SSH系统,在某次操作数据库操作时,代码执行流程大致如下:

 

 

Session session=HibernateSessionFactory.getSession();
session.beginTransaction();
....//发生了异常,并且未捕获处理
session.getTransaction().commit();
session.close();

 因为session操作数据库期间发生了异常,导致session没有close。结果发现访问其他页面时操作数据库发生了错误,并且报错异常信息包含以上代码操作的数据库表的实体类名,而实际上这些页面并没有操作这个表。

 

后来分析结论:Tomcat维护着自己的一个线程池,对于浏览器的每个请求或连接都会从线程池中拿出一个线程进行处理,处理出错的页面的对应线程刚好是之前执行以上代码的线程,所以在通过HibernateSessionFactory.getSession()获取Session时,获取到的Session还是上一个请求的Session,而该Session由于处理过程中发生了异常导致还没有Close,Session还缓存有之前操作的信息,而对于这些信息,Session在数据检查时认为有错,因此又抛出了异常。

 

说得有点乱,估计只有我自己明白是咋回事 。。。

 

分享到:
评论

相关推荐

    J2EE利用Hibernate采用B/S架构网页设计

    public class HibernateSessionFactory { /** * Location of hibernate.cfg.xml file. * Location should be on the classpath as Hibernate uses * #resourceAsStream style lookup for its configuration ...

    中小公司人事管理系统

    private static SessionFactory sf=null; private static Session s=null; private static final ThreadLocal&lt;Session&gt; sessionThread=new ThreadLocal(); private static final ThreadLocal&lt;Transaction&gt; ...

    Spring.3.x企业应用开发实战(完整版).part2

    12.2.1 配置SessionFactory 12.2.2 使用HibernateTemplate 12.2.3 处理LOB类型数据 12.2.4 添加Hibernate事件监听器 12.2.5 使用原生Hibernate API 12.2.6 使用注解配置 12.2.7 事务处理 12.2.8 延迟加载的问题 12.3...

    Spring3.x企业应用开发实战(完整版) part1

    12.2.1 配置SessionFactory 12.2.2 使用HibernateTemplate 12.2.3 处理LOB类型数据 12.2.4 添加Hibernate事件监听器 12.2.5 使用原生Hibernate API 12.2.6 使用注解配置 12.2.7 事务处理 12.2.8 延迟加载的问题 12.3...

    Spring 2.0 开发参考手册

    ThreadLocal目标源 7.11. 定义新的通知类型 7.12. 更多资源 8. 测试 8.1. 简介 8.2. 单元测试 8.3. 集成测试 8.3.1. Context管理和缓存 8.3.2. 测试fixture的依赖注入 8.3.3. 事务管理 8.3.4. 方便的变量...

    spring chm文档

    ThreadLocal目标源 7.11. 定义新的通知类型 7.12. 更多资源 8. 测试 8.1. 简介 8.2. 单元测试 8.3. 集成测试 8.3.1. Context管理和缓存 8.3.2. 测试fixture的依赖注入 8.3.3. 事务管理 8.3.4. 方便的变量...

    Spring中文帮助文档

    ThreadLocal目标源 7.11. 定义新的Advice类型 7.12. 更多资源 8. 测试 8.1. 简介 8.2. 单元测试 8.2.1. Mock对象 8.2.2. 单元测试支持类 8.3. 集成测试 8.3.1. 概览 8.3.2. 使用哪个支持框架 8.3.3. ...

    Spring API

    ThreadLocal目标源 7.11. 定义新的Advice类型 7.12. 更多资源 8. 测试 8.1. 简介 8.2. 单元测试 8.2.1. Mock对象 8.2.2. 单元测试支持类 8.3. 集成测试 8.3.1. 概览 8.3.2. 使用哪个支持框架 8.3.3. ...

    Spring-Reference_zh_CN(Spring中文参考手册)

    ThreadLocal目标源 7.11. 定义新的通知类型 7.12. 更多资源 8. 测试 8.1. 简介 8.2. 单元测试 8.3. 集成测试 8.3.1. Context管理和缓存 8.3.2. 测试fixture的依赖注入 8.3.3. 事务管理 8.3.4. 方便的变量 8.3.5. ...

    spring-framework-reference4.1.4

    Not Using Commons Logging ................................................................... 12 Using SLF4J ..............................................................................................

    spring-framework-reference-4.1.2

    Not Using Commons Logging ................................................................... 12 Using SLF4J ..............................................................................................

Global site tag (gtag.js) - Google Analytics