-->
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.  [ 10 posts ] 
Author Message
 Post subject: 10.4.2. Many sessions with automatic versioning
PostPosted: Thu Sep 01, 2005 3:58 pm 
Beginner
Beginner

Joined: Tue Nov 09, 2004 12:22 pm
Posts: 44
Quote:
Each interaction with the persistent store occurs in a new Session. However, the same persistent instances are reused for each interaction with the database. The application manipulates the state of detached instances originally loaded in another Session and then "reassociates" them using Session.update() or Session.saveOrUpdate().

Code:
// foo is an instance loaded by a previous Session
foo.setProperty("bar");
session = factory.openSession();
session.saveOrUpdate(foo);
session.flush();
session.connection().commit();
session.close();

Quote:
You may also call lock() instead of update() and use LockMode.READ (performing a version check, bypassing all caches) if you are sure that the object has not been modified.


This is a section of the manual reference of Hibernate.
Could you explain how a call to lock() can replace the update method?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 01, 2005 5:19 pm 
Beginner
Beginner

Joined: Wed Jul 13, 2005 2:18 pm
Posts: 44
Calling update() generates a SQL UPDATE statement. If you call lock(), you are effectively telling Hibernate you're sure the object has not changed, so Hibernate does not execute a SQL UPDATE.

_________________
- Matt


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 01, 2005 5:32 pm 
Beginner
Beginner

Joined: Tue Nov 09, 2004 12:22 pm
Posts: 44
matt_mcgill wrote:
Calling update() generates a SQL UPDATE statement. If you call lock(), you are effectively telling Hibernate you're sure the object has not changed, so Hibernate does not execute a SQL UPDATE.


Well, if I write the following code :
Code:
session.lock(myObject, LockMode.READ);
myObject.setObjectProperty(objectProperty);


myObject will be updated in the database which means it is equivalent to :
Quote:
myObject.setObjectProperty(objectProperty);
session.update(myObject);


This is the point I don't understand.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 01, 2005 5:56 pm 
Beginner
Beginner

Joined: Wed Jul 13, 2005 2:18 pm
Posts: 44
speedster wrote:
matt_mcgill wrote:
Calling update() generates a SQL UPDATE statement. If you call lock(), you are effectively telling Hibernate you're sure the object has not changed, so Hibernate does not execute a SQL UPDATE.


Well, if I write the following code :
Code:
session.lock(myObject, LockMode.READ);
myObject.setObjectProperty(objectProperty);


myObject will be updated in the database which means it is equivalent to :
Quote:
myObject.setObjectProperty(objectProperty);
session.update(myObject);


This is the point I don't understand.


That is correct. This isn't the situation where lock() would be useful, however. Consider the following case, in which the object myObject has a lazily initialized many-to-one association to some object myParent. During one session, some query loads myObject:
Code:
session = sessionFactory.openSession();
Query query = session.createQuery("from myObject o where o.id='foo'");
myObject = (MyObject)query.uniqueResult();
session.close();

myObject.myParent is proxied, and has not been initialized yet. Notice that the session has been closed, so myObject is detatched. Now suppose that later you'd like to load myParent, and you know that myObject has not changed:
Code:
session = sessionFactory.openSession();
session.lock(myObject, LockMode.READ);
parent = myObject.getMyParent();

myObject has been reassociated, but no UPDATE was performed. LockMode.READ will cause a version check to be performed, LockMode.NONE will not.

Is this any clearer?

_________________
- Matt


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 01, 2005 6:19 pm 
Beginner
Beginner

Joined: Tue Nov 09, 2004 12:22 pm
Posts: 44
Humm... Not completely.

I don't understand why a call to a setter after a call to the lock() method will perform an update.

Indeed, I had a problem that had thrown a NonUniqueObjectException because I had executed a query that retrieved an object "Match" and after that I was trying to update this object after performing a change on it by calling session.update().

To solve this problem I called the lock method with the LockMode.READ and erase the session.update() and surprisingly, the object "Match" was updated in the database which was exactly what I wanted but without calling the update() method.

Do you understand what I can't figure out?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 01, 2005 11:57 pm 
Beginner
Beginner

Joined: Wed Jul 13, 2005 2:18 pm
Posts: 44
speedster wrote:
Humm... Not completely.

I don't understand why a call to a setter after a call to the lock() method will perform an update.


This is one of the cool features of Hibernate - once an object is 'persistant,' any modifications you make to the state of that object will be propagated to the database automatically.

This is all in the manual, but in short, an object can be in three states as far as Hibernate is concerned: Transient, Persistant, or Detatched.

