Question

I have hibernate pojo class A { B b ; some other properies} with lazy= true for class B. When i get object A, B is not loaded and hibernate returns its proxy. When i pass this object to another module, that module traverse each and every objects in A and when it encounter B.getXXX it throws LazyInitialization exception. In this particular case, I do not want to load class B as it is not required. Is there any way when i call methods on B it either return null or turn proxy of B into real object B so that module doesn't throw LazyInitialization error. I cannot change class B getter,setter as it common class and use by many other classes.

Was it helpful?

Solution 4

Thanks for all your suggestion. My application have layered architecture. Service->Manager->Dao. Hibernate session closes after manager. Other module interacts only through Service. Opening hibernate session till request complete is not an option for me. I also do not want to hit database as it is not necessary that properties of B are populated. I just want to replace hibernate proxy with real object so that anyone who is using service do not face any problem. I found a utility at http://svn.rhq-project.org/repos/rhq/branches/HEIKO-EXP/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/util/HibernateDetachUtility.java which exactly does what i want. It inspect object and replace hibernate proxy with real object. I need to customize following things in above utility 1. Change instances of classname from org.rhq to my package structure. 2. They expect name of identity field in pojo is "id". I change it to use those property which has annotation of javax.persistence.Id.

Basic testing with above changes is done and it is working fine. I just need to test whole application with various scenario so that it is working in all scenario.

OTHER TIPS

If I understand your question, you're retrieving an object A with a lazy association to B. However, this association is not initialized, and you find that other modules are throwing exceptions because B is actually used. So it is required in some way.

You want to either

  • Return null from calls to B (not possible, as far as I know, unless there's some application-specific behavior on those modules that only you can be aware of) or

  • Initialize B when such calls happen. I'll try to help you implement this one.

The reason why you're getting LazyInitializationExceptions is that the session that fetched B (and didn't initialize it) has already been closed, so at this point, the instance of B is of no use at all. One workaround you could apply here is to use the OSIV pattern so that you have the same Hibernate session open in all the request scope. This is the session that will fetch A with lazy B and will initialize B when there is the need.

Another option you could apply would be to initialize B in another session (only valid if those exceptions are occurring in the context of another transaction, that is, with another Hibernate session open, different from the one that fetched A). For instance:

session.update(a.getB());

Of course, you could always force initialization of B with fetchMode.EAGER or Hibernate.initialize(a.getB()). But that would be loading the instance unconditionally, even if it won't be used at all.

Also, you may find the answers to this question may be useful: hibernate: LazyInitializationException: could not initialize proxy

Actually, you have a few option.

1) Make A->B relation EAGER.

2) You are getting LazyInitializationExceptions when you try to initiate proxy while you hibernate session is lready closed. so he possible solution would be to keep Session open till all your A,B,C...etc object manipulation are not completed.

3) If you are talling about WEB environment, there are a pattern called Open Session in view. which keeps your Hibernate session open till your HTTP Request is alive.

I you can read more about it here. I think it will be useful for you to read it.

Don't send the entities to other modules when the session is closed.

If these other module is executed in the same Application Domain as the session, keep the session open when calling the module and close it when it returns.

If these module is not in the same AppDomain, if you need some kind of serialization to send the objects or if it is called asynchronously, I would use a DTO. Exposing the entities outside of the server (I don't know if this is the case here) is a bad practice for several reasons. Ayende Rahien calls it the Stripper Pattern.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top