13

I have next error: nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.Model.entities, could not initialize proxy - no Session

My Model entity:

class Model {
...
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "model", orphanRemoval = true)
    @Cascade(CascadeType.ALL)
    @Fetch(value = FetchMode.SUBSELECT)
    public Set<Entity> getEntities() {
        return entities;
    }

    public void addEntity(Entity entity) {
        entity.setModel(this);
        entities.add(entity);
    }

}

And I have a service class:

@Service
@Transactional
class ServiceImpl implements Service {
    @Override
    public void process(Model model) {
        ...
        model.addEntity(createEntity());
        ...
    }
}

I'm calling service from another service method:

@Override
@JmsListener(destination = "listener")
public void handle(final Message message) throws Exception {
    Model model = modelService.getById(message.getModelId());
    serviceImpl.process(model);
    modelService.update(model);
}

But when I'm trying to call this method I'm getting exception on line entities.add(entity); also the same exception occurs when I'm calling getEntities() on model . I've checked transaction manager and it's configured correctly and transaction exists on this step. Also I've checked tons of answers on stackoverflow connected to this exception but nothing useful.

What could be the cause of it?

4
  • When you say "transaction exists on this step" you mean that you have checked that a transaction is really open, like using stackoverflow.com/a/42584751/3517383? Commented Mar 21, 2017 at 11:34
  • @gabrielgiussi yes Commented Mar 21, 2017 at 11:35
  • Is entity a new object? If it's the case, you have to save the entity object first in the database and then you can add it in the list of entities. Commented Mar 21, 2017 at 13:32
  • I guess you are wrong, actually calling model.getEntities() gives me the same error about lazyinitialization Commented Mar 21, 2017 at 13:41

2 Answers 2

9

It seems that model is a detached entity.

Try to merge and perform operations on a merge instance:

@Override
public void process(Model model) {
     ...
    Model mergedModel = session.merge(model);

    mergedModel.addEntity(createEntity());
    ...
}
Sign up to request clarification or add additional context in comments.

4 Comments

Indeed, or open the transaction in an initial service that invokes all the other services.
Actually I don't want to use session object. Just before calling process I'm doing modelService.getModelById(modelId); and it returns me object from database
Ok but that is done i assume in a separate transaction.. once you call process method the model is already a detached entity and persistence provider does not manage it anymore. You have to merge it back. Or simply make the query inside of the process method.
Thanks your answer helped. Added query to my process method
7

So as @Maciej Kowalski mentioned after first @Transactional read of my model it's already in deatached state and call to get entities from another @Transactional method failed with LazyInitializationException.

I've changed my service a bit to get model from database in the same transaction:

@Service
@Transactional
class ServiceImpl implements Service {
    @Override
    public void process(long modelId) {
        ...
        Model model = modelDao.get(modelId);
        model.addEntity(createEntity());
        ...
    }
}

Now everything works as expected.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.