-->
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.  [ 18 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Column-level lazy fetching
PostPosted: Sat Sep 04, 2004 11:28 am 
Beginner
Beginner

Joined: Wed Mar 10, 2004 9:51 am
Posts: 42
Location: France
From the release notes ...
snip=
This is a checkbox feature that Hibernate needs for marketing purposes. Any property may be marked lazy="true", and will be fetched from the database when the field is first accessed.
This feature requires build-time bytecode instrumentation using an Ant task.
If Hibernate encounters uninstrumented classes at runtime, the feature will be transparently disabled.
=snip

Is there no way that this can be done without bytecode modification ?

I can think of about 3 areas in my application that would benefit from
this kind of performance enhancement but I work on an open source
project and the developers have very different skill levels, generally
the less ANT tasks you have in a project the better it is for all concerned.

Anyhow even if you aren't going to implement it using CGLIB or
runtime stuff I still think it is an extremely usefull feature and I would
be hard pressed to dismiss it as a "checkbox feature".

I would call it a very usefull enhancement.

Bryan

_________________
Pesimist: The glass is half empty
Optimist: The glass is half full
Engineer:The glass should be half that size


Top
 Profile  
 
 Post subject:
PostPosted: Sat Sep 04, 2004 11:32 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
I'd like to see good use cases for it, so far we haven't seen much. If you have some... I fear it won't work without bytecode instrumentation. Be happy that Hibernate doesn't need it for all other features. ;)

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


Top
 Profile  
 
 Post subject:
PostPosted: Sat Sep 04, 2004 11:59 am 
Beginner
Beginner

Joined: Wed Mar 10, 2004 9:51 am
Posts: 42
Location: France
christian wrote:
I'd like to see good use cases for it, so far we haven't seen much. If you have some... I fear it won't work without bytecode instrumentation. Be happy that Hibernate doesn't need it for all other features. ;)


For sure, don't get me wrong. Even as it is I think it is a very usefull
feature.

I am very glad that Hibernate doesn't need it ( bytecode enhancement )
for all it's features.

---------------------------------------------------------------------------------

I can give you a popular use case though for this field level lazy loading
feature.

( all my use cases are on the same theme ( real estate ))

An object which represents a house ( lets call it Property )
holds a collection for it's associated images

(pictures of the front , back, living room etc etc )

You could store this wrapped in an object

lets call it PropertyImage

PropertyImage has the following fields

id Integer
description String
imageData binary [] ( this could be up to 50k in size )

Now it might be desirable to grap the Property object ,
call it's getPropertyImages method which returns the
Set of PropertyImages and then itterate through it.

However the user might not want to look at all the
images, he/she might only look at the descriptions
and then select the particular one that they are
interested in.

So if there are 10 images @ 50k each that is 500k
just for the images.

That is a lot of data to pull into memory.

Obviously if the imageData field was lazy then your
graph would drop dramatically in size.

I have to say that I was delighted when you announced
this feature. I think it is going to be a lot more popular
than you seem to expect.

--b

_________________
Pesimist: The glass is half empty
Optimist: The glass is half full
Engineer:The glass should be half that size


Top
 Profile  
 
 Post subject:
PostPosted: Sat Sep 04, 2004 12:24 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Thats what LOB's are for, as the name "locator object" implies. You get them as text and binary types and they are by definition lazily loaded when first accessed.

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


Top
 Profile  
 
 Post subject:
PostPosted: Sat Sep 04, 2004 1:02 pm 
Beginner
Beginner

Joined: Wed Mar 10, 2004 9:51 am
Posts: 42
Location: France
christian wrote:
Thats what LOB's are for, as the name "locator object" implies. You get them as text and binary types and they are by definition lazily loaded when first accessed.


I'm not sure I understand exactly what you mean.

Are you suggesting the use of a lazy init many-to-one to
hold the object which contains the actual data

or

are you refering to an object that will just hold a id
which can be transformed into a url to fetch the image data ?

If it is the latter the relationship still needs to be both
ways , ie a Property will still need contain a set of images
and an image will still need to hold a reference to the Property.

