论坛首页 Java企业应用论坛

请教一个用ThreadLocal管理session的问题

浏览 9583 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2006-08-16  
环境:JDK1.5,hibernate3.1,tomcat5.5
---------------------------------------------------------------
我是用ThreadLocal管理session,具体如下:

private static ThreadLocal<Session> sessionMap =
        new ThreadLocal<Session>();

protected Session getSession() {
    Session session = sessionMap.get();
    if (session == null || !session.isOpen()) {
        session = sessionFactory.openSession();
        sessionMap.set(session);
    }
    return session;
}

---------------------------------------------------------------
我操作hibernate的方式是:
1.一对多关系,多方使用延迟加载
2.读取数据库时,不关闭session.
3.更新数据库(save,update or delete)时,提交事务并关闭session.

在单个用户进行操作时:
1.读取数据库时没有问题,用户始终只使用一个session.
2.用户更新数据库之后,会重新生成一个session用来读取数据库
---------------------------------------------------------------
我遇到的问题:

在两个用户(A,B)同时进行操作时:
A用户初始化session,并读取了一次数据库,之后的读取操作将不会再读数据库,而是从缓存中读取(控制台仅生成了一次sql读取语句).
此时,如果B用户对数据库进行了更新,A用户再读取,则仍旧读取的是缓存里面的数据(控制台未生成新的sql读取语句).
(因为他未被告知数据库已更新,未重新获取session).

我测试发现,如果A用户已经打开缓存,B用户更新数据库之后,
A用户必须等30秒之后再获取数据才能得到正确的结果(控制台生成了sql语句).

请问:
我想让B用户更新之后,A用户立即得到更新结果(直接从数据库中读取或新生成session),但之后就不再从数据库中读取,除非发生另外一次更新事件.
这种情况有办法解决吗?
   发表时间:2006-08-17  
A用户操作之前 session.refresh(obj)呢?
0 请登录后投票
   发表时间:2006-08-17  
好像不可以,那样只是用A自己的session来刷新,别的用户不会受到影响的。
0 请登录后投票
   发表时间:2006-11-22  
我也碰到过这个问题,当我更新过一条数据后,立即得到更新过数据时,却还是得到的是老数据。
  ,如果楼主解决,请通知下小弟
0 请登录后投票
   发表时间:2006-11-22  
每次更新操作都得flush和close。
0 请登录后投票
   发表时间:2006-11-23  
你的session是不是没有关闭?session如果没有关闭,一级缓存当然也没有更新去数据库。session就像connection,都是需要尽快释放的资源。
0 请登录后投票
   发表时间:2006-11-23  
我也碰到过这个问题,楼主肯定是没有把session关闭,每次http请求完之后应该把session关闭,缓存中的数据在一个http请求中共享应该已经够了
0 请登录后投票
   发表时间:2006-11-23  
你更新之提交事务就行了为什么关闭SESSION呢?,看看spring的open session in view的源代码
0 请登录后投票
   发表时间:2007-04-18  
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;

public class NetshopSessionFactory {	

    private static String CONFIG_FILE_LOCATION = "/hibernate-netshop.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;

    private NetshopSessionFactory() {
    }
	
	/**
     * 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;
    }
    
    /**
     * Returns the ThreadLocal Session instance.  Lazy initialize
     * the <code>SessionFactory</code> if needed.
     *
     *  @return Session
     *  @throws HibernateException
     */
    public static Session getNewSession() throws HibernateException {
        return sessionFactory.openSession();
    }

	/**
     *  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) {
		NetshopSessionFactory.configFile = configFile;
		sessionFactory = null;
	}

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


}




下面的操作时调用的方法


	public static void saveOrUpdateItem(Item item){
		Session session = NetshopSessionFactory.getSession();
		Transaction tx = session.beginTransaction();
		session.saveOrUpdate(item);
		session.flush();
		tx.commit();
		item = null;		
		session.close();
	}


	public static Item getItemByid(Integer id){		
		Session session = NetshopSessionFactory.getSession();
		session.clear();
		Item item = (Item)session.load("netshop.dolchn.hibernate.Item", id);
		//System.out.println(item.getItname());
		session.close();
		return item;
	}






与楼主的问题一样, 无论session.flush() 还是session.clear(); 脏读数据依然被读出来, 实在不知道这些数据到底缓存在哪里, 二级缓存也已经被关闭了, 我现在怀疑问题出在线程上.

    
0 请登录后投票
   发表时间:2007-04-19  
用户A想看到用户B更新过的数据,是必须在用户B更新后把session flunsh的。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics