gerrytan
gerrytan

Reputation: 41143

Programmatically Fetching a Lazy JPA Field

I have a lazily fetched field in my entity

@ElementCollection(fetch = LAZY)
private List<String> emails;

And my transaction boundary stops at service class, I don't want to keep it open while rendering the view. I want my service classes to return detached entities.

In my service class I tried calling the getters but that seem to be erased by the compiler -- maybe it's an optimization for a statement that appear to do nothing

/* User Service class */
@Transactional
public List<User> getAllUsers() {
  List<User> users = new ArrayList();
  for(User u : userRepo.findAll()) {
    u.getEmails(); // <-- this seem to be erased by the compiler optimization.
    users.add(u);
  }
  return users;
}

Hence I'm forced to print the lazy field into TRACE log so that it won't clutter the production logs. Doing this will ensure the lazy field is pre-populated before the entities are detached:

LOG.trace(u.getEmails().toString());

However this solution isn't pretty at all. Is there any better way to do this?

I don't want to mark the field as EAGER because I have another service method that purposely skips the relationship for efficiency.

Upvotes: 2

Views: 1153

Answers (2)

Todd
Todd

Reputation: 31720

Since you are using Hibernate, this is probably going to have to be specific. I'm not aware of any JPA functionality that does this. According to the Hibernate Documentation:

The static methods Hibernate.initialize() and Hibernate.isInitialized(), provide the application with a convenient way of working with lazily initialized collections or proxies. Hibernate.initialize(cat) will force the initialization of a proxy, cat, as long as its Session is still open. Hibernate.initialize( cat.getKittens() ) has a similar effect for the collection of kittens.

This should prevent the compiler from erasing that call, and remove the need for you to do some kind of work with the return value to trick the compiler. So Hibernate.initialize(u.getEmails()) should work for you.

Upvotes: 3

baju
baju

Reputation: 511

Hibernate.initialize(u.getEmails())

Upvotes: 3

Related Questions