-->
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: What is the best place to catch LazyInitializationException?
PostPosted: Thu Aug 04, 2005 9:35 am 
Regular
Regular

Joined: Wed May 11, 2005 11:57 pm
Posts: 80
I want to be able to catch and handle LazyInitializationExceptions, but I don't see a good way to do that in Hibernate. Here are the things I've looked at:

* One way to do this would be inside my data model getXXX() methods, but I don't want to embed Hibernate-specific code into my data model.
* Another place to put this might be the code that calls my data model getXXX() methods, but these methods can be called directly from framework code that I cannot alter.
* The only other place I can think to catch and handle this exception is inside a subclass of the Hibernate collection class that actually does the lazy initialization. Unfortunately, it seems to me from browsing the source code of HbmBinder that there is no clean way to use my own collection subclass, and even if there was, I would need to subclass every possible Collection class to make this work, since the lazy initialization happens in the AbstractPersistent superclass.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 04, 2005 10:20 am 
Expert
Expert

Joined: Thu Dec 04, 2003 12:36 pm
Posts: 275
Location: Bielefeld, Germany
Have you already thought about the right strategy to avoid LazyInitializationExceptions?

From JavaDoc of LazyInitializationException:
"Indicates access to unfetched data outside of a session context.
For example, when an uninitialized proxy or collection is accessed
after the session was closed."

So, you should have a look at the session handling in your application in order to avoid these exceptions. Have a look at the following link, for example.
http://www.hibernate.org/43.html

Best regards
Sven


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 04, 2005 10:31 am 
Regular
Regular

Joined: Wed May 11, 2005 11:57 pm
Posts: 80
I am aware of what LazyInitializationException means, and I understand that it is preferable to avoid it. That said, I should still be able to catch and handle the exception if I choose to.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 04, 2005 10:34 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
It's no different from any other exception, so handle it where you take care of RuntimeException, I guess.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 04, 2005 11:04 am 
Regular
Regular

Joined: Wed May 11, 2005 11:57 pm
Posts: 80
christian wrote:
It's no different from any other exception, so handle it where you take care of RuntimeException, I guess.


There's an important difference in this case... unlike a NullPointerException, IndexOutOfBoundsException, or other JDK RuntimeException, the LazyInitializationException being thrown is outside the control of the data object calling it. Consider the following code:

Code:
public class Instructor {
    private List coursesTaught = new List();

    public boolean hasCourses {
        return coursesTaught.size() > 0;
    }
}


When I'm not running Hibernate, there might be Errors, but as far as I can tell, there are no RuntimeExceptions that can be thrown in this method.

When using Hibernate, there could be a LazyInitializationException. I could do as you suggest and modify my data model to catch Hibernate exceptions, but that would make my data model dependent on the Hibernate classes, ruin the 'transparency' of Hibernate, and require me to duplicate that code in every accessor method. I would like the capability to handle that exception somewhere in the size() method of the coursesTaught. There are many things I might do with the exception:

* Rethrow the Exception as some abstracted non-Hibernate exception that I can catch without creating a dependency on Hibernate
* Log the exception
* Load the information on demand through some other mechanism
* Substitute some default value
* Derive the data through some calculation


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 04, 2005 11:26 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
OK, so replace the word "LazyInitializationException" with "RuntimeException" and replay the scenario. Would you catch that in your model or at a single point in your application where fatal infrastructure exceptions are handled? It's a bug in your application if you get it. No reason to catch and handle it special.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 04, 2005 11:36 am 
Senior
Senior

Joined: Thu May 12, 2005 11:40 pm
Posts: 125
Location: Canada
A LazyInitializationException is an error condition that should be fixed instead of handled. Because it can occur anywhere (during view rendering, during business logic, whatever), there's no good place to catch it. If you get it, you should generally think about adding eager fetches to make that data available to the code that produces it, rather than trapping it and then doing some logic to perform additional loading.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 04, 2005 11:45 am 
Regular
Regular

