问题描述:
   假设表A当中共有10条语句,使用hibernate自带delete方法或者save方法删除或者添加一条语句后,数据库表受到影响,数据条数分别为9条或者11条。但问题出现了。
   当我使用hql查询该表A的所有对象集合时,得到的list表前几次会正常显示A表修改后的数据内容,但多刷新几次,list的size就会不定时的变成10条,影响查询结果,致使得到的查询结果仍然是表A修改前的内容。
   这个问题没有固定性,有时候出现,有时候正常,而且出现问题时,查询的结果也是不稳定的,有时候正确有时候错误,但只要重起一下服务,就什么问题都没有了。
  
   以下是增删改代码:   public boolean remove(News n){
Session session=HibernateSessionFactory.getSession();
Transaction ts=null;
try{
ts=session.beginTransaction();
session.delete(n);
ts.commit();
session.clear();
return true;
}catch(HibernateException e){
if(ts!=null)
ts.rollback();
session.clear();
e.printStackTrace();
return false;
}finally{
if(session!=null)
session.close();
}
}//删除一条新闻;

public boolean saveOrUpdate(News n){
Session session=HibernateSessionFactory.getSession();
Transaction ts=null;
try{
ts=session.beginTransaction();
session.saveOrUpdate(n);
ts.commit();
session.clear();
return true;
}catch(HibernateException e){
if(ts!=null)
ts.rollback();
session.clear();
e.printStackTrace();
return false;
}finally{
if(session!=null)
session.close();
}
}//新增新闻或更新新闻内容;   以下是查询代码:    public List<News> findAllByCol(String colname){
Session session=HibernateSessionFactory.getSession();
session.clear();
Query q=session.createQuery("from News where colchildId='"+colname+"'order by plusDate desc");
List<News> l=null;
l=q.list();
session.clear();
HibernateSessionFactory.closeSession();
if(l!=null)
return l;
else
return null;
}//按照栏目名称查找新闻    映射文件:
  
    <hibernate-mapping>
    <class name="xhghj.object.News" table="news" catalog="xhgh">
        <id name="id" type="java.lang.String">
            <column name="id" length="32" />
            <generator class="uuid" />
        </id>
        <property name="colchildId" type="java.lang.String">
            <column name="colchild_id" length="32" not-null="true" />
        </property>
        <property name="newsname" type="java.lang.String">
            <column name="newsname" length="32" not-null="true" />
        </property>
        <property name="newscontent" type="java.lang.String">
            <column name="newscontent" length="65535" not-null="true" />
        </property>
        <property name="plusDate" type="java.lang.String">
            <column name="plus_date" length="32" />
        </property>
    </class>
</hibernate-mapping>   我查询了很多资料,大部分说是session没有清理干净的问题,但代码我改了又改,无论是clear清除session,flush强制刷新,close关闭session,HibernateSessionFactory.close()都不行,难道清除session用的都是其他方法?
   也有部分说是hibernate缓存的问题,但hibernate映射文件当中,缓存默认为false,我压根就没有设置,哪里来的缓存一说?
   最后找到一个比较靠谱的说法,是关于HibernateSessionFactory.getSession();的,我跟着那篇帖子用debug追进这个方法当中,发现hibernate是先判断线程,如果线程中有现成的session,就直接拿来,如果没有才会新建一个session放进当前操作的线程当中,但是,就算我直接将判断那里给session赋值为null,让它直接生成一个新的session来操作数据库,结果还是会出现问题。
   这个问题不解决,简直如鱼刺在哽,日夜难眠,还望论坛达人能够予以解释并给予一个解决方案。

解决方案 »

  1.   

    HibernateSessionFactory写得应该有问题,造成session线程不安全了,也就是产生了不同的session,一定要保证HibernateSessionFactory只有一个session实例存在package dao;
    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.cfg.Configuration;
    public class HibernateSessionFactory {    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() {    }    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;
        } 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; } public static void setConfigFile(String configFile) { HibernateSessionFactory.configFile = configFile; sessionFactory = null; }
    public static Configuration getConfiguration() { return configuration; }}
    另外session关闭的时候最好调用HibernateSessionFactory.closeSession()方法
      

  2.   

    Session session=HibernateSessionFactory.getSession();finally{
    if(session!=null)
    session.close();
    }补充一下,这样关闭session只关闭了你本地创建的Session变量session,HibernateSessionFactory中的session变量压根就没有关闭,所以HibernateSessionFactory中session越创建越多
      

  3.   

    这个HibernateSessionFactory是hibernate自动生成的 
    我用的开发环境是myeclipse 是在工具上直接导入的hibernate框架 以下是myeclipse自己生成的代码package xhghj.hibernate;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 =null; 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;
    }}
      

  4.   

    那应该就是session关闭的问题,你只关闭了本地变量
      

  5.   

    我先试试 之前确实忽略了 只在查询当中关闭的HibernateSessionFactory的session...
      

  6.   

    不行 问题依旧 hql查询的结果依然不稳定
      

  7.   

    public boolean saveOrUpdate(News n){
    Session session=HibernateSessionFactory.getSession();
    Transaction ts=null;
    try{
    ts=session.beginTransaction();
    session.saveOrUpdate(n);
    session.flush();
    //session.evict(n);
    ts.commit();
    session.clear();
    return true;
    }catch(HibernateException e){
    if(ts!=null)
    ts.rollback();
    session.clear();
    e.printStackTrace();
    return false;
    }finally{
    if(session!=null)
    session.close();
    }
    }//新增新闻或更新新闻内容;修改你的代码如上 ,建议好好看看hibernate的flush机制!
      

  8.   

    //session.evict(n);
    ts.commit();
    这两句分两行写,上面的格式有点问题,抱歉!
      

  9.   

    你的意思是在提交事务之前 刷新session?
      

  10.   

    你的这个类 直接继承hibernateSupport类就行了 里面有封装好的方法
    不用你去管理session 
      

  11.   

    与其说去继承,还不如直接让hibernate直接生成这个类呢 你这个说法等于白说
    我现在是要找到问题的根源所在 以防再犯
    我现在不明白的是 一模一样的代码 为什么唯独这次工程会出问题 
      

  12.   

    怀疑myeclipse自动生成的session factory类有问题。
      

  13.   

    你commit试试   或者你自己写sessionFactory不要用上面自带的!!
      

  14.   

    现在不都是spring自带生成SESSION机制来管理么 很少手动来生成了
      

  15.   

    Hibernate  总是有很多诡异的问题   你可以继承Hibernate的HibernateDaoSupport 直接用getHibernateTemplate.sava/update/delete就行了  就不会出那个问题 
      

  16.   

       一级缓存就是session,这个是肯定会开启的你根本没法不让他开启啊。xml里面配置的是二级缓存。我猜还是你的session一级缓存的问题。session.close会自动关闭session并且清空缓存。
      

  17.   

    嗯 对  就是这样  用起来hibernate就会方便很多