-->
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.  [ 22 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: What´s the semantic behind Session´s lock operation?
PostPosted: Mon Aug 08, 2005 2:04 pm 
Newbie

Joined: Wed Jun 29, 2005 4:51 pm
Posts: 10
Location: Brazil
What´s the semantic behind Session´s lock operation?

Should it be called 'reattach' and for historic reasons it is not?

What is considered the identity of an object for this method to throw a 'NonUniqueObjectException', is it the id (database id) of the object? or the java identity?

It sounds perfectly good to me the implementors decide to throw a exception when I try to lock the same object 2 times, but I´m really using this operation to re-attach a object whose session was already closed.

I´m not using the operations 'update' or 'merge' because I don´t want to persist this object but what I want is to use its lazy initalized properties. Should I really use the 'lock' operation in this case? The question that goes in my mind is "I´m not trying to lock this object to me, I just want it connected to my current session to keep using it´s lazy initalized properties transparently'

I´ve searched the forums, the reference manual and the unit tests but could get to no conclusion. Any help to clarify the semantics behind this operation will be most appreciated.

I´m using hibernate version 3.0.

Thanks in advance for your valuable time.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 08, 2005 2:07 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
http://www.hibernate.org/hib_docs/v3/ap ... e.LockMode)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 08, 2005 2:29 pm 
Newbie

Joined: Wed Jun 29, 2005 4:51 pm
Posts: 10
Location: Brazil
What I´m trying to understand is 'Do I need to worry if my object is comming from my current session or not when I use the lock operation?'.

I´ve made several unit tests that uses objects comming from dead sessions and some that come from the current session. All representing the same database record, they are all loaded from database with the same id.

When I first use session lock with an old object (its session was already closed) I can do whatever I want. That is:

-use the operation lock with a object whose session is alive;
-use the operation lock with another object whose session is dead;
-use the operaion lock several times with any object with the same id;
-update a re-attached old object and call update;

But when I first use the lock operation with one object that has just come from the session and I try to lock some object whose session is dead I get the 'NonUniqueObjectException' exception.

That´s the source of my confusion.

Thanks for the link but reading the javadoc description and source code of this operation couldn´t explain this behavior to me or to my co-workers.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 08, 2005 2:32 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
http://www.hibernate.org/116.html#A6


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 08, 2005 2:52 pm 
Newbie

Joined: Wed Jun 29, 2005 4:51 pm
Posts: 10
Location: Brazil
Thanks again for the link. But I´ve read already the FAQ and could find the item "I'm confused about the semantics of saveOrUpdate()" but not one related to the lock operation.

Maybe one topic on this operation on the FAQ could be useful to other hibernate newbies. One treating the "Re-attaching of objects to the current session to keep using hibernate´s lazy initialization behaviour"


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 08, 2005 3:01 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Ok, so my first link gave you enough information to understand that lock() with LockMode.NONE just does a reattach. My second link explained what problems you can experience if you reattach and how to avoid it. I've no idea what else you want to know.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 08, 2005 6:02 pm 
Newbie

Joined: Wed Jun 29, 2005 4:51 pm
Posts: 10
Location: Brazil
Neither of then explain the scenario I´ve presented in my second post. In other words trying to be more clear "What I must consider about the object I´m about to re-attach (session.lock(?, LockMode.NONE))?".

As I told in my 2d post, I found different behaviours dependending on the kind of object I reattached first: "When I first use session lock with an old object (whose session is dead)" and "when I first use the lock operation with one object that has just come from the session".

This is exactly what I trying to know and couldn´t find in any topic in the FAQ nor in the javadocs.

Sounds a important issue to be clarified in my mind before start coding with hibernate, since we are delaing with dettached objects all the time (could this be the problem?) in our web application. Start coding more I mean :)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 08, 2005 6:41 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Quote:
"When I first use session lock with an old object (whose session is dead)" and "when I first use the lock operation with one object that has just come from the session".


I don't understand this, because the terms you use mean nothing to me. We have to talk using the object states (transient, persistent, detached) as defined in the Hibernate reference documentation.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 08, 2005 9:36 pm 
Newbie

Joined: Wed Jun 29, 2005 4:51 pm
Posts: 10
Location: Brazil
Your are right, I should have used the object states vocabulary from the start.

I´ve made a simple class to illustrate the scenario of my second post:

Code:
package net.bpfurtado.sessionlocktest;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.hibernate.LockMode;
import org.hibernate.Session;

public class Main
{
    private static SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");

    public static void main(String[] args)
    {
        lockFirstDetachedThenPersistent();
        lockFirstPersistentThenDetached(); //Here I get the 'NonUniqueObjectException' exception
    }

    private static void lockFirstDetachedThenPersistent()
    {
        Book detached = createDetached();

        HibernateUtil.beginTransaction();
        Book persistent = (Book) HibernateUtil.getSession().load(Book.class, detached.getId());

        HibernateUtil.getSession().lock(detached, LockMode.NONE);
        HibernateUtil.getSession().lock(persistent, LockMode.NONE); //Here I don´t get the error and I can do anything I want with the detached or transient instance.

        detached.setTitle("Detached updated " + sdf.format(new Date()));

        HibernateUtil.commitTransaction();
        HibernateUtil.closeSession();
    }

