2

I have an Parent object that contains a list of Child objects. When I fetch a list of these Parents (to display in a grid) I do NOT want all the Child objects - that just wastes time and memory. However, when I fetch a single Parent (to display all details of the parent on a different page) I DO want a list of its Children.

class Parent {
    String name;
    List<Child> children;
}

class Child {
    String name;
    Date   birthDate;
}

So I set up lazy-fetch on Children so that by default the Children are not returned (when getting a list), but I can set FetchMode to JOIN to return the full object (Parent + Children) for a single Parent when I want it. This works fine.

However, for my action class that queries these two sets of data to 'return' it to my JSP screens, I use Gson.toJson(object) to format it. This throws a LazyInitializationException because its trying to fetch the Children. I don't WANT the children to be fetched when I don't need that data.

So this brings up some questions on how to 'fix' this situation :

1) Can I tell/configure Gson to NOT fetch missing lazy-fetched children?

2) If not, is there an alternative Json formatter to Gson that will respect hibernate lazy-fetch?

3) Is there another way for my action class to return or make accessible the Java bean objects that are fetched from a DB to the JSPs so that the data can be used to fill in fields and grids, other than using json format?

user3708842
  • 543
  • 8
  • 23
  • How about explicitly setting the child list to empty list in places where you send data to be displayed on grid where child doesnt matter. Sorry if this is not helpful – Manjunath Aug 16 '14 at 18:13
  • U can try this: http://stackoverflow.com/questions/4802887/gson-how-to-exclude-specific-fields-from-serialization-without-annotations – Sandhu Santhakumar Aug 16 '14 at 20:02
  • @Manjunath Actually that was my 'kludge' workaround. After fetching the list of objects, I traversed the list, setting the ChildrenList to null. This kept Gson from attempting to lazy-fetch the data. But I knew there had to be a better/right way to do this. – user3708842 Aug 18 '14 at 13:52
  • 1
    @sandhu Thanks for the link. I followed it to find a fix and wrote the details below. – user3708842 Aug 18 '14 at 13:52

1 Answers1

4

I took the link that Sandhu provided and that led to Excluding Fields From Serialization and Deserialization here :

https://sites.google.com/site/gson/gson-user-guide#TOC-Custom-Serialization-and-Deserializ

Using this strategy, I get this :

class Parent {
    String name;
    transient List<Child> children;
}

and when I retrieve the FULL object from the DB (with Children), I use this :

Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.STATIC).create();

It's a little backwards because the default is TRANSIENT and STATIC, so setting the exclude to only STATIC implies that TRANSIENT IS included. (I think they need an includeFieldsWithModifiers() method).

So in summary, lazy fetch is defined in the hbm.xml, and when I need all the data, I override it with FetchMode.JOIN. Gson defaults to ignoring the transient attribute that wasn't fetched and when I need all the data 'jSoned' I override that with excludeFieldsWithModifiers.

I'm not sure I'm 100% happy with this setup, because 'transient' may have some other effects that I haven't found yet. If so, then I guess I can set up a User Defined Exclusion Strategies to stop jSon from touching that non-fetched attribute.

IMO I think Gson is way overstepping its bounds in 'secretly' fetching data that I know I don't have nor do I want. To me it should simply just convert whatever data is IN the object to a string. I thought it was a simple object-string conversion utility - something that I could write in an hour. But if it needs to be much more complicated, it should at least have a 'simple' conversion option - tojSonSimple().

One followup question - will setting attributes as transient have any other undesirable effects that I should know about?

user3708842
  • 543
  • 8
  • 23