tibo
tibo

Reputation: 5474

Hibernate to initialize object in a different transaction

I got the famous LazyInitializationException.

I have an object User which is stored in the session. This object contains an other object Market which is lazy initialized. When I load the user in the session, I don't load Market because it is too heavy and I don't need it everytime.

When I want to load the market, I am in a different transaction and I don't want to reload the user from the database. How can I retrieve the Market object? Knowing that User.market contains the Hibernate proxy and so the id of the market and that I don't want to hack Hibernate using reflection.

That would be even better if I could load the market without loading it into the user. Since the user is in the session, I don't want to put a lot of stuff in the session.

A JPA compatible solution would be even better.

Cheers

Upvotes: 2

Views: 1520

Answers (5)

Bogdan
Bogdan

Reputation: 944

What you have to do is to annotate the accessors instead of the fields. This will allow you to avoid loading of the market object when you initially load the user, but you will have access to the id of the market from the Hibernate proxy object without triggering a lazy loading or getting a LazyInitializationException. Then later on when you want to load the market itself you do a normal entity retrieval based on its id. You can read a detailed explanation of how this works here.

Upvotes: 1

Atticus
Atticus

Reputation: 1632

Why is the obvious solution not good? Like the one ring0 suggested, or simply using the findById or find methods if you already have the id in the User object.

//if using a session factory
session.findById(Market.class, marketId); 

//if using the EntityManager
em.find(Market.class, marketId);

Depending on how the current_session_context_class configured (I have it in hibernate.cfg.xml) you might have a new session with each new transaction. If that is the case the you do not need to worry about putting too much stuff in there. You can find more info on contextual sessions here.

Upvotes: 1

Sudhakar
Sudhakar

Reputation: 4873

Since you have mentioned new transaction , then you would probably working with a new hibernate session belonging to thread ,

Use this incase of direct interaction with hibernate session

   obj = session.merge(obj);

In case your using JPA2 Api

   obj=   entityManager.merge(obj);

Please rate the answer if it helps. Cheers

Upvotes: 0

Déjà vu
Déjà vu

Reputation: 28840

If the eager mode fetching is not acceptable, and if the transaction cannot be maintained up to the Market retrieval, a specific dao method could be implemented to retrieve specifically the market from a user

public List<Market> retrieveMarketFromUser (final User user) {
  Query query = session.createQuery("SELECT m FROM User AS u INNER JOIN u.market as m WHERE u.userid = :uid");
  query.setParameter("uid", user.getId());
  List<Market> list = query.list();
  return list;
}

or the short version

  Query query = session.createQuery("SELECT u.market FROM User AS u WHERE u.userid = :uid");

This is maybe not the JPA solution you were expecting, just a workaround.

Upvotes: 2

Bogdan
Bogdan

Reputation: 944

If the relation is bidirectional then you can load the Market independently using a query with clause like where market.user.id = ?.

Upvotes: 1

Related Questions