RESOLVIDO ! - Hibernate cria novo dado ao atualizar

E ae pessoal, tudo certo, gostaria de saber se voces podem me ajudar,

Eu estou fazendo um projeto de controle de estoque, ´só que esta acontecendo o seguinte, existe o metodo armazenar, que serve pra atualizar os dados , só que quando eu armazeno, ele nao atualiza os dados, ele cria outro registro com os dados que eu alterei.
Pensei que fosse o GenerationType.SEQUENCE, mas comentei e mesmo assim continua do mesmo jeito …

segue em exemplo abaixo

tenho a classe produto

@Entity
public class Produto implements Serializable {

    @Id
    @GeneratedValue//(strategy = GenerationType.SEQUENCE)
    @Column(name="id_produto")
    private Long id;

    @Column(name="nome_produto")

    private String nome;

    @Column(nullable=false)
    private String modelo;

    private double vlvenda;

    private double vlcompra;

   @Temporal(javax.persistence.TemporalType.DATE)
   private Date data;

    
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name="id_categoria",
     insertable=true, updatable=true)
    @Fetch(FetchMode.JOIN)
   @Cascade(CascadeType.ALL)
    private Categoria categoria;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name="id_fornecedor",
    insertable=true, updatable=true)
    @Fetch(FetchMode.JOIN)
    @Cascade(CascadeType.ALL)
    private Fornecedor fornecedor;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name="id_marca",
     insertable=true, updatable=true)
    @Fetch(FetchMode.JOIN)
    @Cascade(CascadeType.ALL)
    private Marca marca;

    @Column(unique=false, nullable=false)
    private String status;

//getters e setters

O meu armazena da classe ProdutoLogic é esse

public void armazena(Produto produto) {
        this.daoFactory.beginTransaction();
        this.daoFactory.getProdutoDao().atualiza(produto);
        this.daoFactory.commit();
    }

O meu dao é segue o modelo da loja virtual

    public void atualiza(T u) {
        this.session.merge(u);
    }

O que eu estou fazendo de errado ? como eu posso resolver este problema.

muito obrigado galera

Verifique se o Id do Produto não está nulo ao chamar o método armazenar

O objeto pode estar no modo de detached. Aí o merge vai persistir mesmo. Se for esse o caso, tenta fazer o seguinte (pra atualizar):

Objeto o = em.merge(o);
// Modificacoes no "o"
em.merge(o);

Você muda o estado dele e depois atualiza ele no banco.

Entao ignacio83 , o id esta preenchido …

Andre Brito

Como eu insiro isto na logica do dao que eu estou usando … ?

pessoal, existe outra maneira de resolver este problema ?

No atualiza, tente fazer assim:

u = this.session.merge(u); // aqui é pra não inserir nada, só mudar o estado do objeto this.session.merge(u);

E ae Andre, eu coloquei esse codigo no meu dao e mesmo assim continua criando um novo dado , e nao atualiza …
existe alguma outra maneira de resolver isso ?

cara poste o codgo onde vc altera os dados do produto antes de atualizar pra mim dar uma olhada,pode ser ai que esta o problema.

vc esta usando JSF ? se for, o Bean deve estar no escopo de request. entao é so alterar no faces-config.xml para session. tb tive esse problema e foi isso.

e ae igweb, o codigo ta ai embaixo

eu estou usando o vraptor na camada de controle, o metodo que eu estou usando pra atualizar é esse


    public void armazena(Produto produto) {
         this.daoFactory.beginTransaction();
        this.daoFactory.getProdutoDao().atualiza(produto);
        this.daoFactory.commit();
    }

O form esta assim

