Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Session level cache problem.
PostPosted: Tue Sep 23, 2003 12:51 am 
Newbie

Joined: Tue Sep 23, 2003 12:31 am
Posts: 3
I'm programming a web forum using Hibernate 2.0.3, and I've encountered a session level cache problem. See below mapping code:

Code:
        <class name="net.gleamynode.notes.driver.hibernate.PageImpl" table="PAGES">
                <id name="id" column="PAGE_ID" type="integer">
                        <generator class="identity"/>
                </id>
                <property name="timestamp" column="PAGE_TIMESTAMP" type="timestamp" not-null="true"/>
                <property name="title" column="PAGE_TITLE" type="string" not-null="true"/>
                <property name="content" column="PAGE_CONTENT" type="string" not-null="true"/>
                <set name="comments" order-by="COMMENT_TIMESTAMP">
                        <key column="PAGE_ID"/>
                        <one-to-many class="net.gleamynode.notes.driver.hibernate.CommentImpl"/>
                </set>
                <set name="attachments" order-by="ATTACHMENT_NAME">
                        <key column="PAGE_ID"/>
                        <one-to-many class="net.gleamynode.notes.driver.hibernate.AttachmentImpl"/>
                </set>
                <set name="keywords" table="PAGE_INDEX" sort="net.gleamynode.notes.driver.hibernate.KeywordValueComparator">
                        <key column="PAGE_ID"/>
                        <many-to-many column="KEYWORD_ID" class="net.gleamynode.notes.driver.hibernate.KeywordImpl"/>
                </set>
        </class>

        <class name="net.gleamynode.notes.driver.hibernate.CommentImpl" table="COMMENTS">
                <id name="id" column="COMMENT_ID" type="integer">
                        <generator class="identity"/>
                </id>
                <many-to-one name="page" column="PAGE_ID" not-null="true" class="net.gleamynode.notes.driver.hibernate.PageImpl" />
                <property name="timestamp" column="COMMENT_TIMESTAMP" type="timestamp" not-null="true"/>
                <property name="userName" column="COMMENT_USER" type="string" not-null="true"/>
                <property name="userEmail" column="COMMENT_EMAIL" type="string"/>
                <property name="userURL" column="COMMENT_URL" type="string"/>
                <property name="content" column="COMMENT_CONTENT" type="string" not-null="true"/>
        </class>


Here is the code I programmed to write a comment on a page(topic):

Code:
   public Comment newComment(Integer pageID, String userName, String userEmail, String userURL, String content) throws NotesException {
      CommentImpl comment = new CommentImpl();
      
      comment.setPage(getPage(pageID));
      comment.setUserName(userName);
      comment.setUserEmail(userEmail);
      comment.setUserURL(userURL);
      comment.setContent(content);
      
      try {
         comment.setId((Integer)session.save(comment));
         session.flush();
      }
      catch (HibernateException e) {
         throw new NotesException(e);
      }
      
      return comment;
   }

   public Page getPage(Integer id) throws NotesException {
      try {
         return (Page)session.load(PageImpl.class, id);
      }
      catch ( ObjectNotFoundException onfe ) {
         return null;
      }
      catch ( HibernateException he ) {
         throw new NotesException(he);
      }
   }


Here is what happens when a user calls newComment(...):

1. getPage(...) is called. The executed SQLs are:
Code:
Hibernate: select pageimpl0_.PAGE_ID as PAGE_ID, pageimpl0_.PAGE_TIMESTAMP as PAGE_TIM2_, pageimpl0_.PAGE_TITLE as PAGE_TITLE, pageimpl0_.PAGE_CONTENT as PAGE_CON4_ from PAGES pageimpl0_ where pageimpl0_.PAGE_ID=?
Hibernate: select comments0_.COMMENT_ID as COMMENT_ID__, comments0_.COMMENT_ID as COMMENT_ID, comments0_.PAGE_ID as PAGE_ID, comments0_.COMMENT_TIMESTAMP as COMMENT_3_, comments0_.COMMENT_USER as COMMENT_4_, comments0_.COMMENT_EMAIL as COMMENT_5_, comments0_.COMMENT_URL as COMMENT_6_, comments0_.COMMENT_CONTENT as COMMENT_7_ from COMMENTS comments0_ where comments0_.PAGE_ID=? order by comments0_.COMMENT_TIMESTAMP
Hibernate: select attachme0_.ATTACHMENT_ID as ATTACHME1___, attachme0_.ATTACHMENT_ID as ATTACHMENT_ID, attachme0_.PAGE_ID as PAGE_ID, attachme0_.ATTACHMENT_NAME as ATTACHME3_ from ATTACHMENTS attachme0_ where attachme0_.PAGE_ID=? order by attachme0_.ATTACHMENT_NAME
Hibernate: select page_ind0_.KEYWORD_ID as KEYWORD_ID__, keywordi1_.KEYWORD_ID as KEYWORD_ID0_, keywordi1_.KEYWORD_VALUE as KEYWORD_2_0_ from PAGE_INDEX page_ind0_ left outer join KEYWORDS keywordi1_ on page_ind0_.KEYWORD_ID=keywordi1_.KEYWORD_ID where page_ind0_.PAGE_ID=?


