Erro ao atualizar dados com Hbernate

8 respostas
J

Pessoal,

Estou com um problema aqui, fui fazer um formulário e um action do Struts para alterar os dados dos usuarios, os dados dos usuarios que podem ser alterados sao senha e nome (login e tipo nao podem), mas asim carrego todos esses dados para dar updates no BD, o que acontece é que se coloco
session.merge
ele esta criando uma nova linda no BD e se eu colocar
session.update
nada acontece, sera que alguem pode me ajudar?

alterarUsuario.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>

<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>

    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title><bean:message key="catalogo.titulo"/></title>
        <link rel="stylesheet" href="${pageContext.request.contextPath}/css/catalogo.css" type="text/css" />
    </head>
    <body>
        <div id="topo"></div>
        <jsp:include page="../uteis/menu.jsp"></jsp:include>
        <div id="conteudo">
            <br /><br />
            <form action="${pageContext.request.contextPath}/alterarUsuario.do" method="post" name="AlterarUsuarioForm">
            <h2>Alterar Dados de Usu&aacute;rio</h2>
            <table border="0">
                <tr>
                    <td width="20">&nbsp;</td>
                    <td width="120"><label>Nome:</label></td>
                    <td width="380"><input type="text" name="nome" size="60" maxlength="60" value="${usuario.nome}" /></td>
                </tr>
                <tr>
                    <td>&nbsp;</td>
                    <td><label>Login:</label></td>
                    <td><input type="text" name="login" size="20" maxlength="20" readonly="true" value="${usuario.login}" />
                    <span id="fonte10">Login não pode ser alterado.</span></td>
                </tr>
                <tr>
                    <td>&nbsp;</td>
                    <td><label>Nova Senha:</label></td>
                    <td><input type="password" name="senha" size="21" maxlength="20" />
                    <span id="fonte10">A senha deve ser diferente de 1234.</span></td>
                </tr>
                <tr>
                    <td>&nbsp;</td>
                    <td><label>Confirme a senha:</label></td>
                    <td><input type="password" name="senha2" size="21" maxlength="20" /></td>
                </tr>
            </table>
            <input type="hidden" name="tipo" value="1" />
            <br />
            <div id="botoes">
                <html:submit><bean:message key="catalogo.botao.alterar"/></html:submit>
                <input type="button" value="Cancelar" onclick="javascript:window.location='${pageContext.request.contextPath}/'" />
            </div>
          </form>
        </div>
    </body>
</html>
AlterarUsuarioForm
package catalogo.controle.forms;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;

public class AlterarUsuarioForm extends org.apache.struts.action.ActionForm {

    private String login, nome, senha;
    private int tipo;

    public AlterarUsuarioForm() {
        super();
    }

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getSenha() {
        return senha;
    }

    public void setSenha(String senha) {
        this.senha = senha;
    }

    public int getTipo() {
        return tipo;
    }

    public void setTipo(int tipo) {
        this.tipo = tipo;
    }

    /**
     * This is the action called from the Struts framework.
     * @param mapping The ActionMapping used to select this instance.
     * @param request The HTTP Request we are processing.
     * @return
     */
    /*public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
        ActionErrors errors = new ActionErrors();
        if (getName() == null || getName().length() < 1) {
            errors.add("name", new ActionMessage("error.name.required"));
            // TODO: add 'error.name.required' key to your resources
        }
        return errors;
    }*/
}
AlterarUsuarioAction
package catalogo.controle.actions;

import catalogo.controle.forms.AlterarUsuarioForm;
import catalogo.controle.forms.CadastroUsuarioForm;
import catalogo.dao.GenericDAO;
import catalogo.modelo.Usuario;
import catalogo.util.HibernateUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.hibernate.Session;
import org.hibernate.Transaction;

public class AlterarUsuarioAction extends org.apache.struts.action.Action {
      
    private String retorno;
    
