PessoALL
Estou fazendo uns testes com o Hibernate e estou passando por um problema estranho. Tenho duas classes, Contato e ContatoEndereco, relacionados num Onetomany com cascadeall. Vejam abaixo as definições dessas classes:
@Entity
@Table(name = "contatos")
public class Contato {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "nome", nullable = false, length = 100)
private String nome;
@OneToMany(cascade = CascadeType.ALL,mappedBy="objContato")
private List<ContatoEndereco> listaEnderecos;
public Contato() {
}
// getters e setters removidos
}
@Entity
@Table(name = "contatos_enderecos")
public class ContatoEndereco {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "nomeLogradouro", nullable = false, length = 100)
private String nomeLogradouro;
@Column(name = "numero", length = 20)
private String numero;
@ManyToOne
@JoinColumn(name="id_contato")
private Contato objContato;
public ContatoEndereco() {
}
// getters e setters removidos
}
No teste de cadastrar o objeto, estou instanciando o contato e populando sua lista com tres contatoEndereco. Isso posto, bastou um persist no objeto Contato e a lista de seus endereços foi corretamente cadastrada no banco. Funciona 100%, 10x cascadeall. Vamos ao “show me the code”:
public void inicializaTeste() {
em = Persistence.createEntityManagerFactory("testeAgendaPU").createEntityManager();
instanceContatoJpaController = new ContatoJpaController();
}
@Test
public void testCadastraContatoComTresEnderecos_ComSucesso() {
inicializaTeste();
limpaArquivoDeContatos();
EntityTransaction transacao = em.getTransaction();
transacao.begin();
// INSTANCIA O CONTATO
Contato contato = new Contato();
contato.setNome("CONTATO");
contato.setFoneConvencional("[telefone removido]");
// INSTANCIA A LISTA DE ENDERECOS DO CONTATO
List<ContatoEndereco> listaEnderecos = new ArrayList();
ContatoEndereco obj1 = new ContatoEndereco("RUA", "GENERAL CAMARA", "PORTO ALEGRE", "RS");
obj1.setObjContato(contato);
listaEnderecos.add(obj1);
ContatoEndereco obj2 = new ContatoEndereco("AVENIDA", "PROTASIO ALVES", "PORTO ALEGRE", "RS");
obj2.setObjContato(contato);
listaEnderecos.add(obj2);
ContatoEndereco obj3 = new ContatoEndereco("TRAVESSA", "ANGUSTURA", "PORTO ALEGRE", "RS");
obj3.setObjContato(contato);
listaEnderecos.add(obj3);
contato.setContatoEnderecoList(listaEnderecos);
// PERSISTE TUDO NUM SO COMANDO
em.persist(contato);
transacao.commit();
}
No teste de remover o objeto Contato, basta um remove e tudo, inclusive os endereços, é deletado da base. Beleza pura, tudo certo.
public void testRemocaoDeClienteComTresEnderecos() throws IllegalOrphanException, NonexistentEntityException {
inicializaTeste();
EntityTransaction transacao = em.getTransaction();
transacao.begin();
Long idEmQuestao = instanceContatoJpaController.buscaUltimoId(em);
Contato contato = instanceContatoJpaController.findContato(em, idEmQuestao);
Assert.assertNotNull("Não foi localizado um contato com id="+idEmQuestao, contato);
Assert.assertEquals("A lista do contato deveria ter sido retornada com TRES itens.", 3, contato.getContatoEnderecoList().size());
// REMOVE O OBJETO COM A SUA LISTA DE ENDERECOS
em.remove(contato);
// VERIFICA SE AINDA EXISTE O REGISTRO
Contato contatoNovo = instanceContatoJpaController.findContato(em, idEmQuestao);
Assert.assertNull("Parece que o contato com id="+idEmQuestao+" não foi removido da base porque eu ainda o encontrei", contatoNovo);
transacao.commit();
}
Mas meu problema é na modificacao da lista. Recupero o objeto com os três enderecos (verificando se vieram tres elementos), deleto o primeiro elemento da lista e persisto o objeto Contato. Tu indicaria que o elemento seria excluido da base de dados. Mas não. Esse item da lista NÃO É EXCLUIDO. Inclusive, no teste, faço nova recuparacao do objeto e checo se a partir daquele momento a lista tem dois e apenas dois itens e, no teste isso passa. Tipo, parece que deu certo até que eu vou olhar no banco de dados e constato que o registro ainda está lá…
public void testRemoveUmEnderecoDeUmClienteComTresEnderecos() {
EntityTransaction transacao = em.getTransaction();
transacao.begin();
// DESCOBRE O ULTIMO ID DE CONTATO CADASTRADO
Long idEmQuestao = instanceContatoJpaController.buscaUltimoId(em);
// VAI LÁ E TRAZ O OBJETO REFERENTE ÀQUELE ID
Contato contato = instanceContatoJpaController.findContato(em, idEmQuestao);
// CONFERE SE A LISTA DE ENDERECOS ESTÁ MESMO COM TRÊS ITENS
Assert.assertEquals("A lista deveria ter sido retornada com TRES itens.", 3, contato.getContatoEnderecoList().size());
// PEGA O PRIMEIRO OBJETO ENDERECO DA LISTA
ContatoEndereco objContatoEnderecoDeletado= (ContatoEndereco) contato.getContatoEnderecoList().remove(0);
// REMOVE O BICHO DA LISTA DE ENDERECOS DO CONTATO
contato.getContatoEnderecoList().remove(objContatoEnderecoDeletado);
// DÁ UMA ALTERADA NO NOME DO CLIENTE, SÓ PRA VER SE, PELO MENOS ISSO, REFLETE NO BD
contato.setNome("CONTATO ALTERADO");
// DÁ UM MERGE LÁ NO BO
instanceContatoJpaController.edit(em, contato);
// PASSA A RÉGUA E FECHA A CONTA (OU SEJA, COMMITA O TREM)
transacao.commit();
// PRA DESENCARGO DE CONSCIENCIA, BUSCA DE NOVO O OBJETO
Contato novoContato = instanceContatoJpaController.findContato(em, idEmQuestao);
// VERIFICA SE A LISTA AGORA TEM APENAS DOIS ITENS, AO INVÉS DE TRÊS
Assert.assertEquals("A lista deveria ter sido retornada com DOIS itens.", 2, novoContato.getContatoEnderecoList().size());
}
O que posso estar fazendo errado? Ou, de repente, não ter compreendido corretamente? O cascadeALL não deveria ter deletado mesmo o item?
Agradeço a qualquer boa alma que possa me ajudar nesse esclarecimento.
Abraço a todos
