-->
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.  [ 47 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
 Post subject: Avoiding activation of huge lazy lists on add()
PostPosted: Sat Apr 03, 2004 11:50 am 
Newbie

Joined: Sat Apr 03, 2004 11:40 am
Posts: 17
Is it possible (in the most recent release of hibernate) to add() to a lazy list without loading the whole thing into memory?

I am trying to code for a situation in which the total length of the list could vastly exceed available memory. I know I can keep it out of memory for reading by using session.filter() but I need an equivalent usage for appending.


Top
 Profile  
 
 Post subject: Re: Avoiding activation of huge lazy lists on add()
PostPosted: Sat Apr 03, 2004 4:51 pm 
Proxool Developer
Proxool Developer

Joined: Tue Aug 26, 2003 10:42 am
Posts: 373
Location: Belgium
JulianMorrison wrote:
Is it possible (in the most recent release of hibernate) to add() to a lazy list without loading the whole thing into memory?

I am trying to code for a situation in which the total length of the list could vastly exceed available memory. I know I can keep it out of memory for reading by using session.filter() but I need an equivalent usage for appending.



I don't know about future Hibernate plans, but unfortunately this kind of behavior is not available yet...

May be you could define the list elements as lazy. This way they won't be instanciated/loaded when the collection is loaded - only proxies would be. This could make a big difference in memory consumption if your list elements are heavy. But would still require the instanciation of as many proxies as you have elemnts in your list :(


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 03, 2004 4:56 pm 
Beginner
Beginner

Joined: Fri Apr 02, 2004 3:34 am
Posts: 40
Que? You mean if I have a Organization with a List of Employee, I cannot add a new Employee without loading the entire Employee table?

So, all the one-to-many relationships are esenstially useless unless we are talking about a very small -many instanstances?

I guess the work-around is to add the Employee separately?


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 03, 2004 5:11 pm 
Proxool Developer
Proxool Developer

Joined: Tue Aug 26, 2003 10:42 am
Posts: 373
Location: Belgium
Acco Lade wrote:
Que? You mean if I have a Organization with a List of Employee, I cannot add a new Employee without loading the entire Employee table?


That's true. Hibernate will need to load the entire collection before adding the new element. Why so? Because it needs to enforce the Java collection semantic. Think about it...

- The collection is a set: duplicates must be avoided - so when adding a new element, Hibernate needs to know all the others (at least their ID).

- The collection is a map: keys need to be known for the map to be usable...

- The collection is a list: the indices must be known...

- The only collection that *may* not require to know anything in advance is the bag (and I'm not even sure about it) - but this is not a regular java collection type...

Acco Lade wrote:
So, all the one-to-many relationships are esenstially useless unless we are talking about a very small -many instanstances?


Useless? Why so? It will perform correctly in all cases - but with bad performance with very large collections - unless you know what you are doing and use the tool accordingly.


Acco Lade wrote:
I guess the work-around is to add the Employee separately?


The easiest workaround in this case is probably to define the list element as lazy. This way Hibernate won't load their actual content but just a proxy with their IDs... This is quite efficient, believe me ;)

Think about it... Loading the element IDs will be required anyway - whatever is your strategy to update the list, you will at least need this information...


Top
 Profile  
 
 Post subject: Workaround
PostPosted: Sat Apr 03, 2004 5:13 pm 
Newbie

Joined: Sat Apr 03, 2004 11:40 am
Posts: 17
A workaround I suppose is to emulate a list with a <class>

Code:
<class name="eg.FakeList" table="example_fake_list">
  ...
  <many-to-one name="owner" class="eg.ListOwner" not-null="true">
    <column name="owner" unique-key="unique_owner_and_index"/>
  </many-to-one>
  <property name="index" type="long" not-null="true">
    <column name="index_" unique-key="unique_owner_and_index"/>
  </property>
  <many-to-one name="item" class="eg.ListItem"/>
</class>


Top
 Profile  
 
 Post subject: Not necessary
PostPosted: Sat Apr 03, 2004 5:16 pm 
Newbie

Joined: Sat Apr 03, 2004 11:40 am
Posts: 17
It is concievable to append to a list without loading it. Lock the list, do a "select MAX(index) from list", add the row, unlock the list.


Top
 Profile  
 
 Post subject: Re: Workaround
PostPosted: Sat Apr 03, 2004 5:18 pm 
Proxool Developer
Proxool Developer

Joined: Tue Aug 26, 2003 10:42 am
Posts: 373
Location: Belgium
JulianMorrison wrote:
A workaround I suppose is to emulate a list with a <class>


Hmmm.. don't see the benefit (please light my bulb if I'm wrong)...

How will you map this class to the owner? Using a collection? Then you still have the same issue... (owner -* fakelist - item)


Top
 Profile  
 
 Post subject: Re: Not necessary
PostPosted: Sat Apr 03, 2004 5:23 pm 
Proxool Developer
Proxool Developer

Joined: Tue Aug 26, 2003 10:42 am
Posts: 373
Location: Belgium
JulianMorrison wrote:
It is concievable to append to a list without loading it. Lock the list, do a "select MAX(index) from list", add the row, unlock the list.


This is true - for the list only, and for one element only, and only if you add at the end of the list (append).

The approach taken by Hibernate so far works whatever you are doing with the list. Hibernate handles all collections the same way (in this regards) - that's why it is not always optimized for some scenarios - like the one you face.

Note that you can do the update as you propose yourself - but make sure the collection is not loaded in the current session or you may have some surprise at flush() time ;)


