JPA UPDATE Não exclui registros ao atualizar entidade!

Tenho uma Pessoa com uma lista de emails. Quando quero atualizar os dados da pessoa utilizo o seguinte código:

    @Override
    @SuppressWarnings("unchecked")
    public boolean update(T trasientObject, PK id) {
        EntityManager em = null;
        boolean ok = false;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Object o = em.find(trasientObject.getClass(), id);
            o = trasientObject.getClass().cast(trasientObject);
            em.merge(o);
            em.getTransaction().commit();
            ok = true;
        } catch (Exception ex) {
            throw ex;
        } finally {
            if (em != null)
                em.close();
            if (ok) {
                return true;
            } else {
                return false;
            }
        }
    }

E está funcionando tanto para os valores de pessoa como também quando adiciono mais um email na lista de emails, apenas dou update e tudo ok.
O problema está quando removo um ou mais emails da lista de emails e quero atualizar a entidade pessoa, ela atualiza os campos mas a lista de emails não! Tipo, ela atualiza o nome da pessoa se eu mudar o nome mas não remove o emails se eu remover o email dessa pessoa.
E agora? O que deve fazer? Já rodei aqui pelo fórum e não consegui nada conciso! Me ajudem! Obrigado.

  1. Você sabe para que serve todo esse código? Ainda mais essa linha: o = trasientObject.getClass().cast(trasientObject);?
  2. Você precisa remover/atualizar a lista de email da pessoa após o find, dentro da transação. Se você fizer essa alteração fora da transação e depois mandar um merge, vai acontecer isso que você falou.

Sei sim, a linha “o = trasientObject.getClass().cast(trasientObject);” é porque estou usando um DAO Genérico implementado por várias classes, então como na linha que segue dou o merge(), objeto passado ao método tem que ser do tipo que eu quero atualizar, por isso faço o cast “indireto/dinâmico” vamos dizer assim. Sobre a transação dá pra ver pelo código que está dentro do escopo da sessão…

É como eu tô dizendo, quando a atualização envolve adicionar um elemento a lista, funciona; quando é pra remover, não! :roll:

Exato, pelo fato de ser o genério você precisa deixar seu objeto attached, depois alterar a lista e depois salvar.

Na boa? precisa disso tudo para ser genérico não viu. ^^

E como faço isso da melhor maneira? Já tentei dar find antes e setar os objetos mas dá no mesmo…

    public boolean editar(Pessoa pessoa) throws EntidadeNaoExistenteException, Exception {
        boolean ok = false;
        EntityManager em = null;
        GenericDAOImplement<Pessoa, Long> genericDAO = new GenericDAOImplement<Pessoa, Long>();
        try {
            em = genericDAO.getEntityManager();
            em.getTransaction().begin();
            Pessoa pessoaDoBD = em.find(pessoa.getClass(), pessoa.getId());
            System.out.println(pessoaDoBD);
            if (pessoaDoBD == null) {
                throw new EntidadeNaoExistenteException("A pessoa com id " + pessoa.getId() + " não existe mais.");
            }
            //Seta novos dados na instância gerenciada pelo EntityManager.
            pessoaDoBD.setApelido(pessoa.getApelido());
            pessoaDoBD.setCnpj(pessoa.getCnpj());
            pessoaDoBD.setCpf(pessoa.getCpf());
            pessoaDoBD.setDataDeNascimento(pessoa.getDataDeNascimento());
//Lista de emails aqui... (Estou repassando uma lista com menos elementos então deveria remover)
            pessoaDoBD.setEmails(pessoa.getEmails());
            pessoaDoBD.setEndereco(pessoa.getEndereco());
            pessoaDoBD.setId(pessoa.getId());
            pessoaDoBD.setLogin(pessoa.getLogin());
            pessoaDoBD.setNome(pessoa.getNome());
            pessoaDoBD.setPathFoto(pessoa.getPathFoto());
            pessoaDoBD.setRg(pessoa.getRg());
            pessoaDoBD.setRegras(pessoa.getRegras());
            pessoaDoBD.setSalDaSenha(pessoa.getSalDaSenha());
            pessoaDoBD.setSenha(pessoa.getSenha());
            pessoaDoBD.setSexo(pessoa.getSexo());
            pessoaDoBD.setTelefones(pessoa.getTelefones());
            pessoaDoBD.setUsuarioDoSistema(pessoa.isUsuarioDoSistema());
            if (genericDAO.update(pessoa))
                ok = true;
            em.merge(pessoa);
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            throw ex;
        } finally {
            if (em != null)
                em.close();
            if (ok)
                return true;
            else
                return false;
        }
    }

Não repara no código, é só pra testar, mas mesmo assim nada…

Eu costumo fazer o seguinte.

Vamos supor q eu queria adicionar um email na pessoa:[code]// pessoaId ou então o objeto pessoa, você quem escolhe
public void adicionarEmail(int pessoaId, Email email){
// inicia transação e outras cofingurações
Pessoa pessoa = em.find(Pessoa.class, pessoaId);

//uso apenas caso o cascade não esteja persist
em.persist(email);

pessoa.getEmails().add(email);
em.merge(pessoa);
// commit e tals

}[/code]Repare que em nenhum momento eu passo uma nova coleção de objetos. O email passado também deve estar “attached” à transação.
Para excluir um email, você teria que fazer pessoas.setEmail(null); Mas antes do delete salvava os emails e após o delete apagava um por um.

Ou então fazia um bulk delete.