Anyway one way or another I'm glad you have added this
feature to hibernate.

If it turns out that I need it I can just do the enhancement
for my production build.

--b

_________________
Pesimist: The glass is half empty
Optimist: The glass is half full
Engineer:The glass should be half that size


Top
 Profile  
 
 Post subject:
PostPosted: Sat Sep 04, 2004 2:04 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
The image type is not byte[], but Blob. This is a special JDBC type and used to lazily load huge objects inside a transaction. There are some ways to wrap this in your own type and hide persistence with a Hibernate UserType. LOBs are difficult to handle with Oracle (only with Oracle Drivers) but work OK on most other combinations of databases and drivers.

Writing more about LOBs with/without Hibernate is already on my TODO...

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


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 05, 2004 12:43 pm 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
I hope it is possible to implement lazy properties with proxy too. The same is about lazy entities, I see no major difference. I see no "transparence" in field interception, reflection will ignore it, so this is incomplete anyway. As I understand, it can be solved completely at JVM level only.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 05, 2004 6:15 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Its not possible to proxy some things. For example, you can't proxy String, or Integer. It is possible to proxy Blob or Clob, and I guess I would accept a patch that did that...


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 06, 2004 1:06 am 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
Ok, I will explain it by example.

asume we have class

Code:
class MyBean {

  String prop;

   String getProp(){

         return prop;

   }


}


Transformation does very trivial thing:

Code:
class MyBean implements FieldInterceptEnabled {

  FieldInterceptor callback;

  void setInterceptor(FieldInterceptor callback){
      this.callback = callback;
  }

   String cglib$readProp(){
 
      return callback.readField(this,"prop",prop);

   }

  String prop;

   String getProp(){

         return cglib$readProp();

   }


}


It can not intercept String and it doe's not intercepts property objects, it intercepts get/put field instructions (replaces with method call).

proxy can do almost the same:


Code:
class MyBeanProxy extends MyBean {

static {
  //generated stuff
}

   String getProp(){

         return methodInterceptor(this,METHOD,null);

   }


}


It intercepts method call, but you know about property read in this method and can load it (set with reflection).

You do not need and can not intercept String itself in both cases. I think I can implement it on some weekend without problems (translate existing code to proxy)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 06, 2004 3:15 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Yeah, sure, if you don't access the instvar directly, it can be done like that.

(By the way, I screwed up in my last post: there is no point proxying Blob or Clob, since they are lazy by nature. I meant to also say that you can't proxy arrays either.)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 06, 2004 3:42 am 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
It is possible to replace array access/allocation instructions with methods and to intercept methods without value class transformation (field interception doe's the same, it can not transform system classes), but it is not usefull for persistence. I think it antipattern to read/write fields directly if you declare "virtual" method to access it anyway (It declared for reason). Naming problem is very trivial too, you can declare "read/write" method names in mapping.

<property name="prop" write="setProp" read="getProp" />

I am sure it can not cause any problems in practice.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 06, 2004 4:45 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Trouble is that we can't serialize the object then, which makes it pretty useless...


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 06, 2004 5:48 am 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
As I understand serialization is a problem in both cases, I think it doe's not reduces problem if you do not strip proxies, you need to strip collections anyway (you can not transform standard collection implementation or to register callback, it needs persistent wrapper).
Serialization itself is an antipattern, it breaks data, makes dependant on programming langage, I found it is useless for data marshaling and storage, probably somebody can find use case for serialization like replicated transparent object caches, but I am sure we (JAVA developers) will forget this kind of workarounds.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 06, 2004 6:00 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Current Hibernate solution fully supports serialization:

* for unfetched associations, serialize proxy using writeReplace/readResolve (ok, since circular references are impossible)
* for fetched associations, strip out proxy
* for lazy properties, use buildtime enhancement, which enables serialization

So you see, there is a reason for the particular combination of choices here :-)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 06, 2004 6:39 am 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
You can use the same way as for entity to strip proxy too. If you have proxy for entity you can make any propery lazy, but lazy property will imply proxy for entity (I see this as single negative aspect). Lazy property doe's not change current things, this was my main point.


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