Top
 Profile  
 
 Post subject: Re: Workaround
PostPosted: Sat Apr 03, 2004 5:28 pm 
Newbie

Joined: Sat Apr 03, 2004 11:40 am
Posts: 17
brenuart wrote:
How will you map this class to the owner? Using a collection? Then you still have the same issue... (owner -* fakelist - item)

You do it the old SQL style way.

Code:
...
Long max = (Long) sesion.find("select max(index) from eg.FakeList where owner = ?", owner, Hibernate.entity(ListOwner.class)).get(0);
long next = 1L + max.longValue();
FakeList item = new FakeList();
item.setIndex(next);
item.setOwner(owner);
item.setValue(foo);
session.save(item);
...


Top
 Profile  
 
 Post subject: Re: Workaround
PostPosted: Sat Apr 03, 2004 5:32 pm 
Proxool Developer
Proxool Developer

Joined: Tue Aug 26, 2003 10:42 am
Posts: 373
Location: Belgium
JulianMorrison wrote:
brenuart wrote:
How will you map this class to the owner? Using a collection? Then you still have the same issue... (owner -* fakelist - item)

You do it the old SQL style way.


So you implement your own list management... But there is no explicit dependency between the owner and the list items anymore. So you can't rely on Hibernate cascades to remove orphans when the the owner is deleted, etc.

That's your choice. Sure it will work. But still believe the lazy list elements is a good approach - unless you have millions of items in your list and you update it very often...


Top
 Profile  
 
 Post subject: Re: Workaround
PostPosted: Sat Apr 03, 2004 5:33 pm 
Proxool Developer
Proxool Developer

Joined: Tue Aug 26, 2003 10:42 am
Posts: 373
Location: Belgium
JulianMorrison wrote:
Code:
...
Long max = (Long) sesion.find("select max(index) from eg.FakeList where owner = ?", owner, Hibernate.entity(ListOwner.class)).get(0);
long next = 1L + max.longValue();
FakeList item = new FakeList();
item.setIndex(next);
item.setOwner(owner);
item.setValue(foo);
session.save(item);
...


BTW, be carefull about race conditions...


Top
 Profile  
 
 Post subject: Re: Not necessary
PostPosted: Sat Apr 03, 2004 5:34 pm 
Newbie

Joined: Sat Apr 03, 2004 11:40 am
Posts: 17
brenuart wrote:
This is true - for the list only, and for one element only, and only if you add at the end of the list (append).

You could, I suppose, keep track of an "appended list": if nothing else but add() has touched the list, then you can keep an in-memory in-sequence list of items appended, and batch-append them at flush time (or batch-append at list-initialization time if something else touches the list).

Appending to huge lists is not a marginal case.


Top
 Profile  
 
 Post subject: Re: Workaround
PostPosted: Sat Apr 03, 2004 5:35 pm 
Newbie

Joined: Sat Apr 03, 2004 11:40 am
Posts: 17
brenuart wrote:
BTW, be carefull about race conditions...

Yeah, I saw that race. Just not sure how to lock a whole table in Hibernate.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 03, 2004 5:40 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Haven't read the full thread, but often you simply don't have to load the list, e.g. if its a unidirectional association. Then, adding a child (this is the "many" side) to a parent is just a matter of:

Child c = new Child();
Parent p = // load Parent or create a "fake" Parent with the same id
c.setParent(p);
session.save(c);

The Parent doesn't have a list of children in that case, so you don't have to load it.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject: Lazy list elements
PostPosted: Sat Apr 03, 2004 5:40 pm 
Newbie

Joined: Sat Apr 03, 2004 11:40 am
Posts: 17
So, I'll probably go with the lazy list elements for my case. How do I do this?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 47 posts ]  Go to page 1, 2, 3, 4  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.