Results 1 to 10 of 10

Thread: Hibernate architecture problem with lazy collections

  1. #1

    Default Hibernate architecture problem with lazy collections

    Hi.

    Let's say I have User object containing Role collections. Mening I have :
    public class User {
    ...
    public Set getRoles() {
    ...

    }

    In my web tier I need to use this User instance, sometimes needing it's roles, and sometimes don't. Does it mean that I would have to create businness method with flag such as :
    public User getUser(Long id, boolean loadRoles)
    and depending upon this flag, to eagerly load roles or not?
    It somehow seems to go against common OO to change businnes interface due to persistnece under the hood. And BTW, Im terrified of OpenSessionInView pattern, thus dont want to apply that pattern.

    Solution?

    -Vjeran

  2. #2
    Join Date
    Dec 2004
    Location
    Bucuresti, Romania
    Posts
    72

    Default

    Or you could use OpenSessionInViewFilter

  3. #3
    Join Date
    Sep 2004
    Location
    Toulouse, France
    Posts
    50

    Default

    Vjeran, I agree, I've become allergic to OSIV in all its forms...

    I've usually implemented my getUser methods as you mentioned above, with a flag stating whether I should load all collections or not.

    The other option seems to be to have a service level object for each use-case. A transactional method in this object is responsible for loading the required domain object, and for touching only those collections required in that particular use-case.

    For view-only use-cases the second approach seems like overkill and I would go with the first one. For use-cases involving view and modify (especially complex modification/validation involving the child objects), I'm now tending towards the second option....

    Hope that helps.

    Best regards,

  4. #4

    Default

    Thanx Assaf.

    One more thing troubles me also... similar to when sometimes I need collection instances in my web tier, and sometimes don't, I stumble upon situations where difefrent web pages have to update persistent object differently - once I want to update just this object's property changes, and sometimes I just want to update it's collections objects (db links in fact), and both of times I have to use Session.update() which effects collection depending upon "cascade" configuration in hbm.xml. Thus, no way to specify in code - now I want collection effected, and now I don't.

    The only solution to this is to load complete object (Session.load) before updating (Session.udapte), thus having collections set in it always. Problem arise when having page with form that is used for updating object. Since there are only form fields for this object's properties, and not some "hidden" fileds about it's collection info, I cannot simply create new instance of this object, and call session.update() since that would erase all collection links (since collection reference is null).

  5. #5
    Join Date
    Sep 2004
    Location
    Toulouse, France
    Posts
    50

    Default

    Did you test this? I haven't yet come across a situation where spring binding actually causes Hibernate to delete the entire collection.
    Can you post the code where this is happening?

  6. #6

    Default

    well, code would be messy, but here is explained... If you have web page with form for updating some User object, you can place all property values in a form (ID is usually hidden field), thus when you submit, controller fetches all property values, populate newly created (new User()) empty instance with these values (let's say username, password for User instance), and updates it with Session.update(). But problem is that roles collection is null, since no value was available for populating it, and Hibernate thinks that it should delete all links with Session.update() since this collection has cascade="all" set in hbm.xml.

  7. #7
    Join Date
    Sep 2004
    Location
    Toulouse, France
    Posts
    50

    Default

    Oh, I think I get it.
    Why do you create a new (empty) object after the submit? That's where your problem is. You should be loading the existing object from the database using the ID, and then binding to this existing object.

    Best regards,

  8. #8

    Default

    In our app, we use a callback mechanism to allow the web tier to do lazy-loading of an object graph when it needs to. The method that performs the callback runs within a transaction/session. Although the web tier doesn't need to know that.

  9. #9
    Join Date
    Sep 2004
    Location
    Toulouse, France
    Posts
    50

    Default

    Quote Originally Posted by rhasselbaum
    In our app, we use a callback mechanism to allow the web tier to do lazy-loading of an object graph when it needs to. The method that performs the callback runs within a transaction/session. Although the web tier doesn't need to know that.
    This is fine within the View, if you're loading a fresh object first.
    But in the controller, if you're using Hibernate anyway, you can easily run into an error saying something like "attempt to reconnect an object with dirty collections" (I don't remember the exact wording).
    This is because before loading the collection, you have to reconnect the object to the current session using:
    Code:
     this.getHibernateTemplate().lock(entity, LockMode.NONE);
    If you lazy-load one collection first, modify the collection in any way, and then lazy-load another collection, you'll get the error.

  10. #10
    Join Date
    Oct 2004
    Location
    Antwerp, Belgium
    Posts
    96

    Default

    Why do you create a new (empty) object after the submit? That's where your problem is. You should be loading the existing object from the database using the ID, and then binding to this existing object.
    And if you are using optimistic locking you should store the object in the HTTP session before rendering the form page, get it from the HTTP session upon submit and attach to a session ASAP, update the object based on the values returned from the form and only then will you get a concurrent update exception.

    When you store the object in the HTTP session you should generate a unique id - for example a UUID, store the object in the HTTP session using that id and pass the id as a hidden value instead of the database identity of the object.

Similar Threads

  1. Replies: 5
    Last Post: Dec 27th, 2005, 07:00 AM
  2. Replies: 1
    Last Post: Jul 5th, 2005, 03:48 AM
  3. Spring, JSF, Hibernate & Lazy Collections
    By e.medina.m in forum Data
    Replies: 3
    Last Post: Mar 9th, 2005, 03:28 AM
  4. hibernate lazy collection initialization problem
    By bernardsirius in forum Data
    Replies: 2
    Last Post: Feb 16th, 2005, 08:07 AM
  5. Replies: 3
    Last Post: Nov 19th, 2004, 07:16 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •