Remove Dinâmico JPA - Resolvido

Bom dia a todos,

Eu tenho a seguinte tabela:

TABELA : ASUSUARIO
ATRIBUTO: ID_USUARIO varchar2(10)
ATRIBUTO: NOME varchar2(10)

Sabemos que para a exclusão de registros usando JPA devemos sempre passar o ID da Entity como mostra o modelo abaixo:

 public boolean remove(Class pClassObj, long pId) {
        try {
            em = FactoryConnection.getEntityManager();
            em.getTransaction().begin();
            em.remove(em.find(pClassObj, pId));
            em.getTransaction().commit();
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        } finally {
            FactoryConnection.closeEm();
        }
    }

O método acima ( E que funciona ) é chamado da seguinte forma:

   
   // Instancio o usuario com o id teste 
    AsUsuario usuario = buscaUsuario("teste");
   

  // Agora vou remover o danado.
  dao.remove(usuario.getClass(),usuario.getIdUsuario);


Notem que mesmo o meu id sendo uma String o metódo funciona perfeitamente. Exclui o registro do banco. Bom, gostaria de tornar isso mais dinamico e não sei se isso é possivel e por isso criei este post. Gostaria de fazer algo do tipo:

 public boolean remove(Object obj) {
        try {
            em = FactoryConnection.getEntityManager();
            em.getTransaction().begin();
            
            em.remove(em.find(obj.getClass(), obj.getClass().getId)); //<- Tentativa 1 - Não existe isso rs
            em.remove(obj.getClass());  // <- Tentativa 2 - Não funciona .. disse que eu tenho que passar um ID
            em.remove(em.find(obj.getClass(),19L)); //  <- Tentativa 3 - Funciona, mas disse que o ID recebido foi uma String e o esperado é um long
          
            em.getTransaction().commit();
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        } finally {
            FactoryConnection.closeEm();
        }
    }

Em resumo, gostaria de passar para o metodo remove um objeto já com a instancia correta e gostaria que ele pudesse excluir sem que o id fosse informado, ou então descobrir uma forma de encontrar o ID do objeto de forma dinamica. O Insert, Update já funciona… meu problema está com o delete.
O objeto a ser passado para o metodo remove seria:

String   nomeClasse    = "br.com.estudo.model.AsUsuario";
Object   objPersistir    =  Class.forName(nomeClasse).newInstance();


     iterator = listDeleted.iterator(); // Lista de Objetos AsUsuario.
     while ( iterator.hasNext()){
         objPersistir =  iterator.next();
  
         dao.remove(objPersistir);
      }

Para explicar melhor o que eu quero vamos lá:

  1. Eu tenho uma lista, esta lista poderá ser instanciada com objetos diversos. Uma hora podera ser preenchida com AsUsuario, outra hora poderá ser preenchida com GeCidade, outra hora poderá ser preenchida com GeEstado e por aí vai.

  List result              = new ArrayList();
  String objControle = "";
  1. A lista acima é instanciada após uma consulta no banco de dados e neste momento eu guardo em uma variavel o nome do objeto que está na Lista.

    result              = buscarUsuarios();
    objetoControle = "AsUsuario";
   

3 ) Tenho metodos que removem itens dessa lista, incluem itens nesta lista e removem itens nesta lista.

          Iterator iterator;
          String   nomeClasse    = "br.com.estudo.model."+objetoControle;
          Object   objPersistir  = Class.forName(nomeClasse).newInstance();
          
          iterator = result.iterator();

          while ( iterator.hasNext()){
              objPersistir =  iterator.next();
              
             // Se houve um update ou um insert eu chamo o metodo abaixo
             dao.update(objPersistir);

             // Se houve um delete eu chamo o metodo
            dao.delete( objPersistir.getClass, ???); // E é aqui que surgiu todo o problema. Como vou saber qual é o Id a ser passado ?


           }

Acho que agora ficou um pouco mais explicado.

cara eu faço assim…

public void remove(Object objeto) {
        setSession();
        session.delete(objeto);
        session.getTransaction().commit();
    }
public void setSession() {
        this.session = HibernateUtil.getSession().getCurrentSession();
        session.beginTransaction();
    }

Você está usando Hibernate e eu estou usando JPA. Sera que é aí que tem a diferença hein ? Eu tentei fazer assim, só passando o objeto, mas ele dá um erro. Ele diz que eu preciso informar a PK e tals.

:frowning:

atah, me desculpe, achei que estivesse usando Hibernate, porque o JPA é inspirado no hibernate, então achei que também dava para fazer desse jeito para o seu caso…

Só complementando o que mauricionarcizo falou, no Objeto Session já existe um método delete o qual recebe por parametro um objeto que sendo mapeado é feta a exclusão “automatica” sem a necessidade de informar tabela, como sua lista vai ser populada a partir de uma consulta ao banco ela já vai estar com o id, e caso você insira um objeto no banco ele vai receber o id, dessa forma o metodo remove a partir do mapeamento da classe já saberá qual o id do objeto e sua tabela e irá remove-ló do banco.

existe diferença entre hibernate e JPA? Tipo existe uma outra implementação do JPA que é diferente do hibernate?

Já tentou utilizar o metodo remove do EntityManager?!

Sim. JPA é apenas a especificação, Hibernate a implementação.

O Hibernate implementou a especificação JPA e também tem seu próprio modo de funcionar.

Existe o EclipseLink (TopLink), por exemplo, como implementação do JPA.

Sim. JPA é apenas a especificação, Hibernate a implementação.

O Hibernate implementou a especificação JPA e também tem seu próprio modo de funcionar.

Existe o EclipseLink (TopLink), por exemplo, como implementação do JPA.[/quote]
Bah, valeu!

Matou uma dúvida minha!

Eu uso uma interface para minhas entidades, dessa forma posso receber o objeto para deletar baseado nela.

interface Entidade<ID extends Serializable> { ID getId(); void setId(ID id); }

E no método.

