-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: Stale object with session.find() after session.close()
PostPosted: Thu Feb 19, 2004 12:59 am 
Newbie

Joined: Wed Feb 11, 2004 9:58 pm
Posts: 3
Hello,I am using hibernate-2.1.2 with a web application,Tomcat 5 with JSP2.0 and Servlet 2.4.

My problem is that when I update a object(a User instance here) and close the session,Then find() will get the stale object. For example.I first list the Users.there is a User with name "UserA".then I update the User with name "UserB",I can list the users with name "UserB", and the Database is the correct "UserB".But,after a few minute,I refresh the list,and it get the stale old name "UserA".the strange things is that it becomes "UserB" after another few minutes. and will swap between "UserA" and "UserB".Is that strange?

The focus here I think is that I only close the session when update() and do NOT close the session when find(). because I thought find() does not modify the object's state,so I let the session live between requests.

Can I use the same session between find()?

====My Solve:
If I close the session for each request,It works correctly.I use a Filer to do it. see the last lines.

Thanks a lot.

====Note:some code omited by sign of //......
====User.java:
Code:
package  bean;
import java.util.*;
/**
* @hibernate.class table="user"
*/ public class User extends Persistent{
   private String name;
   private String passwd;
   private String sex;
   //......      
   /**
    * @hibernate.property length="60"
    */
   public String getName(){
      return name;
   }
   public void setName(String value){
      name=value;
   }
   //......
}


====MySessionFactory.java:
Code:
import net.sf.hibernate.cfg.Configuration;
import net.sf.hibernate.*;
import bean.*;
public class MySessionFactory {
   public static ThreadLocal thread =null;
   private static SessionFactory sessionFactory;
   private static ThreadLocal getThread(){
      if(thread==null){
         thread =new ThreadLocal(); }
         return thread;
      }
   public static Session currentSession() throws HibernateException {
      if (sessionFactory == null) init();
      Session s = (Session) getThread().get();
              if (s == null) {
         s = sessionFactory.openSession();
         getThread().set(s);
      }
      return s;
   }
   public static void closeSession() throws HibernateException {       
      Session s = (Session) getThread().get();
      getThread().set(null);
      if (s != null) {
         s.flush();
         s.close();
      }
   }
   private static void init() {
      Configuration conf = null;
      try {
         conf = new Configuration()
         .addClass(   User.class )
         //......
         ;
         sessionFactory = conf.buildSessionFactory();
      } catch (MappingException e) {
         e.printStackTrace();
      } catch (HibernateException e) {
         e.printStackTrace();
      }
   }
}


====DAO.java
Code:
import net.sf.hibernate.Session;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Transaction;
import net.sf.hibernate.type.Type;
import java.util.*;
public class DAO{
   public static DAO dao=new DAO();
   public List find(String query){
      List l=null;
      Session s;
      try{
         s= MySessionFactory.currentSession();
         l=s.find(query);
         s.flush();
         //NO session.close() here
      }catch(HibernateException he){
         System.out.println("DAO:find():Hibernate Error");
      }
      return l;
   }
   public Object update(Object o) throws HibernateException {       
      Session s = MySessionFactory.currentSession();
      Transaction tx = null;
      try{
         tx = s.beginTransaction();
         s.saveOrUpdate(o);
         tx.commit();
      }catch(HibernateException he){
         if ( tx!=null ){
            tx.rollback();
         }
         throw he;
      }finally{
         MySessionFactory.closeSession();// session.close() here,removed after
        I add the filter MyFilter.
      }
      return o;
   }
   public Object add(Object o) throws HibernateException {
      //Like update()
      //......
   }
   public void remove(Object o) throws HibernateException {
      //Like update()
      //......
   }
   //......
}


====The client JSP related code:
Code:
//......
public static List getUsers(){
   return dao.find("from User");
}      
public static String modUser(User u,String newName){
   u.setName(newName);
   //......
   try{
      dao.update(u);
   }catch(HibernateException e){
      e.printStackTrace();
      return "Hibernate Error";
   }
   return null;
}
//......


====My Solve:
I use a Filter in the webapps(configed in web.xml) to implement "session-per-request".
I also remove the MySessionFactory.closeSession() in DAO.java when update() and other calls.

It works OK for "session-per-request"

==== MyFilter.java
Code:
public class MyFilter implements Filter {
   public void init(FilterConfig filterConfig) throws ServletException {}
   public void destroy() {}
   public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws ServletException,IOException {
      fc.doFilter(req,res);
      // close a Hibernate session after each request
      try{
         MySessionFactory.closeSession();       
      }catch(HibernateException e){
         System.out.println("EncodingFilter:doFilter():HibernateException");
      }
   }
}


====Acticle looked:
http://www.hibernate.org/168.html


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 19, 2004 3:41 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Once you've got an object returned by Hibernate (find, load, etc), this object is linked to the session and any update will be persisted into DB.
If you want to play with detached objects either close the session that return them or evict() them.

_________________
Emmanuel


Top
 Profile  
 
 Post subject: Do not close session after find()
PostPosted: Thu Feb 19, 2004 5:28 am 
Newbie

Joined: Wed Feb 11, 2004 9:58 pm
Posts: 3
The situation is like this:

Code:
1.(request)--find() "UserA" ("UserA" in DB)
2.(request)--update()--closeSession() "UserA" to "UserB" ("UserB" in DB)
3.(request)--find() "UserB" ("UserB" in DB)
4.(request)--find() "UserA" or "UserB" ("UserB" in DB)
5.(request)--find() "UserA" or "UserB" ("UserB" in DB)


in 3,4,5 I only do the find() and do not do the update()
I think that 4,5 should return "UserB",that is what confused me.

Thanks very much.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 19, 2004 5:34 am 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
You are surely reusing an old session when you get old data not conforming to the DB. I think you should check your session handling again. For instance that lazy creation of the ThreadLocal seems really dangerous to me with multpile Threads, why dont you just create it once with static ThreadLocal thread = new ThreadLocal() ?


Top
 Profile  
 
 Post subject: Got the reason
PostPosted: Thu Feb 19, 2004 10:15 pm 
Newbie

Joined: Wed Feb 11, 2004 9:58 pm
Posts: 3
gloeglm wrote:
You are surely reusing an old session when you get old data not conforming to the DB. I think you should check your session handling again. For instance that lazy creation of the ThreadLocal seems really dangerous to me with multpile Threads, why dont you just create it once with static ThreadLocal thread = new ThreadLocal() ?


Yes.Today I debuged the program to print the session's hashCode and got the reason.The reason is many sessions exists even when I use the same Browser.

I used private static ThreadLocal thread = new ThreadLocal(); It works also,the thread is only one.

The problem is Session s = (Session) thread.get();will get different session with the same thread.Because I did not save the session between requests,two more sessions exists,sometimes this session,sometimes that session,then I got the values interweaved.

Code:
private static ThreadLocal thread =new ThreadLocal();
public static Session currentSession() throws HibernateException {
   if (sessionFactory == null) {
      init();
   }
   Session s = (Session) thread.get();//Will get differect sessions
   if (s == null) {
      s = sessionFactory.openSession();
      thread.set(s);
   }
   return s;
}


Thanks for all quickly replies and the Hibernate Team!


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.