-->
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.  [ 12 posts ] 
Author Message
 Post subject: LazyInitializationException accessing identifier of proxy
PostPosted: Thu Sep 28, 2006 9:28 am 
Newbie

Joined: Thu Sep 28, 2006 8:50 am
Posts: 4
Hibernate version: 3.1.3

I have a class "A" with a simple Integer property as identifier.
It has a joined-subclass "B", which has a many-to-one self-reference, called "previousB".

The application has 3 tiers (in separate VMs), and the middle tier accesses the Hibernate domain model serialized from the backend tier.

Code:
b.getId()
b.getAnySimpleProperty()
goes fine.
Code:
b.getPreviousB().getId()
throws a LazyInitializationException.

I know the "previousB" is not initialized, and hence represented by a generated proxy class. But I also read in "Hibernate in Action" (p.150, Initializing lazy associations) that:

Quote:
A proxy or collection wrapper is automatically initialized when any of its methods are invoked (except the identifier property getter, which may return the identifier value without fetching the underlying persistent object). However, it's only possible to initialize a proxy or collection wrapper if it's currently associated with an open Session. If you close the session and try to access an uninitialized proxy or collection, Hibernate throws a runtime exception.


Here is my stacktrace:
Code:
   org.hibernate.LazyInitializationException: could not initialize proxy - no Session
   at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:53)
   at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:98)
   at org.hibernate.proxy.CGLIBLazyInitializer.intercept(CGLIBLazyInitializer.java:158)
   at my.package.B$$EnhancerByCGLIB$$d43b234e.getId(<generated>)
   ... (my code calling b.getPreviousB().getId() )


Given the quote from "Hibernate in Action" I would have thought that "previousB" did not need to be initialized when the middle tier only needs to access the identifier property!

Can anyone confirm this? And perhaps give hints why I am not succesful...

Or I am totally wrong - nothing can be accessed once the session is gone? (although accessing it within the session would not necessarily perform actual initialization of my class)


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 28, 2006 9:59 am 
Regular
Regular

Joined: Tue Sep 26, 2006 11:37 am
Posts: 115
Location: Sacramento, CA
In my experience you cannot access a lazy property after the session is gone. In my code I take 2 approaches:

1. if I know the property will be used on the remote side then I access it on the hibernate side before the remoting
2. I set to null properties that are not to be used on the web side

Sometimes in the remoting scenario you have to write your own find/retrieve API based on the usage. Most of the time it amounts to traversing the 'right' level of the object hierarchy.

Deciding where to draw the separation line and add the remoting layer is a difficult decision. Lots of people argue against a remoting approach unless absolutely necessary.

Good luck!

Marius


Top
 Profile  
 
 Post subject: Only the identifier property!
PostPosted: Fri Sep 29, 2006 2:08 am 
Newbie

Joined: Thu Sep 28, 2006 8:50 am
Posts: 4
I am aware that a lazy property in general can not be accessed outside the session unless initialized.

But my case is not the "general" case. I only need to access the identifier property. And this must be present in the uninitialized proxy object. Otherwise it would not be able to proceed with initialization, if it were inside a valid session. And it makes sense: the identifier property is read from the same record as the simple properties of my referring object.

In my mind it would be logical if it was possible to access the identifier property of an uninitialized proxy.

In my company this situation will apply a huge number of times. And if it is not possible, we must retrieve and communicate a lot of extra data just to throw away afterwards. In these cases we *really* just need the identifier.

If it is not possible today it would be a really nice future feature in Hibernate!


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 29, 2006 12:09 pm 
Regular
Regular

Joined: Tue Sep 26, 2006 11:37 am
Posts: 115
Location: Sacramento, CA
Sorry, got it now. I agree it would be nice to get to that ID, I struggle with the same problem.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 10, 2006 3:40 am 
Beginner
Beginner

Joined: Tue Oct 10, 2006 3:23 am
Posts: 33
Hi,
Actually I'm having the same problem:
With a simple Entity such as:
Code:
@Entity
@Table(name="ITEM")
public class Item {