<form action="produto.armazena.logic" method="post">

                <fieldset>
                    <legend>Produtos</legend>
                    <input type="hidden" name="produto.id" value="${produto.id}">
                     <input type="hidden" name="produto.data" value="${produto.data}">
                    <table>
                        <tr>
                            <td>Nome do Produto:</td>
                            <td>Status:</td>
                        </tr>
                        <tr>
                            <td><input maxlength="25" size="35" name="produto.nome" value="${produto.nome}"></td>
                            <td><select name="produto.status" value="${produto.status}">
                                    <option>ATIVO</option>
                                    <option>INATIVO</option>
                                </select></td>
                        </tr>
                        <tr>
                            <td>Marca:</td>
                            <td>Modelo:</td>
                        </tr>
                        <tr>
                            <td><select name="produto.marca.id" id="marca">
                                    <c:forEach var="marca" items="${listaMarcas}">
                                        <option value="${marca.id}"
                                                <c:if test="${produto.marca.id == marca.id}">selected="true"</c:if>>
                                            <c:out value="${marca.nome}"/>
                                        </option>
                                    </c:forEach>
                                </select>
                            </td>
                            <td> <input maxlength="25" size="35" name="produto.modelo" value="${produto.modelo}"></td>
                        </tr>
                        <tr>
                            <td>Valor de Venda:</td>
                            <td>Valor de Compra:</td>
                        </tr>
                        <tr>
                            <td> <input maxlength="25" size="35" name="produto.vlvenda" value="${produto.vlvenda}"></td>
                            <td> <input maxlength="25" size="35" name="produto.vlcompra" value="${produto.vlcompra}"></td>
                        </tr>
                        <tr>
                            <td>Fornecedor</td>
                        </tr>
                        <tr>
                            <td><select name="produto.fornecedor.id" id="fornecedor">
                                    <c:forEach var="fornecedor" items="${listaFornecedores}">
                                        <option value="${fornecedor.id}"
                                                <c:if test="${produto.fornecedor.id == fornecedor.id}">selected="true"</c:if>>
                                            <c:out value="${fornecedor.nome}"/>
                                        </option>
                                    </c:forEach>
                                </select>
                            </td>

                        </tr>
                        <tr>
                            <td>Categoria:</td>
                        </tr>
                        <tr>
                            <td><select name="produto.categoria.id" id="categoria">
                                    <c:forEach var="categoria" items="${listaCategorias}">
                                        <option value="${categoria.id}"
                                                <c:if test="${produto.categoria.id == categoria.id}">selected="true"</c:if>>
                                            <c:out value="${categoria.nome}"/>
                                        </option>
                                    </c:forEach>
                                </select>
                            </td>

                            </td>
                        </tr>

                    </table>
                        <tr>
                          </tr>

                    <input type="submit" value="Cadastrar"/>
                </fieldset>
            </form>

nao thimor, eu estou usando o vraptor…

Quem chama o metodo public void armazena(Produto produto) ??

Entao funciona da seguinte maneira, tem a lista de produtos, onde tem um link que redireciona para o formulario para editar .
para editar dado, é esse o metodo

na pagina de listagem, tem esse link pra editar

 <a href="produto.editar.logic?produto.id=${produto.id}">
 public void editar(Produto produto) {
// carrega os dados no banco para edicao
        this.produto = this.daoFactory.getProdutoDao().procura(produto.getId());

dai ele só manda pro jsp para ser editado, e o action do form é esse

<form action="produto.armazena.logic" method="post">   

que no controlador é esse metodo

public void armazena(Produto produto) { this.daoFactory.beginTransaction(); this.daoFactory.getProdutoDao().atualiza(produto); this.daoFactory.commit(); }

que chama o metodo atualiza do dao

  public void atualiza(T u) {
      this.session.merge(u);

entaum cara , nunca utilizei VRaptor mas me parece que esta td correto com seus metodos,so se certifique que em nenhum lugar do seu codigo vc esteja usando um new Produto() ,pois esta e uma das causas destes tipos de erro, se vc esta com o id preenchido antes de salvar dentro do metodo armazena ele deveria somente atualizar ,verifique o valor do id antes de salvar e pegue o retorno do metodo merge, ele retorna um objeto,peque este objeto e verifique seu id so para confirmar, pode ser com print’s msm:


u=session.merge(u);  
System.out.Println(" "+u.getId() );

Huuuuuuuuuuum, esta dando um new produto sim…

neste trecho do codigo, na classe daofactory…

public class DaoFactory {

//fabrica de daos,
    private final Session session;
    private Transaction transaction;

    public DaoFactory() {
        session = HibernateUtil.getSession();
    }
// abre transacao
    public void beginTransaction() {
        this.transaction = this.session.beginTransaction();
    }

    public void commit() {
        this.transaction.commit();
        this.transaction = null;
    }

    public boolean hasTransaction() {
        return this.transaction != null;
    }

    public void rollback() {
        this.transaction.rollback();
        this.transaction = null;
    }

    public void close() {
        this.session.close();
    }

    public UsuarioDao getUsuarioDao() {
        return new UsuarioDao(this.session);
    }

    public ProdutoDao getProdutoDao() {
        return new ProdutoDao(this.session);
    }

entao ai que deve estar o problema … como eu poderia resolver isso?

O update não resolve?
session.update(objeto);

E ae pessoal , CONSEGUI RESOLVER O PROBLEMA !!!

eu peguei trauma desse metodo merge, eu estava atualizando na mesma pagina da edição, e nao estava fucionando com todos os toques que voces me deram, eu coloquei um SAVEORUPDATE no lugar do merge, e fiz carregar em outro formulario e FUNCIONOU !!!

valeu a ajuda de todos ,vcs sao 10!