-->
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.  [ 5 posts ] 
Author Message
 Post subject: A Problem with Hibernate Lazy Loading and Caching
PostPosted: Thu Mar 12, 2009 12:59 pm 
Newbie

Joined: Wed Oct 01, 2008 8:42 pm
Posts: 12
I've found an interesting case where Lazy Loading is causing a property to be set to null where it really shouldn't be. I've found an "acceptable" solution, but I'm wondering if theres a better way around what Im doing.

Heres the case:

I'm using Struts/Spring/hibernate, so this is a web-app.

I have a Quote, which has an object property of type User.
I also have an Order, which also has a User property.
I have a user name stored in the session.

If I run the following:

Code:
Quote quote = quoteService.findByID(quoteId);
User user = userDao.findById(getLoggedInUserId);
order.setUser(user);


I get an SQL error saying that I cannot insert null into the order tables user column.

However, if I just change the order of the statements like so:

Code:
User user = userDao.findById(getLoggedInUserId);
Quote quote = quoteService.findByID(quoteId);
order.setUser(user);


everything works fine.

After some debugging, I figured out that in the first case, the userDao.findById method was returning a user object with all of it's properties set to null, but in the second, everything was filled in. Why does this happen? The quote that I happened to be looking at was for the logged in user, and quote fetches the user through lazy loading. So, when I get to the userDao.findById, it just hits the cached, proxy object and returns it. However, when I then try and set that proxied object as the property of another object, it still has all of it's null values when I get to the insert.

I have to figure that this is a somewhat typical use case, so my question is, is there a way to have hibernate load those properties when it comes time to insert? Or is there a better way to be doing something like this altogether?

Thanks,
Tim


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 12, 2009 2:49 pm 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
This seems very weird indeed. Hibernate shouldn't care if it is a proxy or a fully initialized user that is associated with your order object. The properties of an entity shouldn't be of any importance when associating your order with the user. Only the user's id and that should be present in the proxy. I really don't know why this happens based on the information you have given so far. Maybe you can post some more information?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 12, 2009 4:02 pm 
Newbie

Joined: Wed Oct 01, 2008 8:42 pm
Posts: 12
Well it seems that you've at least helped me identify the problem.

I'm dealing with a legacy database here, so any criticisms of bad design are already taken into account.

That said, the problem here is that our user table really has 2 "primary keys". We have one column, a numeric user id which is the real primary key, and another, a string login which has a unique constraint.

In my user hibernate mapping, I have the @Id set to the user Id.

In the quote table, the user id is correctly mapped through this key (the numeric user id). However, the order table is mapped through the user login, and I have it annotated as such:

Code:
public class Order {
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="USER_LOGIN", referencedColumnName="USER_LOGIN")
private User user;

}


So this actually makes perfect sense. The ID is stored, but the object that is referencing it is mapped to a different column, hence the issue.

The ultimate solution here then is to get this column mapped to the correct key. In the meantime I can work around this.

Thanks for the help! Hopefully this guides other poor souls with bad databases in the future.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 12, 2009 5:23 pm 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Hmmm... that makes kind of sense.... but I think that when you associate the user with an order it should trigger the user to be initialized.... but it doesn't because you have annotated the private property instead of the getter method. Proxy initialization only works properly if the annotations are on the getter method.

Another option to make sure the user is initialized is to call Hibernate.initialize(user).


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 13, 2009 11:27 am 
Newbie

Joined: Wed Oct 01, 2008 8:42 pm
Posts: 12
Ah, I didn't realize there was a difference in where you put the annotation. I'll change this in my classes.

Thanks again,
Tim


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