    /**
     * This is the action called from the Struts framework.
     * @param mapping The ActionMapping used to select this instance.
     * @param form The optional ActionForm bean for this request.
     * @param request The HTTP Request we are processing.
     * @param response The HTTP Response we are processing.
     * @throws java.lang.Exception
     * @return
     */
    @Override
    public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        
        AlterarUsuarioForm usuarioForm = (AlterarUsuarioForm) form;
        Usuario usuario = new Usuario();
        BeanUtils.copyProperties(usuario, usuarioForm);
        request.setAttribute("usuario", usuario);

        Session sessao = HibernateUtil.getSession();
        Transaction transacao = sessao.beginTransaction();

        GenericDAO<Usuario> dao = new GenericDAO(sessao, Usuario.class);
        //UsuarioDAO usuarioDao = new UsuarioDAO(sessao, Usuario.class);

        try
        {
            dao.Atualizar(usuario);
            transacao.commit();
            sessao.flush();
            retorno = "usuarioAlterado";
        }
        catch (Exception e) {
            System.out.println(e.getMessage());
            transacao.rollback();
            retorno = "erroAlterarUsuario";
        }
        finally {
            sessao.close();
        }
        
        return mapping.findForward(retorno);
    }
}

Pelo que parece o xml do struts esta certo, pois faz o direcionamento para a pagina de erro.
Se precisarem de mais alguma coisa, é só falar
Desde ja agradeço

8 Respostas

Jair_Rillo_Junior

É bem provavel que a sua entidade Usuario está sem o ID (primary key) na hora de fazer o merge e/ou update.
Nesse caso, o merge vai pensar que é uma entidade nova e vai fazer um INSERT, o UPDATE não vai achar o ID e por isso não irá atualizar nada.

Faz um breakpoint e verifica se o valor do ID está populado na entidade usuario

thiago.correa

Jair Rillo Junior:
É bem provavel que a sua entidade Usuario está sem o ID (primary key) na hora de fazer o merge e/ou update.
Nesse caso, o merge vai pensar que é uma entidade nova e vai fazer um INSERT, o UPDATE não vai achar o ID e por isso não irá atualizar nada.

Faz um breakpoint e verifica se o valor do ID está populado na entidade usuario

Como disse o Jair, em que momento você está passando o objeto com o Id populado para a tua camada de controle, pelo menos na página eu não vi!!

J

Estranho que antes estava funcionando o update.
A minah entidade Usuario está com o id (PK) sim, esta assim:

package catalogo.modelo;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Table;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
@Table(name = "usuario", schema = "catalogo")
public class Usuario implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "codigo", nullable = false)
    private int codigo;

    @Column(name = "login", nullable = false, length = 45)
    private String login;

    @Column(name = "senha", nullable = false, length = 45)
    private String senha;

    @Column(name = "nome", length = 45)
    private String nome;

    @Column(name = "tipo_usuario_codigo")
    private int tipo;

    public Usuario() {

    }

    public int getCodigo() {
        return codigo;
    }

    public void setCodigo(int codigo) {
        this.codigo = codigo;
    }

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getSenha() {
        return senha;
    }

    public void setSenha(String senha) {
        this.senha = senha;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public int getTipo() {
        return tipo;
    }

    public void setTipo(int tipo) {
        this.tipo = tipo;
    }

}

O erro deve esta em não passar o id do usuario na hora de atualizar, como ficaria, mais ou menos, soh um exemplo para eu ter uma ideia?

Jair_Rillo_Junior

A questão não é o atributo referente ao ID e sim o conteúdo dele.
Quando você envia o seu objeto, no caso Usuario para o em.merge ou em.update, o atributo ID deve estar com o valor correto do ID.

J

O atributo id nao esta com o valor correto mesmo nao, descobri isso agora. O estranho é que ele preenche as informações do usuario nos campos textos corretamente, mas o campo id esta zerado, por isso nao consigo atualizar os dados, como posso resolver isso?

J

