Announcement Announcement Module
Collapse
No announcement yet.
Hibernate lazy loading breaks DataAcessExceptions Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Hibernate lazy loading breaks DataAcessExceptions

    Let's consider the following architecture:

    Services use DAOs to manipulate Domain Objects. Services make all efforts to be really isolated (and agnostic) from data access technology.

    But, when DAOs are specifically Hibernate DAOs, lazy loading proxies get into the way, so any HibernateException occurred during lazy loading will not be translated, and will leak into Service classes :!: (see code below)

    I am having big trouble trying to make DAOs and Services really reusable and properly isolated. OK, I could install interceptors here and there to translate leaked HibernateExceptions back into DataAccessExceptions... But I think it begins to get messy... :roll:

    So I'm asking your help, thanks in advance!

    Code:
    public interface CustomerService
    {
        Customer login(String id, String password) throws LoginException;
    }
    
    public class CustomerServiceImpl implements CustomerService
    {
        private CustomerDAO customerDAO;
    
        public setCustomerDAO(CustomerDAO customerDAO)
        {
            this.customerDAO = customerDAO;
        }
    
        public Customer login(String id, String password) throws LoginException
        {
            Customer customer = customerDAO.findById(id);
    
            // verify password and throw LoginException on failure
    
            // but hey, a database failure on loading any lazy 
            // loaded Customer property (not only collections, but any 
            // Hibernate3 lazy loaded instance) will result on HibernateException,
            // thus leaking technology specific Exceptions into Service Layer
            // and also breaking DataAccessException philosophy...!
    
            return customer;
        }
    }
    
    public interface CustomerDAO
    {
        Customer findById(String id) throws DataAccessException;
    }
    
    public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDAO
    {
        public Customer findById(String id) throws DataAccessException    
        {
            return (Customer)getHibernateTemplate().load(Customer.class, id);        
        }
    }

  • #2
    Are you using this in a web app? See the org.springframework.orm.hibernate3.support.OpenSes sionInViewFilter. Adding this into your app should solve your problems.

    Comment


    • #3
      Originally posted by lightc
      Are you using this in a web app? See the org.springframework.orm.hibernate3.support.OpenSes sionInViewFilter. Adding this into your app should solve your problems.
      I am already using OpenSessionInViewFilter, lightc. The problem is not the absence of a Session, but the HibernateExceptions which may be thrown by Hibernate proxies.

      Let's supposed that some method in service layer uses a DAO to retrieve any entity. Hibernate will provide a proxied entity. So, if you try to access any property which is lazy loaded by the proxy, a HibernateException may occur.

      So, if you're trying to isolate tiers, suddenly a HibernateException will occur outside the DAO (in service layer, in this case). So the service layer should now be aware of Hibernate, and tier isolation blows away. Spring's DataAccessException philosophy blows away too.

      I am trying to figure out what should be done to avoid this. Maybe to write some kinda wrapper around the service layer?

      Comment


      • #4
        Yes, this is definitely a danger of lazy loading. It does break the Spring exception contract. However, I think the real question is how you would handle the error, regardless of the exception. If you don't have the data, the page will presumably break or be misleading to the user, and exactly which exception you're dealing with is more a cosmetic issue.

        So I would advice ensuring that your application is tested so that a lazy loading error cannot occur. (Or perhaps use Open Session in View, although I'm not a great fan of that approach.)

        The org.springframework.test package enables you to test your code outside the web container but hitting a real database. There is an endTransaction() method that enables you to end the transaction and then touch relationships as you like, to ensure that adequate data has been loaded. Much faster to find problems and prevent regressions that relying on navigating through your pages by hand...

        Comment


        • #5
          Originally posted by Rod Johnson
          Yes, this is definitely a danger of lazy loading....
          Thank you, Rod!

          Since I'm new to both Spring and Hibernate, I was afraid I could be missing important detail and misinterpreting something. Sometimes I think that trying to achieve perfect tier isolation and a high level of technology 'independence' can make things worse in some cases.

          I was thinking "Hmmm, I shouldn't have HibernateExceptions outside my DAOs, at least the DAOs should catch them and rethrow them as generic DAOExceptions".

          But, after reading your reply, I can see that I must reconsider about it.

          Comment

          Working...
          X