-->
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.  [ 4 posts ] 
Author Message
 Post subject: Session caching and multithreads
PostPosted: Fri Oct 08, 2004 8:10 pm 
Newbie

Joined: Fri Oct 08, 2004 7:26 pm
Posts: 4
Location: Florianopolis - SC - Brazil
Hi all,

I am having a problem with the behavior of Hibernate's session cache management. I already know one or two solutions to my problem, but I am asking for you expert guys if there is another solution.

I have two threads and a Parent/child association and the child's parent is nullable and I am using ThreadLocal to store the session for each thread and I never close a session.

If I load the childs on one thread, deletes it's parent on another thread and then re-load the child again, it is with his parent still setted. I know that this is the natural behavior of the session cache that Hibernate provides

I know that if I close the session in every DAO "action" (throwing away the ThreadLocal solution), it would work, but I would also loose the session cache advantages.

Other solution that I thought was to load the parent, call session.evict on it and then load the parent again. But this sounds very bad to me.

Here is the code that can reproduce what I am saying:

Code:

import net.sf.hibernate.HibernateException;

public class StaleTest  {
   
   Deleter deleter;
   Checker checker;
   
   public class Deleter implements Runnable {
      private int parentId;
      
      public Deleter(int parentId) {
         this.parentId = parentId;
      }

      public void run() {
         //sleep till Checker's first check is done.
         try {
            Thread.sleep(3000);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
         
         ParentDAO parentDAO = new ParentDAO();
         try {
            System.out.println("Gonna delete parent "+parentId+"...");         
         
            parentDAO.delete(parentId);
         } catch (HibernateException e1) {
            e1.printStackTrace();
            return;
         }
         System.out.println("Deleted...");
         

      }
      
   }

   public class Checker implements Runnable {
      

      public void run() {
         Child child;
         ChildDAO childDAO = new ChildDAO();
         
         try {            
            child = childDAO.load(1);
         } catch (HibernateException e1) {            
            e1.printStackTrace();
            return;
         }
         System.out.println("Child's parent (before)= "+child.getParent());

         //sleeps till the parent has been deleted
         try {
            Thread.sleep(10000);
         } catch (InterruptedException e) {         
            e.printStackTrace();            
         }
      
         try {
            child = childDAO.load(1);
         } catch (HibernateException e2) {
            e2.printStackTrace();
            return;
         }
         System.out.println("Child's parent (after)= "+child.getParent());

      }
      
   }
   
   public StaleTest(int parentId) {
      this.deleter = new Deleter(parentId);
      this.checker = new Checker();

   
   }
   
   public void start() {
      System.out.println("Starting test!");
      new Thread(this.deleter).start();
      new Thread(this.checker).start();
   }
   
   public static void main(String args[]) throws HibernateException {
      System.setProperty("java.util.logging.config.file", "res/logging.properties");
      System.loadLibrary("_corelibsj");

      Parent parent;
      ParentDAO parentDAO = new ParentDAO();
      parent = (Parent)parentDAO.findAll().get(0);
      
      Child child;
      ChildDAO childDAO = new ChildDAO();

      child = childDAO.load(1);
      child.setParent(parent);
      childDAO.update(child);
      
      StaleTest st = new StaleTest(parent.getId());
      st.start();      
   }
   
   
}



Here is the output of this code:

Code:
Starting test!
Child's parent (before)= com.hoplon.core.data.Parent@1
Gonna delete parent 1...
Deleted...
Child's parent (after)= com.hoplon.core.data.Parent@1



And here is the output that I would like this code to have:

Code:
Starting test!
Child's parent (before)= com.hoplon.core.data.Parent@1
Gonna delete parent 1...
Deleted...
Child's parent (after)= null


Any help with this would be greatly appreciated!


Hibernate version:2.1.3

Mapping documents:
Parent.hbm:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >

<hibernate-mapping package="com.hoplon.core.data">
<class name="Parent" table="parent">
<id
column="parent_id"
name="Id"
type="int"
>
<generator class="vm" />
</id>

</class>
</hibernate-mapping>


Child.hbm
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >

<hibernate-mapping package="com.hoplon.core.data">
<class name="Child" table="child">
<id
column="child_id"
name="Id"
type="int"
>
<generator class="vm" />
</id>
<many-to-one
class="Parent"
name="Parent"
not-null="false"
>
<column name="parent_id" />
</many-to-one>
</class>
</hibernate-mapping>

Name and version of the database you are using:Oracle 10g

The generated SQL (show_sql=true):
Hibernate: select this.parent_id as parent_id0_ from parent this where 1=1
Hibernate: select child0_.child_id as child_id1_, child0_.parent_id as parent_id1_, parent1_.parent_id as parent_id0_ from child child0_ left outer join parent parent1_ on child0_.parent_id=parent1_.parent_id where child0_.child_id=?
Hibernate: update child set parent_id=? where child_id=?
Hibernate: select child0_.child_id as child_id1_, child0_.parent_id as parent_id1_, parent1_.parent_id as parent_id0_ from child child0_ left outer join parent parent1_ on child0_.parent_id=parent1_.parent_id where child0_.child_id=?
Hibernate: select parent0_.parent_id as parent_id0_ from parent parent0_ where parent0_.parent_id=?
Hibernate: delete from parent where parent_id=?


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 09, 2004 3:05 am 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
Quote:
I know that if I close the session in every DAO "action" (throwing away the ThreadLocal solution), it would work, but I would also loose the session cache advantages.


your mistake is only here, hibernate session = 1st level cache not the app cache, just plug a second level cache EHcache by default or jbosstreecache.

Once again hibernate session should have a short life, just to do a use case and will be closed

_________________
Anthony,
Get value thanks to your skills: http://www.redhat.com/certification


Top
 Profile  
 
 Post subject: Distributed cache
PostPosted: Mon Oct 11, 2004 1:39 pm 
Newbie

Joined: Fri Oct 08, 2004 7:26 pm
Posts: 4
Location: Florianopolis - SC - Brazil
Suppose we had the two threads on that example running on separate machines. Is there a distributed cache solution? How would EHcache behave in this case?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 11, 2004 4:58 pm 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
jbosstreecache or easier versionning

_________________
Anthony,
Get value thanks to your skills: http://www.redhat.com/certification


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 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.