Acho que descobri o que pode ser, mas nao sei como resolver.
É o seguinte, eu estou pegando somente o login e senha do usuario, pois o que eu estou fazendo é verificar o login e a senha e se a senha estiver padrao (1234) eu mando para a pagina de alteração de dados, com isso eu só consigo ter acesso a login e senha, o atributo codigo, tipo e nome do usuario não sao carregados, como posso mudar isso, tentei fazer uns metodos aki no meu dao para trazer esses dados, mas nao funcionou.

LoginForm
package catalogo.controle.forms;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;

public class LoginForm extends org.apache.struts.action.ActionForm {
    
    private String login;
    private String senha;

    public LoginForm() {
        super();
    }

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getSenha() {
        return senha;
    }

    public void setSenha(String senha) {
        this.senha = senha;
    }

    /**
     * This is the action called from the Struts framework.
     * @param mapping The ActionMapping used to select this instance.
     * @param request The HTTP Request we are processing.
     * @return
     */
    /*public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
        ActionErrors errors = new ActionErrors();
        if (getName() == null || getName().length() < 1) {
            errors.add("name", new ActionMessage("error.name.required"));
            // TODO: add 'error.name.required' key to your resources
        }
        return errors;
    }*/
}
LoginAction
package catalogo.controle.actions;

import catalogo.controle.forms.LoginForm;
import catalogo.dao.UsuarioDAO;
import catalogo.modelo.Usuario;
import catalogo.util.HibernateUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.hibernate.Session;

public class LoginAction extends org.apache.struts.action.Action {

    private String retorno;
    private Session session = HibernateUtil.getSession();
    private UsuarioDAO dao = new UsuarioDAO(session, Usuario.class);
    /**
     * This is the action called from the Struts framework.
     * @param mapping The ActionMapping used to select this instance.
     * @param form The optional ActionForm bean for this request.
     * @param request The HTTP Request we are processing.
     * @param response The HTTP Response we are processing.
     * @throws java.lang.Exception
     * @return
     */
    @Override
    public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {

        LoginForm loginForm = (LoginForm) form;
        Usuario usuario = new Usuario();
        BeanUtils.copyProperties(usuario, loginForm);
        request.setAttribute("usuario", usuario);

        String login = loginForm.getLogin();
        String senha = loginForm.getSenha();
    
        try
        {
          if (dao.ValidarLogin(login, senha))
          {
            if (dao.VerificarSenha(login, senha))
            {
                retorno = "mudarSenha";
            }
            else
            {
                retorno = "logado";
            }
          }
          else
          {
            retorno = "erroLogin";
          }
          session.flush();
        }
        catch (Exception e)
        {
            System.out.println(e.getMessage());
            retorno = "erroLogin";
        }
        finally {
            session.close();
        }

        return mapping.findForward(retorno);
    }
}

Quando o struts encontra "mudarSenha" ele redireciona para uma pagina de alteração de dados, nessa pagina eu nao consigo acessar o codigo do usuario, apenas login e senha, deu para entender?

Jair_Rillo_Junior

Existem N maneiras de armazenar o ID.

  • Deixar o ID na sessão
  • Deixar o objeto na sessão. Pega os valores alterados pelo form, recupera o objeto da sessão, atualiza os valores e depois chama a camaa de negocio
  • Deixa o ID no form mas em um campo hidden

O importante é seu objeto chegar completo na hora do Merge, senão não apenas o login e senha serão alterados, mas sim os outros valores também

J

Consegui resolver o problema
Fiz o seguinte?
No action do login, onde valido o mesmo no BD, como eu soh tenho o login e a senha, nesse action eu recupero através de uma dao os outros dados do usuario que me sao necessarios através do login q eu tenho, depois eu passo tudo para o outro dao pra atualizar o usuario
Valeu pela ajuda pessoal

Criado 2 de março de 2010
Ultima resposta 3 de mar. de 2010
Respostas 8
Participantes 3