1
resposta

Como recarregar objetos Lazy após o merge

Pessoa, boa tarde.

Estou usando JSF + Hibernate e o @Transactional do JEE 7. E estou tendo problemas para recarregar objetos Lazy após um merge(). Seria o seguinte:

Eu criei um método chamado initializePessoa() onde ele ao iniciar a view editando uma Pessoa, eu faço o fetch da mesma e também já carrego as coleções Lazy que eu preciso:

public void initializePessoa() {
    pessoa = getEntityManager().createQuery(
                "SELECT p FROM Pessoa p " +
                        "LEFT JOIN FETCH p.enderecos e " +
                        "LEFT JOIN FETCH e.tipo " +
                        "WHERE p.empresa.id = :empresaId " +
                        "AND p.empresaCodigo = :empresaCodigo", Pessoa.class)
                .setParameter("empresaCodigo", idParameter)
                .setParameter("empresaId", loginController.getEmpresa().getId())
                .getSingleResult();

    pessoa.setEmails(getEntityManager().createQuery(
                "SELECT pe FROM PessoaEmail pe " +
                        "JOIN FETCH pe.tipo " +
                        "WHERE pe.pessoa.id = :pessoaId", PessoaEmail.class)
                .setParameter("pessoaId", pessoa.getId())
                .getResultList());
}

Então eu faço as edições que eu preciso e então eu chamo o método savePessoa() onde eu vou gravar as alterações utilizando um merge(), após fazer isso o merge() deixa meu objeto e todas as coleções vinculadas no estado detached ou seja, se eu tento fazer qualquer coisa após isso, seja uma alteração ou acessar algo, ocorre o LazyInitiationException.

Pelo que entendi se trata de um comportamento normal e eu tenho que recarregar essas coleções.

Então eu tentei após o merge() chamar o método initializePessoa() para ter tudo recarregado:

@Transactional(rollbackOn = {Exception.class})
public String savePessoa(boolean saveAndReturn) {
    pessoa = getEntityManager().merge(pessoa);
    initializePessoa();
}

Se eu faço isso, quando eu passo no primeiro carregamento de uma coleção, ele me retorna:

A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance

Como se a transação fosse levada até o initializePessoa() e ele tentasse gravar o set após encerrar o método.

Como eu poderia resolver essa situação? E qual seria o melhor jeito para recarregar essas coleções após um merge?

Obrigado desde já.

1 resposta

Oi Guilherme, achei a situação meio confusa :). No fim o que você precisa é dar o merge e depois inicializar a coleção novamente realmente. O que eu faria é: após o merge eu daria um redirect para o xhtml que você quer... Isso geraria um novo request e este problema que você está tendo ia desaparecer.