3

I'm using hibernate for persistence. In my data access layer, I specify some parts of the result to be eagerly loaded depending on the scenario.

Now I need to send these result as JAX WS responses.

Is there any way that I can have some cleaner method which will take an entity object, traverse through it, and set null to fields that are not initialized so that hibernate would not throw LazyInitializationException when the object is passed to web service layer.

Or is there any alternatives to solve this issue.

janith
  • 1,025
  • 5
  • 21
  • Have you seen [this](http://stackoverflow.com/questions/5800814/is-it-possible-to-detach-hibernate-entity-so-that-changes-to-object-are-not-aut)? – mindas Mar 13 '13 at 21:37

4 Answers4

2

There's such thing as Hibernate#initialize() which you could run in an active session after loading entity, but it will initialize fields/references at the root level of the entity (or collection) you have passed -- in case entity is a Hibernate proxy. As the JavaDoc states:

Note: This only ensures intialization of a proxy object or collection; it is not guaranteed that the elements INSIDE the collection will be initialized/materialized.

Assigning NULL to uninitialized fields is not a good approach as it breaks data consistency (if someone access those fields, then they are expected to return the actual value).

Art Licis
  • 3,619
  • 1
  • 29
  • 49
1

I have the same architecture here and we do the load job in the business layer. There is no way to do this automatically because just you know what data is needed in your ws response. Basically, I have a method that converts a entity model(JPA mapping) to a simple POJO and vice-versa and in this method I resolve which attribute is needed to load.

You could use something like this:

public interface IBusiness<Model, VO> {

    public Model toModel(VO vo);
    public VO toVO(Model model);
    public List<Model> toModelList(List<VO> vos);
    public List<VO> toVOList(List<Model> models);

}

You implements this interface on your business layer and solve the lazy problem loading everything you need in this methods.

good luck =)

Marcio Barroso
  • 783
  • 1
  • 7
  • 21
  • Yes, as you said I resolve which attributes should be loaded in my data access layer. What I was wondering was whether there was any method to 'nullify' the uninitialized fields automatically before sending them through the web service. – janith Mar 13 '13 at 15:02
  • I like your approach btw, how do you handle a scenario like this: In one scenario you have a certain subset of the fields initialized, and in another scenario some other subset of fields are initialized. – janith Mar 13 '13 at 15:05
  • You can use Hibernate.initialize() to load the not initialized fields. But take care ... you must call this method using which not initialized fields and not the object instance. – Marcio Barroso Mar 13 '13 at 15:21
1

If you're using Spring you can use the OpenSessionInView(Interceptor|Filter). It's an easy fix for lazy initialization exceptions because it aligns the session boundaries with the request boundaries. I generally don't like this approach because it gets rid of the errors by doing additional queries against the database for data that is proxied.

My preference in a case like yours is to use transfer objects that have the specific fields you're interested in for each call. There is no point to sending data back and forth that isn't necessary, or worse, sending data that misrepresents the actual state of your persistence layer.

I'd actually go one step further and leave your session boundaries as they are, and make sure that your DAO methods are returning transfer objects and not entities. People will often argue that entities are just POJOs, and this is just more work. But the reality is, as your question illustrates, an attempt to treat the entity as a POJO can result in implicit data access, which belongs in a layer dedicated to data access.

Jeff
  • 3,669
  • 1
  • 23
  • 33
  • I do not use spring, "People will often argue that entities are just POJOs, and this is just more work" This was exactly why I didn't initally consider DTOs. But as you pointed out, using DTOs will be a good solution here. Can you point me to any design patterns/elegant ways to handle the conversion of Entity -> DTO – janith Mar 13 '13 at 15:11
  • I am not shure that OpenSessionInView filter will work in this scenario. – Marcio Barroso Mar 13 '13 at 15:26
  • 1
    It's a tough problem to solve when you consider entity nesting, collections and type conversions (relationships in DTOs are often represented by a primitive PK field rather than full entity). Maybe something like Dozer (http://dozer.sourceforge.net/) would help get you most of the way there. – Jeff Mar 13 '13 at 15:28
0

The alternative could be not using lazy initialization at all.

How to do it depends on the case you dealing with. The answer you will find on SO.

  • Not using lazy loading is not an option. If all the relationships were eagerly loaded I would end up with a LOT of unnecessary data, which when transferred over the network would be a significant performance issue. – janith Mar 13 '13 at 14:47
  • because of that, I suggest you to solve "by your self" the loading of necessary data before the end of cycle. =) – Marcio Barroso Mar 13 '13 at 14:55