void remover(Entidade e) { if((e == null) || (e.getId() == null)) { // Dispara um erro } Entidade entidade = em.find(e.getClass(), e.getId()); em.remove(entidade); }

Removi o Id do metodo e passei apenas o objeto como mostra abaixo

public boolean delete(Object obj,String metodoId) {
 
        try {
            em = FactoryConnection.getEntityManager();
            em.getTransaction().begin();
            em.remove(obj);
            //  em.remove(em.find(obj.getClass(), metodoId));
            em.getTransaction().commit();
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        } finally {
            FactoryConnection.closeEm();
        }
    }

O erro é este

Vou tentar algo com a interface… Não é possivel que nao tem um jeito de fazer isso … Jesus Amado rs.
Abraços

PQ vc não faz oq a mensagem do erro sugeriu?

br.com.nuwe.websis.model.AsUsuario@ac2f9b, try merging the detached and try the remove again.

Acabei de fazer.
Fiz o merge e em seguida fiz o remove.

em = FactoryConnection.getEntityManager();
            em.getTransaction().begin();
            em.merge(obj);
            em.remove(obj);
            em.getTransaction().commit();

O erro continua. Onde eu estou comendo bola ?

O erro continua o mesmo?

Sua entidade tem algum relacionamento? OneToOne, OneToMane… e assim vai?

Pode ser um desses caras que está te travando.

Tem nada :frowning:

É uma entidade simples… simples… simples… Engraçado que o insert e o update funciona. Achei que o delete iria funcionar tb

@Entity
@Table(name = "ASUSUARIO")
@NamedQueries({@NamedQuery(name = "AsUsuario.searchAll"         , query = "SELECT a FROM AsUsuario a"),
               @NamedQuery(name = "AsUsuario.searchById"        , query = "SELECT a FROM AsUsuario a WHERE a.idUsuario = ?1")
})
public class AsUsuario implements Serializable {
    
    
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "ID_USUARIO")
    private String idUsuario;
    
    @Basic(optional = false)
    @Column(name = "SENHA")
    private String senha;
    
    @Basic(optional = false)
    @Column(name = "NOME")
    private String nome;
    
    @Basic(optional = false)
    @Column(name = "FG_ATIVO")
    private String fgAtivo;

   

    /**
     * @return the senha
     */
    public String getSenha() {
        return senha;
    }

    /**
     * @param senha the senha to set
     */
    public void setSenha(String senha) {
        this.senha = senha;
    }

    /**
     * @return the nome
     */
    public String getNome() {
        return nome;
    }

    /**
     * @param nome the nome to set
     */
    public void setNome(String nome) {
        this.nome = nome;
    }

    /**
     * @return the fgAtivo
     */
    public String getFgAtivo() {
        return fgAtivo;
    }

    /**
     * @param fgAtivo the fgAtivo to set
     */
    public void setFgAtivo(String fgAtivo) {
        this.fgAtivo = fgAtivo;
    }

    /**
     * @return the idUsuario
     */
    public String getIdUsuario() {
        return idUsuario;
    }

    /**
     * @param idUsuario the idUsuario to set
     */
    public void setIdUsuario(String idUsuario) {
        this.idUsuario = idUsuario;
    }
    
}
  1. Vc não precisa do “implements Serializable” para uma entidade simples.
  2. Tenta implementar o equals/hashcode

Sim, você tem razão. Não precisaria.

Implementei … veja:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.nuwe.websis.model;

import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

/**
 *
 * @author Lbertanholi
 */
@Entity
@Table(name = "ASUSUARIO")
@NamedQueries({@NamedQuery(name = "AsUsuario.searchAll"         , query = "SELECT a FROM AsUsuario a"),
               @NamedQuery(name = "AsUsuario.searchById"        , query = "SELECT a FROM AsUsuario a WHERE a.idUsuario = ?1")
})
public class AsUsuario implements Serializable  {
    
    
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "ID_USUARIO")
    private String idUsuario;
    
    @Basic(optional = false)
    @Column(name = "SENHA")
    private String senha;
    
    @Basic(optional = false)
    @Column(name = "NOME")
    private String nome;
    
    @Basic(optional = false)
    @Column(name = "FG_ATIVO")
    private String fgAtivo;

   

    /**
     * @return the senha
     */
    public String getSenha() {
        return senha;
    }

    /**
     * @param senha the senha to set
     */
    public void setSenha(String senha) {
        this.senha = senha;
    }

    /**
     * @return the nome
     */
    public String getNome() {
        return nome;
    }

    /**
     * @param nome the nome to set
     */
    public void setNome(String nome) {
        this.nome = nome;
    }

    /**
     * @return the fgAtivo
     */
    public String getFgAtivo() {
        return fgAtivo;
    }

    /**
     * @param fgAtivo the fgAtivo to set
     */
    public void setFgAtivo(String fgAtivo) {
        this.fgAtivo = fgAtivo;
    }

    /**
     * @return the idUsuario
     */
    public String getIdUsuario() {
        return idUsuario;
    }

    /**
     * @param idUsuario the idUsuario to set
     */
    public void setIdUsuario(String idUsuario) {
        this.idUsuario = idUsuario;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final AsUsuario other = (AsUsuario) obj;
        if ((this.idUsuario == null) ? (other.idUsuario != null) : !this.idUsuario.equals(other.idUsuario)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 79 * hash + (this.idUsuario != null ? this.idUsuario.hashCode() : 0);
        return hash;
    }
    
    
   
    
    
    
}

O Dao esta assim:

public boolean delete(Object obj,String metodoId) {
 
        try {
            em = FactoryConnection.getEntityManager();
            em.getTransaction().begin();
            em.merge(obj);
            em.remove(obj);
            //  em.remove(em.find(obj.getClass(), metodoId));
            em.getTransaction().commit();
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        } finally {
            FactoryConnection.closeEm();
        }
    }

E o erro está assim rsrs:

Dureza né ? Pensei em uma gambi aqui. Gravar o metodo que representa a chave composta em uma variavel e executar este metodo dinamicamente para a exclusão. Mas é fods né ? Queria um jeito certo de fazer, ficaria mais bonito.

Faz um teste. Ao invés de fazer um em.remove(obj); faz em cima da sua classe.

[code]AsUsuario asUsuario = (AsUsuario) obj;

em.remove(asUsuario )[/code]

Ele diz a mesma coisa. Pra fazer o merge e tals. Se eu não passo o ID não funciona.