Joined: Wed May 11, 2005 11:57 pm
Posts: 80
christian wrote:
OK, so replace the word "LazyInitializationException" with "RuntimeException" and replay the scenario. Would you catch that in your model or at a single point in your application where fatal infrastructure exceptions are handled? It's a bug in your application if you get it. No reason to catch and handle it special.


The key word here is 'fatal'. If it's fatal, it should be LazyInitializationError, not LazyInitializationException.

I don't view it as fatal. I think that I should be able to load the information on demand without needing to mangle my data model.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 04, 2005 11:48 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Hibernate is a transaction processing system, not an ad-hoc object streaming service.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 04, 2005 11:51 am 
Senior
Senior

Joined: Thu May 12, 2005 11:40 pm
Posts: 125
Location: Canada
jbarnum wrote:
christian wrote:
OK, so replace the word "LazyInitializationException" with "RuntimeException" and replay the scenario. Would you catch that in your model or at a single point in your application where fatal infrastructure exceptions are handled? It's a bug in your application if you get it. No reason to catch and handle it special.


The key word here is 'fatal'. If it's fatal, it should be LazyInitializationError, not LazyInitializationException.

I don't view it as fatal. I think that I should be able to load the information on demand without needing to mangle my data model.


You can load data on demand so long as you're within the original session scope, which is the definition of lazy loading. If Hibernate were to open new sessions and perform reattachment instead of throwing a LazyInitializationException, that would expose you to the well discussed ad-hoc transactional semantics, which you don't want. As a solution, either reattach the instance using lock() before you use it within another session scope, or think more carefully about your fetch plan in order to avoid the problem altogether.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 04, 2005 11:55 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
By the way, the difference between Error and Exception is not if one is fatal or the other isn't, but if there should be a catch or not.

As you have certainly read the Hibernate reference documentation, you already know that you have to catch all exceptions thrown by Hibernate (hence no errors) to gracefully rollback and end your unit of work. There are even a few exceptions where it makes sense to continue the application, such as locking failures. In a new unit of work, of course.

However, as has been explained several times in this thread already, and many times in the past, LazyInitializationException is a bug in your application and appears when your unit of work already ended, hence there can't be no "loading on demand" at this point. If you want to continue retrieving data, open a new unit of work and reattach your detached objects to it. Or, retrieve all data you need in the first unit of work, using appropriate fetching techniques. There are no ad-hoc transactions in Hibernate.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 04, 2005 12:10 pm 
Regular
Regular

Joined: Wed May 11, 2005 11:57 pm
Posts: 80
christian wrote:
Hibernate is a transaction processing system, not an ad-hoc object streaming service.


So if I want an "ad-hoc object streaming service", do you have any suggestions? Other than this missing capability, I am reasonably happy with most other aspects of Hibernate.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 04, 2005 12:14 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Use serialization, you don't seem to need transactional processing, just something that swaps pages of memory in and out. Some object databases basically do just that.

Since nobody finds the FAQ about this stuff I've now added it as a paragraph to the Open Session in View page.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 04, 2005 12:44 pm 
Regular
Regular

Joined: Wed May 11, 2005 11:57 pm
Posts: 80
christian wrote:
Use serialization, you don't seem to need transactional processing.


Yes I do, for 80% of my application. But for read-only access to information that is not used in transactions, I need to be able to do on-demand loading.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 04, 2005 2:17 pm 
Senior
Senior

Joined: Thu May 12, 2005 11:40 pm
Posts: 125
Location: Canada
jbarnum wrote:
christian wrote:
Use serialization, you don't seem to need transactional processing.


Yes I do, for 80% of my application. But for read-only access to information that is not used in transactions, I need to be able to do on-demand loading.


No you don't. Map your read-only objects as lazy="false" (<class ... lazy="false">) and enable the second level cache for them (<class-cache class="..." usage="read-only"/>) to avoid n+1 selects.


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.