JPA - Cascade.REMOVE não funciona

17 respostas
java
Satangozo

Eu tenho uma tabela chamada “Empresa” que está relacionada a tabela “Usuario” e Empresa é dona do relacionamento.

No mapeamento da tabela empresa tenho o seguinte código:

@OneToMany(cascade = CascadeType.REMOVE, mappedBy = "usuarioId")
private List<Usuario> usuarioList;

Se eu criar a empresa e o usuario e depois tentar excluir a empresa recebo uma violate constraint exception, mas isso não deveria acionar a cascata???

Mas curiosamente se eu fechar e abrir a aplicação novamente consigo excluir normalmente em cascata. Após isso fiz vários testes e a unica coisa que resolveu via código era criando um novo EntityManagerFactory para cada delete() que eu fizer… Mas isso é uma bela de uma gambiarra que consome muitos recursos. Qual é maneira certa de fazer esse delete sem ter que criar um novo EntityManagerFactory?

17 Respostas

Lucas_Camara

Qual a constraint que foi violada?

Satangozo

Ela se chama “FK_REFERENCE_2” mas ela na verdade é o unico relacionamento da tabela “Empresa” que liga o campo “empresaId” da tabela “Empresa”, no campo “empresaId” da tabela “Usuário”

Lucas_Camara

Se dentro do usuário possui a empresa em que o mesmo está, então esse mapeamento está errado. Deveria ser:

@OneToMany(cascade = CascadeType.REMOVE, mappedBy = "empresa")
private List<Usuario> usuarioList;
Satangozo
@OneToMany(cascade = CascadeType.REMOVE, mappedBy = "empresaId") private List usuarioList;

Falha minha, é que eu tentei de tudo acabei esquecendo assim XD… Alterei o código como acima e fiz o teste novamente, ainda assim só consigo excluir em cascata se eu fechar e abrir novamente a aplicação (o que tambem cria um novo EntityManagerFactory).

Lucas_Camara

Na classe Usuário, a empresa está mapeada como?

Satangozo
@JoinColumn(name = "EMPRESA_ID", referencedColumnName = "EMPRESA_ID", insertable = false, updatable = false) @ManyToOne(optional = false) private Empresa empresaId;

Assim.

Lucas_Camara

Porque insertable e updatable estão como false? Nâo deveria ser true?

Satangozo

Essa parte de código foi gerada automaticamente pelo Netbeans então nem ousei a modificar, e eu realmente nem sei pra que ele funciona, mas acredito que seja para que eu não consiga criar ou alterar o FK sem ter o objeto em questão persistido, mas vou tentar setando eles para true para ver se rola.

Lucas_Camara

insertable:

Whether the column is included in SQL INSERT statements generated by the persistence provider.

fonte: JoinColumn Docs

Satangozo

Achei um caso parecido com o meu no stackOverFlow onde o cara tinha as tabelas Empregado, Patrao, e endereço, tanto o empregado quanto o patrao usavam a tabela endereço, e ao tentar excluir o empregado que tinha cascata pro endereco ele recebia a exception porque o patrao tambem usava essa tabela… Eu tenho algo parecido porque tenho a tabela usuario que tambem é usado pela tabela pessoa, e até ai tudo bem, mas porque ele faz o que eu quero quando uso outro entityManagerFactory (ou reinicio a aplicação)? Isso não deveria funcionar de maneira alguma, ou funcionar para todos os casos…

Lucas_Camara

Hmmm, ai complica. Realmente bem estranho :confused:

Lucas_Camara

Uma pergunta. Usuário é uma especialização de pessoa no seu banco?

Satangozo

É sim, Um usuário é criado quando eu ligo uma pessoa a uma empresa, é como uma relação de “muitos para muitos” entre empresa e pessoa. Por isso eu quero apagar o usuário e manter a pessoa quando excluo uma empresa.

Lucas_Camara

Deveria excluir de boa, pois a chave do usuário não existe na pessoa. Acho que você poderia mostrar um pouco mais de código pra gente tentar entender o que está acontecendo.

Satangozo

O pior é isso… Eu consigo exatamente como deveria, mas só depois de reiniciar a aplicação, ou usar um EntityManagerFactory diferente…

É como se a Sessão em que eu criei os dois objetos ignorasse o Cascade, mas se ela não criou tais objetos ela passase a respeitar.

Lucas_Camara

Se você pegar o SQL que é gerado pela JPA (antes da exceção) e executar diretamente no banco, o registro é excluído?

Satangozo

Está falando sobre um comando direto no banco? Não funciona porque no banco os cascades são restricts. Ou seja, se tiver filho restringe de deletar o pai.

Criado 15 de julho de 2016
Ultima resposta 15 de jul. de 2016
Respostas 17
Participantes 2