A Transient object is like a brand new object with no state stored in the database. It's a regular POJO:
Code:
SomeObject obj = new SomeObject("param1", 2);

That's a transient object - it isn't stored in a database.

A Persistant object, on the other hand, is an object which has been persisted to the database. A Persistant object (roughly) corresponds to a row in the database. For an object to be persistant, it must be 'associated' with a Hibernate Session object. The Session needs to know about your object for it to be 'persistant.' Any object that you retrieve from the database is associated with the Session you used to retrieve it.

The third type of object, a detatched object, is what you call a persistant object once the session it's associated with is closed.

Now, back to your post. Hibernate detects changes to persistant objects, and automatically generates UPDATE statements for those changes. Typically the UPDATE happens when you commit the transaction, but it could happen before that, or you could make it happen by flushing the Session. This is a pretty cool feature.

Consider the Javadoc comments for the update() and lock() methods:
Code:
lock():
Obtain the specified lock level upon the given object. This may be used to perform a version check (LockMode.READ), to upgrade to a pessimistic lock (LockMode.UPGRADE), or to simply reassociate a transient instance with a session (LockMode.NONE). This operation cascades to associated instances if the association is mapped with cascade="lock".

update():
Update the persistent instance with the identifier of the given detached instance. If there is a persistent instance with the same identifier, an exception is thrown. This operation cascades to associated instances if the association is mapped with cascade="save-update".


The comments are a bit confusing, I suppose. I think 'transient instance' in the comment for lock() should really be 'detatched instance,' as I've used the term in this post.

In the comment for update(), it seems as though 'persistant instance' is meant to mean 'state stored in the database,' while the reference to 'detatched instance' here is correct.

Now, back to the code in your original post:
Code:
// foo is an instance loaded by a previous Session
foo.setProperty("bar");
session = factory.openSession();
session.saveOrUpdate(foo);
session.flush();
session.connection().commit();
session.close();


Remember that Hibernate can detect changes to a persistant object, but not a detatched object. What you would want to do is make the detatched object foo persistant before you change its property:
Code:
session = factory.openSession();
tx = session.beginTransaction();
session.lock(foo, LockMode.NONE);  // make foo persistant, without generating an UPDATE statment
foo.setProperty("bar");  // Hibernate will now detect this change
tx.commitTransaction();  // this will result in the UPDATE
session.close();

_________________
- Matt


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 02, 2005 10:04 am 
Beginner
Beginner

Joined: Tue Nov 09, 2004 12:22 pm
Posts: 44
Thank you Matt by taking your time to post your messages.

This is one is really clear. Now I understood.

I already knew about the three different states of the objects but as you said so well, the javadoc comments are a bit confused because of certain terms and specially the transient word.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 02, 2005 11:18 am 
Beginner
Beginner

Joined: Wed Jul 13, 2005 2:18 pm
Posts: 44
It's always nice when things click into place =) Have fun with Hibernate! Oh, and please rate my post if it was helpful - I'm in active development on a project using Hibernate, and I'll probably need the credits when I get stuck ;)

_________________
- Matt


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 08, 2005 4:42 pm 
Beginner
Beginner

Joined: Wed Jul 14, 2004 11:51 am
Posts: 43
Hi,

I've read your posts and have read the whole chapter 12 of the hibernate 3 documentation but still am having a problem with "detached" instances.

I have a test case which does the following:

Code:
- Create instance of Product (v1)

- Open Session
- Fetch instance of Product in P1 (v1)
- Close Session

- Open Session
- Fetch instance of Product in P2 (v1)
- Close Session

- Create Item 1
- Add Item1 to detached object P1
- Open Session
- Save P1 (v2)
- Close Session

- Create Item 2
- Add Item2 to detached object P2
- Open Session
- Save P2
- Close Session


When I save an instance I use the saveOrUpdateMethod().

I put some v<x> versions next to the persistent methods of my algorithm (or as I understand them) that represent the versionning of the detached object done by hibernate's cache.

I was expecting to receive an exception from my saveOrUpdate of P2 because the detached object's version should now be obsolete (still using v1) and hibernate has now a v2.

I probably don't understand the detached objects and automatic versionning system or am not using it correctly.

Anybody can give me a clue?

Thanks,

Francois


Top
 Profile  
 
 Post subject:
PostPosted: Sun Oct 09, 2005 11:52 am 
Beginner
Beginner

Joined: Wed Jul 14, 2004 11:51 am
Posts: 43
Forget my last post... I just figured it out using the <timestamp> mapping in my class and using the optimistic-lock=verstion.


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