-->
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.  [ 1 post ] 
Author Message
 Post subject: How to refresh efficiently a set of objects
PostPosted: Mon Oct 10, 2005 8:16 am 
Newbie

Joined: Mon Oct 10, 2005 6:10 am
Posts: 10
Hello everybody,

I'm wondering, how to refresh efficiently a set (or even better s subset) of objects which is already present in the first-level cache (session cache).

The example scenario is pretty simple: a fat-client presents a list of customers and a single refresh button. Whenever the user clicks "refresh" the list should be updated based on the most current database state.

Side conditions:
- One Hibernate Session should be used
- Each customer instance hold in memory should only get thrown away if it is deleted in the database; if the instance gets stale, it's attributes have to get updated

The problem:
Code:
private void retrieve_a() {
       Query q = session.createQuery("from Customer as cust");
   listA = q.list();
   tx.commit();
}

Every time this code is executed, listA might not contain a consistent view of the database state, as there might be stale objects:
t1: retrieve_a() --> listA {(id=1,name=frank,seq=2) )}
t2: -- some concurrent database user inserts a new tuple (id=2 ...)
t3: retrieve_a() --> listA {(id=1,name=frank,seq=2),(id=2,name=joe,seq=1)}
t4: -- some concurrent database user updates (id=1,name=bart,seq=3) and inserts (id=3,...)
t5: retrieve_a() --> listA {(id=1,name=frank,seq=2),...,(id=3,name=homer,seq=1)}

At t5 there is a stale object (cusomer:id=1) hold in memory.

This behaviour is well documented, as Hibernate uses its first-level cache.

There are of course some simple solutions:
a) get rid of all cached objects before querying the database (evicting them: session.evict(...) )
b) within one transaction boundary: first query the database, second refresh each object in the result-set (query.list) (as shown in retrieve_c() )

By using solution a) everytime a query is executed, all instances are thrown away and new ones are created. I really want to avoid this!

By using solution b) a potential performance problem might occur, as for each element of listA a "select from where" has to be performed, to check, if some changes occured. If there are lots of instances in listA ...

Question
My question is, how to efficiently refresh the first-level cache? Is there a way to 'mark' a whole set of objects to get refreshed in an efficient way?


Hibernate version:
3.0.5
Mapping documents:
Code:
<hibernate-mapping>
   <class name="Customer" table="customer">
   <id name="id" column="id"> <generator class="increment"/></id>
   <version name="sequence" column="sequence"/>
   <property name="name" column="name"/>
   </class>
</hibernate-mapping>

Code snippet:
Code:
class Cusomer {
  public int id;
  public int sequence;
  public String name;
}

class Test {
...
    private List listA;
   
...
private void init(){
   testA();
   refreshGui();
}

public void buttonCallBack(){
   testA();
   refreshGui();
}

private void testA(){
   //t0
   retrieve_a(); 
   //t1
}
private void retrieve_a() {
      Session session = HibernateUtil.currentSession();
      Transaction tx = session.beginTransaction();
      Query q = session.createQuery("from Customer as cust");
      listA = q.list();
      tx.commit();
}

private void retrieve_b(){
                Session session = HibernateUtil.currentSession();
      Transaction tx = session.beginTransaction();
      Query q = session.createQuery("from Customer as cust");
                q.setLockMode("cust",LockMode.READ);
      listA = q.list();
      tx.commit();
}

private void retrieve_c(){
                Session session = HibernateUtil.currentSession();
      Transaction tx = session.beginTransaction();
      Query q = session.createQuery("from Customer as cust");
      listA = q.list();
                //pseudocode begin --
                  for all objects in listA:
                      session.refresh( ... )
                //pseudocode end --
      tx.commit();
}
[/i]


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

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.