Remover uma lista sem cascade="all-delete-orphan" was no longer referenced by [resolvido]

2 respostas
P

Eu tenho um objeto pessoa que possui algumas listas. Qdo preciso atualizar nao tenho como saber se é uma operacao de update ou delete, entao eu optei
por deletar as listas e inserir de novo. E tive os problemas abaixo além da exeção: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance:

1 - primeiro tentei inserir os emails(codigo do salvaremail()) apos usar o emails().clear. Ao inserir dava erro dizendo que já existia, devido a constraint
2 - ainda usando emails().clear, fiz um metodo separado para adicionar os emails, esperando finalizar a transacao do metodo atualizarpessoa() e depois chamando salvaremail() pudesse resolver
3 - removi o emails.clear() e fiz um delete na mao, dae funcionou, usando atualizarpessoa() e salvaremail()

A melhor maneira de eu remover uma lista e adicionar novamente seria como fiz ? a princípio nao posso mexer no mapeamento....

fluxo dos metodos:
atualizarpessoa();
salvaremail()

class PessoaService { //ejb

public atualizarpessoa(){
//1
   pessoa.getEmails().clear();
//3
entityManager.createQuery("DELETE  Email p WHERE p.pessoa.idPessoa = :idPessoa").setParameter("idPessoa", pessoa.getIdPessoa()).executeUpdate();


}

//2
public salvaremail(){

		try {
			List<Email> emails = pessoa.getEmails();
			for (Email pe : pessoar.getEmails()) {
				if (pe.getEmail().isEmpty())
					continue;
				pe.setPessoa(pessoa);
				emails.add(pe);
			}
			pessoa.setEmails(emails);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return pessoa;
}


}


//estou usando yy xx pra simplificar...
class Pessoa extends  YY{

    @OneToMany(mappedBy = "pessoa")
    @Cascade({
        CascadeType.ALL,
        CascadeType.DELETE_ORPHAN
    })
	private List<Email> emails = newList();

}

class YY extends XX {}
class XX {

    public static <T> List<T> newList() {
        return new ArrayList<T>();
    }
}

2 Respostas

H

Seu passo dois se não te mantou vai te matar.

Ao executar entityManager.createQuery(“DELETE Email p WHERE p.pessoa.idPessoa = :idPessoa”).setParameter(“idPessoa”, pessoa.getIdPessoa()).executeUpdate(); caso exista esse email dentro do seu PersistenceUnit, ele vai ficar furado.
O JPA/Hibernate não detecta se houve não alguma alteração em algum objeto attached quando você usa o executeUpdate().

Ou você mudar para entityManager.remove(); e passa o objeto aí ou então vc chama o flush antes de executar o executeUpdate();

P

resolv vi assim:

//classe pessoa
 @OneToMany(mappedBy = "pessoa")
    @Cascade({
        CascadeType.ALL,
        CascadeType.DELETE_ORPHAN
    })
	private List<Email> emails = newList();


//codigo no ejb
pessoa.getEmails().clear();
entityManager.flush();
salvaremail();

:slight_smile:

Criado 11 de abril de 2012
Ultima resposta 16 de abr. de 2012
Respostas 2
Participantes 2