2. session.update() and flush() will insert a row:

Code:
Hibernate: insert into COMMENTS (PAGE_ID, COMMENT_TIMESTAMP, COMMENT_USER, COMMENT_EMAIL, COMMENT_URL, COMMENT_CONTENT) values (?, ?, ?, ?, ?, ?)


[PROBLEM 1] If the user calls getPage(...) to load the page again, the only SQL statement executed is the first one in step 1 above, so PageImpl.getComments() will return the list which does not contain the comment that has been inserted just before. I think session-level cache is not working correctly. Because a new row has been inserted, there should be at least one more query.

[PROBLEM 2] I cache SessionFactory instance and call sessionFactory.openSession() for each web page request, but I can't see any SQL queries are executed if there is no updates since the first query. Is it a normal behavior? I thought the result would not be cached because I open and close the session for every request. Is it a session factory level cache actually, or is the session instance is reused internally not clearing the cache?

_________________
what we call human nature in actually is human habit
--
http://gleamynode.net/


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 23, 2003 8:11 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1812
Location: Austin, TX
Quote:
[PROBLEM 1] If the user calls getPage(...) to load the page again, the only SQL statement executed is the first one in step 1 above, so PageImpl.getComments() will return the list which does not contain the comment that has been inserted just before. I think session-level cache is not working correctly. Because a new row has been inserted, there should be at least one more query.

Don't quite follow you here. If the user initiates getPage(...), wouldn't that constitute a new request and thus a new Session? Anyway there is a problem here in that the page instance you are working with still does not know about the comment you just added within the bunds of thats session in which it was created. Think of it like this:
Code:
Page page = new Page();
Comment comment = new Comment();
comment.setPage(page);
List pageComments = page.getComments(); // <- this will not "see" the new comment


Twos ways to correct:
1) set the comments collection on page to cascade and assign the new comment to the page instance and flush the session. Then the comment gets created through a cascade and the page instance in memory knows about the new comment
2) after inserting the comment, "evict" the page instance from the session cache. That way it would be completely rehydrated from the database on next access. You could also try the new session.refresh() method, but I've not played with that at all...

Quote:
[PROBLEM 2] I cache SessionFactory instance and call sessionFactory.openSession() for each web page request, but I can't see any SQL queries are executed if there is no updates since the first query. Is it a normal behavior? I thought the result would not be cached because I open and close the session for every request. Is it a session factory level cache actually, or is the session instance is reused internally not clearing the cache?

There are a couple of different layers at which you can cache in Hibernate. The default is to cache only at session level. However you can also choose to cache at different levels through configuration. It does not have a session factory level cache per-se. It can be configured to utilize a JVM-level cache.

No, session instances are not reused.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 23, 2003 10:15 am 
Newbie

Joined: Tue Sep 23, 2003 12:31 am
Posts: 3
Quote:
Don't quite follow you here. If the user initiates getPage(...), wouldn't that constitute a new request and thus a new Session?


The user inserts a new row (CommentImpl) and then call getPage(...) again, so newly returned PageImpl instance should contain the new comment which has been inserted just before. But Hibernate doesn't seem to query COMMENTS table again. This procedure happens in the same session.


[quorte]2) after inserting the comment, "evict" the page instance from the session cache. That way it would be completely rehydrated from the database on next access. You could also try the new session.refresh() method, but I've not played with that at all... [/quote]

How can I evict the page instance from the session cache? Is session.refresh() only way to do? Is there any way just to disable session cache?

_________________
what we call human nature in actually is human habit
--
http://gleamynode.net/


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 23, 2003 11:14 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1812
Location: Austin, TX
OK, so its the programmer, not the user...

Quote:
This procedure happens in the same session

I know, its because you do it the way you do and the fact that it all happens in the same session that you see this behavior. Again, if you follow either of the solutions I listed this will work...

session.evict() is the method you want to evict from the session cache

No session cache cannot be disabled


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 23, 2003 7:16 pm 
Newbie

Joined: Tue Sep 23, 2003 12:31 am
Posts: 3
Quote:
OK, so its the programmer, not the user...


I meant the word 'user' for 'web application'. Sorry for confusion. :)

Thanks very much! The problem resolved. Hibernate rocks! ;)

_________________
what we call human nature in actually is human habit
--
http://gleamynode.net/


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 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.