    private static void lockFirstPersistentThenDetached()
    {
        Book detached = createDetached();

        HibernateUtil.beginTransaction();
        Book persistent = (Book) HibernateUtil.getSession().load(Book.class, detached.getId());

        HibernateUtil.getSession().lock(persistent, LockMode.NONE);
        HibernateUtil.getSession().lock(detached, LockMode.NONE); //Here I get the 'NonUniqueObjectException' exception

        detached.setTitle("Detached updated " + sdf.format(new Date()));

        HibernateUtil.commitTransaction();
        HibernateUtil.closeSession();
    }

    private static Book createDetached()
    {
        Book detached = new Book();
        detached.setTitle("Detached " + sdf.format(new Date()));

        HibernateUtil.beginTransaction();

        Session session = HibernateUtil.getSession();
        session.save(detached);

        HibernateUtil.commitTransaction();
        HibernateUtil.closeSession();
        return detached;
    }
}


The 'NonUniqueObjectException' exception occurs at the invocation of the second statement of main method. Better saying at the 'lockFirstPersistentThenDetached' operation.

A simple eclipse project with this example can be found here http://www.bpfurtado.net/files/sessionlocktest.
The .java files are in the same location if you don´t want to download the project.

Thanks in advance.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 09, 2005 3:40 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Yeah, that's exactly the problem described in the FAQ I pasted, with two possible solutions. What you do makes no sense.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 09, 2005 11:37 pm 
Newbie

Joined: Wed Jun 29, 2005 4:51 pm
Posts: 10
Location: Brazil
The motivation behind my question is the following scene in my web application:

-A request is received;
-the authenticated user is obtained from the session;
-we try to use the user and it´s lazy properties/collections (at this time the authenticated user is a detached object);
-Hibernate throws an exception with the message that session (for that object) is closed;

I assumed that I must reattach the user object, so:

-A request is received;
-the authenticated user is obtained from the session;
-I use session.lock(authenticatedUser, LockMode.NONE);
-And sometimes I get the exception 'NonUniqueObjectException', that´s probably because a object that represents the authenticated user was already loaded in the collection of another business object involved in the same transaction. Better saying, that user must have been already loaded in the process of resolving some relationship of other buss. objs. Sometimes this is not the case, and the error is not raised at all.

What I want to know from the experts is "Should I catch 'NonUniqueObjectException' the exception and obtain the persistent object from the session or am I missing something?".

Another secondary question would be "Is session.lock the only and right way to simply reatach my objects?". What by the answers received I´m assuming it is.

Basically I want to know from the designers and implementors of the API the way they expect we to use the operations/exceptions
, in this case how should we hibernate users use session.lock operation and it´s possible raised exception 'NonUniqueObjectException'.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 09, 2005 11:48 pm 
Newbie

Joined: Wed Jun 29, 2005 4:51 pm
Posts: 10
Location: Brazil
Talking to my friends and co-workers I´ve read again the item "11.6. Modifying detached objects" of the Reference Manual, which says:
Quote:
Use update() if you are sure that the session does not contain an already persistent instance with the same identifier, and merge() if you want to merge your modifications at any time without consideration of the state of the session.


That precisely answers my question. In my case I´m inclined to use the merge operation instead of lock.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 10, 2005 7:03 am 
Newbie

Joined: Fri Jul 02, 2004 7:23 am
Posts: 1
Why don't you just use session.load(detachedObject) ?

In the Web-Application we build we had the same problems in the beginning. Currently we are using a data-structure where every object is registrated and re-loaded once per request (and then tagged), since we deal with the more or less request-less jsf framework.

In your case, i would just get the identifier of your deattached Object and pass it to load to get a "fresh" and persisted instance.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 12, 2005 5:07 pm 
Newbie

Joined: Wed Jun 29, 2005 4:51 pm
Posts: 10
Location: Brazil
It is not my intention to stop using my HttpSession to store my object instances.

Thanks for trying to help :)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 06, 2006 2:40 pm 
Newbie

Joined: Tue Sep 16, 2003 3:26 pm
Posts: 8
Maybe this is late but it could work for you. Since there's usually no help from the Hibernate team I guess we should actually solve the common cases. Here it goes the workaround (for Hibernate 3.1, though it might work for 3.0):

Code:
    private Serializable getObjectId(Object obj) {
        ClassMetadata md = factory.getClassMetadata(obj.getClass());
        Serializable id = md.getIdentifier(obj, EntityMode.POJO);
        return id;
    }

    public void attach(Object obj) {
        Session session = factory.getCurrentSession();
        Serializable id = getObjectId(obj);
        if(id != null) {
            if(!session.contains(obj)) {
                // We need a cache to sustain the performance hit.
                Object oldObj = session.get(obj.getClass(), id);
                if(oldObj != null) {
                    session.evict(oldObj);
                }
            }

            // Reattach and version-check.
            session.lock(obj, LockMode.READ);
        }
    }


Note that I'm using "session.get" as an ad-hoc test to see if there's an object of the same id loaded in the session. Then I make sure that the object is evicted, avoiding Hibernate's lack of a good contains() method.

Hope it helps somebody. The solution is not optimal in that Hibernate should provide a session.containsForId() method that makes the test easier. But I'm tired of submitting RFEs that get ignored.

Have fun and don't forget to post any problems this approach could have!


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 22 posts ]  Go to page 1, 2  Next

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.