Search code examples
hibernatejpalazy-loadingentitymanagerhibernate-session

Is the use of Session.buildLockRequest() to reattach entity to EntityManager a practical solution?


My problem is relatively simple:

I have an entity with many lazily loaded Sets that I don't need all the time. Now I don't want to load everything eagerly, nor do I want to have several different getSlimEntity(), getFullEntity(), getEntityForSpecialOccasion() methods.

What I'd like to do is having the 'slim' version by default and then load the lazy stuff on demand. That demand could originate in changing a tab on a web page displaying a 'task' entity. The new tab should display the task's history. This tab isn't used very often, though, so I don't want the data eagerly.

A solution should put as little work as possible on the database since database performance this is a problem for us.

A possible solution I came up with is using Session.buildLockRequest() to 're-attach' the task to the EntityManager and the call Hibernate.initialize() on the Set I need. It looks like this:

public Set<HistoryEntry> getHistory(Task task) {

    Session session = manager.unwrap(Session.class);
    session.buildLockRequest(LockOptions.NONE).lock(task);

    Hibernate.initialize(task.getHistory());

    return task.getHistory();
}

It's a slim and relatively easy-to-understand solution, also the database isn't updated or anything, just queried for the HistoryEntries in question.

Now my question(s): Is this solution okay to use? Does it pose any problems I don't see? What is actually happening by calling buildLockRequest? Also, could there be problems when multiple users view the same task?

// Edit: As pointed out, this solution uses Hibernate specific calls that may not be compatible with other Persistence Providers, such as EclipseLink or OpenJPA. Since this project is internal only, that should not be a problem.


Solution

  • I am not sure if using LockRequest#lock() to reattach object to session (by the way, it behaves strangely as it does not make any version check or synchronize changes) is a good idea. In your case it may seem like a proper solution, but it just looks like a side effect and I would not rely on this feature.

    The other thing is - talking about Hibernate specific calls when using JPA is bad as MWiesner already pointed out in comment.

    You have so many alternatives:

    1. If you know how an object will be used at the time of retrieval from DB - make use of entity graphs.
    2. You can just make query retrieving all Histories for passed entity.
    3. If you know that the passed object cannot be changed, you can just reattach it to persistence context via EntityManager#merge.

    Why don't select one of above?