   @Id
   @Column(name="ID")
   Long id;
   @Column(name="ITEM_NAME")
   String itemName;
   @ManyToOne(fetch=FetchType.LAZY)
   @JoinColumn(name="ITEM_TYPE_ID",unique=true)
   ItemType itemType;
...
@Entity
@Table(name = "ITEM_TYPE")
public class ItemType implements Serializable{
   @Id
   @Column(name = "ID")
   private Integer id;
   
   @Column(name = "TYPE_NAME")
   private String typeName;
   public ItemType(){}


And doing:
Code:
Session s=sessionFactory.openSession();
Item tp=(Item)s.get(Item.class,new Long(1));
s.close();
System.out.println(tp.getItemType().getId());

First issues select item0_.ID as ID0_0_, item0_.ITEM_NAME as ITEM2_0_0_, item0_.ITEM_TYPE_ID as ITEM3_0_0_ from ITEM item0_ where item0_.ID=?
so far so good but then causes a LazyInitializationException.

According to the FAQ I was under the impression that this should work.
I'm using 3.2.0.CR5 core and 3.2.0.CR3 annotations.

Thanks in advance


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 10, 2006 4:44 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Guys, if you map your entitiy with field access, Hibernate doesn't know that getId() exists. It's treated like any fooBar() method on your proxy, the proxy is initalized if you call it.

If you use property method access, Hibernate knows that it exists and that the proxy doesn't need to be initialized if you call getId().


Top
 Profile  
 
 Post subject: Thanks!
PostPosted: Tue Oct 10, 2006 7:43 am 
Newbie

Joined: Thu Sep 28, 2006 8:50 am
Posts: 4
When the access="..." is not specified in the mapping document the default is "property" access.

But when using annotations on the field (not on the method), the default appears to be that access="field" winds up in the mapping document!

I haven't tried yet, but I'll bet inserting explicit access="property" solves my problem. Or maybe moving the annotations to the method instead.

Thanks a lot for your help!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 10, 2006 8:35 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
when you use annotations there is no need for mapping files so why are you referring to them ?

put the annotation on a method and you get what corresponds to access="property"

put the annotation on field and you get what corresponds to access="field"

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 10, 2006 9:53 am 
Regular
Regular

Joined: Tue Sep 26, 2006 11:37 am
Posts: 115
Location: Sacramento, CA
Nice :) Thanks Max!

Marius


Top
 Profile  
 
 Post subject: Xdoclet
PostPosted: Tue Oct 10, 2006 11:15 am 
Newbie

Joined: Thu Sep 28, 2006 8:50 am
Posts: 4
In my case I am referring to xdoclet annotations, so I guess I really do need the mapping files. Yeah, sadly I am stuck on J2SE 1.4 for a while to come.

And I also find it a little confusing to have the annotations on the methods: Are they needed on both getter and setter? And you must scroll through more code to get the overview of the mapping. I find find it logical to specify the mapping where the fields are defined. A matter of taste, I guess.

I presume the mapping will be fine when I include access="property" as part of the (xdoclet) annotation on the fields.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 10, 2006 11:49 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Quote:
And I also find it a little confusing to have the annotations on the methods: Are they needed on both getter and setter? And you must scroll through more code to get the overview of the mapping. I find find it logical to specify the mapping where the fields are defined. A matter of taste, I guess.


It's not a matter of taste, it's matter of what you do and what you want. You can put your annotations on whatever you want, you don't need to duplicate them, and you can configure field or property access also through a global setting in the class (with an extra annotation) if you don't like the implicit default (@Id on field = field access).


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 10, 2006 1:34 pm 
Beginner
Beginner

Joined: Tue Oct 10, 2006 3:23 am
Posts: 33
Hi,
That did it, adding @AccessType("property") on the @Id annotation solved the problem. Thanks a lot Christian!!!

Personnally I like to annotate the fields as the Getter and setter are mostly autogenerated and if I need to rename a field it is way easier to delete the getter and setter and regenerate.

Thanks again for the help!!!


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