Reputation: 9487
I'm having a problem where JPA is trying to lazily load my data when I don't want it to. Essentially what is happening is I'm using a Service to retrieve some data, and when I go to parse that data into JSON, the JSON library is triggering hibernate to try and lazily load the data. Is there any way to stop this? I've given an example below.
// Web Controller method
public String getEmployeesByQuery(String query) {
Gson gson = new Gson();
List<Employee> employees = employeeService.findEmployeesByQuery(query);
// Here is where the problem is occurring - the gson.toJSON() method is (I imagine)
// using my getters to format the JSON output, which is triggering hibernate to
// try and lazily load my data...
return gson.toJSON(employees);
}
Is it possible to set JPA/hibernate to not try and lazily load the data?
UPDATE: I realize that you can use FetchType.EAGER - but what if I don't want to eager load that data? I just want to stop hibernate from trying to retrieve more data - I already have the data I want. Right now whenever I try and access a get() method hibernate will throw a "no session or session is closed" error, which makes sense because my transaction was already committed from my service.
Thanks!
Upvotes: 11
Views: 12028
Reputation: 1610
You really have two options:
toJSON
library reflect the entire object graph. I know some JSON libraries allow you to only serialize some properties of an object to JSON.Personally I would think #1 would be easier if your library only uses reflection.
Upvotes: 4
Reputation: 1378
The easy and straight forward thing to do is create new Data classes (something like DTO) use Hibernate.isInitialized() to check if the object is initialized by hibernate or not. I am checking gson if i can override anything. I will post it here if I find anything new.
Upvotes: 0
Reputation: 556
As others have stated, this is not an issue with JPA/hibernate but rather with the json serialization library you are using. You should instruct gson to exclude the properties you don't want traversed.
Upvotes: 2
Reputation: 2480
Your problem is that you are serializing the data. We ran into the same sort of problem with Flex and JPA/Hibernate. The trick is, depending on how much you want to mangle things, either
Option one is what we did for the first big project we did, but it ruined the data access library we had for any sort of general purpose use. Since that time we've tended more toward option two.
YMMV
Upvotes: 0
Reputation: 7778
I suggest you to make a fetched copy of the entities you want to use outside of a transaction. That way, the lazy loading will occur from within a transaction and you can pass to Gson a plain, not enhanced, POJO.
You can use Doozer to do this. It is very flexible and through a little configuration (read you'll gonna loose your hair configuring it) you can even retrieve only partially the data you want to send to Gson.
Upvotes: 1
Reputation: 242706
There are several options:
If you always need to load your collection eagerly, you can specify fetch = FetchType.EAGER
in your mapping, as suggested in other answers.
Otherwise you can enable eager fetching for particular query:
By using JOIN FETCH
clause in HQL/JPQL query:
SELECT e FROM Employee e JOIN FETCH e.children WHERE ...
Session
via em.unwrap(Session.class)
)Upvotes: 6
Reputation: 44073
You could always change the fetch
attribute to FetchType.EAGER
, but it is also worth considering if you have your transactions have the right scope. Collections will be correctly loaded if they are accessed within a transaction.
Upvotes: 0