Hibernate EntityManager Update não funcionando

Bom dia amigos,
Estou estudando java e hibernate, e agora me bati com um problema…
se os senhores dispuserem de algum tempo, e puderem da uma olhada no meu código, explico abaixo o que está acontecendo:

Este é meu método na classe UsersDAO:

public void update(Users u) {
    try {
        em.getTransaction().begin();
        em.merge(u);
        em.getTransaction().commit();
    } catch (Exception e) {
        em.getTransaction().rollback();
        e.printStackTrace();
    }
}

E este meu update do meu bean que vai chamar o update do meu DAO

public void update(RowEditEvent event) {
		users = (Users) event.getObject();
		try {
			dao = new UsersDAO();
			users = dao.getById(((Users) event.getObject()).getIdusers());
			users.setSenha(convertStringToMd5(users.getSenha())); //Converter a senha para md5
			dao.update(users);
			saveMessage();
		}catch (Exception e){
			e.printStackTrace();
		}
	}

Quando atualizo minha datatable, tenho a seguinte resposta no console:
Hibernate:

update
    users 
set
    cargo=?,
    data_criacao=?,
    email=?,
    login=?,
    nome=?,
    phone=?,
    senha=? 
where
    idusers=?

o problema é, nada acontece… o item não é atualizado. Alguma luz para o novato em java?

A configuração da JPA está como RESOURCE_LOCAL mesmo?

De qualquer forma, testa assim para ver se funciona:

// inicia transação
Users users = em.merge(u);
users.setSenha(convertStringToMd5(users.getSenha()));
// commit
1 curtida

Sim, está RESOURCE_LOCAL no meu persistence.xml
e está funcionando normal o save e tudo, somente no update que não está acontecendo nada.

Testei sua solução e não mudou nada por hora :frowning:

Posta a classe Users e a declaração da entityManager

1 curtida

Fala mike… segue,
a declaração da Em:

public class UsersDAO {
    private EntityManagerFactory emf;
    private EntityManager em;
    private static UsersDAO instance;

    public static UsersDAO getInstance() {
        if(instance == null)
            instance = new UsersDAO();
        return instance;
    }

    public UsersDAO() {
        em = getEntityManager();
    }

    private EntityManager getEntityManager() {
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("databasejambu");
        if(em == null) {
            em = factory.createEntityManager();
        } return em;
    }

minha classe Users:

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

/**
 *
 * @author ength
 */
@Entity
@Table(name = "users")
@XmlRootElement
@NamedQueries({
   @NamedQuery(name = "Users.findAll", query = "SELECT u FROM Users u"),
   @NamedQuery(name = "Users.findByIdusers", query = "SELECT u FROM Users u WHERE u.idusers = :idusers"),
   @NamedQuery(name = "Users.findByCargo", query = "SELECT u FROM Users u WHERE u.cargo = :cargo"),
   @NamedQuery(name = "Users.findByNome", query = "SELECT u FROM Users u WHERE u.nome = :nome"),
   @NamedQuery(name = "Users.findByEmail", query = "SELECT u FROM Users u WHERE u.email = :email"),
   @NamedQuery(name = "Users.findByPhone", query = "SELECT u FROM Users u WHERE u.phone = :phone"),
   @NamedQuery(name = "Users.findByLogin", query = "SELECT u FROM Users u WHERE u.login = :login"),
   @NamedQuery(name = "Users.findBySenha", query = "SELECT u FROM Users u WHERE u.senha = :senha"),
   @NamedQuery(name = "Users.findByDataCriacao", query = "SELECT u FROM Users u WHERE u.dataCriacao = :dataCriacao")})
public class Users implements Serializable {

   private static final long serialVersionUID = 1L;
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Basic(optional = false)
   @Column(name = "idusers")
   private Integer idusers;
   @Basic(optional = false)
   @Column(name = "cargo")
   @Enumerated(EnumType.STRING)
   private Cargo cargo;
   @Basic(optional = false)
   @Column(name = "nome")
   private String nome;
   @Column(name = "email")
   private String email;
   @Column(name = "phone")
   private String phone;
   @Basic(optional = false)
   @Column(name = "login",  unique=true)
   private String login;
   @Basic(optional = false)
   @Column(name = "senha")
   private String senha;
   @Column(name = "data_criacao")
   @Temporal(TemporalType.TIMESTAMP)
   private Date dataCriacao;
   @OneToMany(mappedBy = "idusers")
   private List<Sale> saleList;

   public Users() {
   }

   public Users(Integer idusers) {
      this.idusers = idusers;
   }

   public Users(Integer idusers, Cargo cargo, String nome, String login, String senha) {
      this.idusers = idusers;
      this.cargo = cargo;
      this.nome = nome;
      this.login = login;
      this.senha = senha;
   }
//setters e getters + equals e hash

Mano, se vc recuperar a entidade usando o método find da entityManager e alterar o atributo desejado dentro de uma transação e realizar o commit, o dado será alterado no banco de dados sem problemas. Desse jeito, nem precisa usar o método merge.

O merge seria necessário se a instância da entidade estivesse detached, mas vc está recuperando ela do banco no momento da alteração, com isso, ela ainda estará managed.

2 curtidas

você pode me mostrar um exemplo?
tentei assim:
no meu dao:

public void update(Users u) {
    try {
        em.getTransaction().begin();
        em.find(Users.class, u.getIdusers());
        //em.merge(u);
        em.getTransaction().commit();
    } catch (Exception e) {
        em.getTransaction().rollback();
        e.printStackTrace();
    }
}

no meu bean:

public void update(RowEditEvent event) {
		users = (Users) event.getObject();
		try {
			dao = new UsersDAO();
			users = dao.getById(((Users) event.getObject()).getIdusers());

			users.setNome(((Users) event.getObject()).getNome());
			users.setLogin(((Users) event.getObject()).getLogin());
			users.setSenha(convertStringToMd5(users.getSenha())); //Converter a senha para md5
			dao.update(users);
		}catch (Exception e){
			e.printStackTrace();
		}
	}

settei os novos valores recebido pelo evento, e chamei o update do dao

public void converterSenhaParaMD5(Users user) {
	try {
		em.getTransaction().begin();
		Users users = em.find(Users.class, u.getIdusers());
		users.setSenha(convertStringToMd5(users.getSenha()));
		em.getTransaction().commit();
	} catch (Exception e) {
		em.getTransaction().rollback();
		e.printStackTrace();
	}
}

Algumas considerações:

  • O nome da classe deveria ser User em vez de Users, pois a definição de classe, nesse caso, representa um usuário e não um conjunto de usuários. Para um conjunto de usuários, usaria-se List<User> users;
  • Pelo que entendi, o seu update irá apenas pegar a senha atual do User e converter para MD5. Se for isso mesmo, você poderia manter um método dentro da própria classe User para fazer isso, dando mais responsabilidade para a classe em vez de apenas trafegar dados do banco;
  • Essa parte: u.getIdusers(), poderia ser apenas u.getId(), pois o nome da classe já indica que se trata de um User.