Olá pessoal.
Estou com um problema em um projeto que estou desenvolvendo, utilizando JSF, Hibernate e Spring.
Primeiro caso: Em uma tela de cadastro de usuários está acontecendo um comportamento estranho, onde ao executar o sistema pela primeira vez e cadastrar um usuário, ocorre tudo ok. Mas se eu tentar cadastrar outro logo em seguida, ele pega as permissões que atribui no primeiro usuário e exclui, passando-as para o usuário cadastrado depois.
Fiz um teste colocando para verificar se os usuários estavam entrando no método save com um código atribuído e constatei que sim, e o normal seria que estivesse null ou 0;
Segundo caso: Se eu for na tela que tem um datatable com a listagem de usuários e selecionar um para alterar, ele altera normalmente, porém, logo após esta operação, eu tentar salvar um novo usuário, ele pega o código do usuário alterado e acontece o problema do primeiro caso.
Fazendo uns testes aqui, notei que o model não está sendo atualizado, ficando sempre o ultimo model manipulado.
Verifiquei as configurações de transação do hibernate (que estão sendo tratadas pelo spring) aparentemente estão normais. O mesmo está acontecendo com uma tela de cadastro de Denuncias, também após cadastrar uma denuncia ou atualizar uma já existente, ou tentar cadastrar uma nova denuncia, ele pega o código e tenta fazer um update, enquanto o comando era para salvar.
Segue abaixo o código:
ApplicationContext.xml
<?xml version='1.0' encoding='UTF-8'?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Scan dos pacotes para injection AutoWired-->
<context:annotation-config />
<context:component-scan base-package="br.com.webdenuncias.bean"/>
<context:component-scan base-package="br.com.webdenuncias.dao"/>
<context:component-scan base-package="br.com.webdenuncias.service"/>
<context:component-scan base-package="br.com.webdenuncias.model"/>
<!-- Hibernate Configuration -->
<!-- DataSource Declaration MYSQL -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/web_denuncias" />
<property name="username" value="root" />
<property name="password" value="123456" />
</bean>
<!-- Session Factory Declaration -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="br.com.webdenuncias.model" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</prop>
<!-- <prop key="hibernate.hbm2ddl.auto">update</prop> -->
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- Transaction Manager is defined -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- Enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
Managed Bean
package br.com.webdenuncias.bean;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import org.primefaces.event.SelectEvent;
import org.primefaces.event.UnselectEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import br.com.webdenuncias.model.Usuario;
import br.com.webdenuncias.service.IUsuarioService;
@Controller
@ManagedBean(name="usuarioMB")
@RequestScoped
public class UsuarioMB implements Serializable{
private static final long serialVersionUID = -7741113640481635410L;
@Autowired
private IUsuarioService usuarioService;
@Autowired
private Usuario usuario;
private List<Usuario> usuarioList;
private String confirmaSenha;
public String addUsuario() {
String userSenha = this.getUsuario().getSenha();
FacesMessage msg;
if (userSenha.equals(this.getConfirmaSenha()) && (this.getUsuario() != null)) {
getUsuarioService().salvar(this.getUsuario());
return "usuariof";
} else {
msg = new FacesMessage("Senha confirmada não confere. Ou usuário inválido");
FacesContext.getCurrentInstance().addMessage(getUsuario().getNome(), msg);
return "usuariof";
}
}
public String removeUsuario(){
getUsuarioService().deletar(this.getUsuario());
return "listausuario?faces-redirect=true";
}
public void onRowSelect(SelectEvent event){
FacesMessage msg = new FacesMessage("Pessoa Selecionada: ",
((Usuario) event.getObject()).getNome() + "\n Login:" + ((Usuario) event.getObject()).getLogin());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public void onRowUnselect(UnselectEvent event) {
FacesMessage msg = new FacesMessage("Car Unselected", ((Usuario) event.getObject()).getLogin());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public String selecionaUsuario(){
return "usuariof.jsf?faces-redirect=true";
}
public String atualizaUsuario(){
getUsuarioService().atualizar(getUsuario());
return "listausuario?faces-redirect=true";
}
public IUsuarioService getUsuarioService() {
return usuarioService;
}
public void setUsuarioService(IUsuarioService usuarioService) {
this.usuarioService = usuarioService;
}
public Usuario getUsuario() {
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
public List<Usuario> getUsuarioList() {
this.usuarioList = new ArrayList<Usuario>();
usuarioList.addAll(this.getUsuarioService().listaUsuario());
return usuarioList;
}
public String atribuiPermissoes(Usuario usuario, String permissao){
this.usuario = usuario;
Set<String> permissoes = this.usuario.getPermissao();
if(permissoes.contains(permissao)){
permissoes.remove(permissao);
atualizaUsuario();
}else {
this.usuario.getPermissao().add(permissao);
atualizaUsuario();
}
return null;
}
public String buscarPorId() {
usuario = getUsuarioService().getById(usuario.getCodigo(), getUsuario());
usuario.getLogin();
return "usuariolista";
}
public String getConfirmaSenha() {
return confirmaSenha;
}
public void setConfirmaSenha(String confirmaSenha) {
this.confirmaSenha = confirmaSenha;
}
}
Model
package br.com.webdenuncias.model;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.hibernate.annotations.NaturalId;
import org.springframework.stereotype.Component;
@Component(value="usuario")
@Entity
@Table(name="usuario")
public class Usuario implements Serializable{
private static final long serialVersionUID = -9135278507458400645L;
@Id
@GeneratedValue
@Column(name="codigo")
private Integer codigo;
@Column(name="nome")
private String nome;
@Column(name="login")
@NaturalId
private String login;
@Column(name="senha")
private String senha;
@Column(name="ativo")
private boolean ativo;
@ElementCollection(targetClass=String.class, fetch=FetchType.EAGER)
@JoinTable(
name="permissao_usuario",
uniqueConstraints= {@UniqueConstraint(columnNames= {"usuario", "permissao"})},
joinColumns = @JoinColumn(name="usuario"))
@Column(name = "permissao", length=50)
private Set<String> permissao = new HashSet<String>();
public Integer getCodigo() {
return codigo;
}
public void setCodigo(Integer codigo) {
this.codigo = codigo;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
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 boolean isAtivo() {
return ativo;
}
public void setAtivo(boolean ativo) {
this.ativo = ativo;
}
public Set<String> getPermissao() {
return permissao;
}
public void setPermissao(Set<String> permissao) {
this.permissao = permissao;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (ativo ? 1231 : 1237);
result = prime * result + ((codigo == null) ? 0 : codigo.hashCode());
result = prime * result + ((login == null) ? 0 : login.hashCode());
result = prime * result + ((nome == null) ? 0 : nome.hashCode());
result = prime * result
+ ((permissao == null) ? 0 : permissao.hashCode());
result = prime * result + ((senha == null) ? 0 : senha.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Usuario))
return false;
Usuario other = (Usuario) obj;
if (ativo != other.ativo)
return false;
if (codigo == null) {
if (other.codigo != null)
return false;
} else if (!codigo.equals(other.codigo))
return false;
if (login == null) {
if (other.login != null)
return false;
} else if (!login.equals(other.login))
return false;
if (nome == null) {
if (other.nome != null)
return false;
} else if (!nome.equals(other.nome))
return false;
if (permissao == null) {
if (other.permissao != null)
return false;
} else if (!permissao.equals(other.permissao))
return false;
if (senha == null) {
if (other.senha != null)
return false;
} else if (!senha.equals(other.senha))
return false;
return true;
}
}
Generic DAO
package br.com.webdenuncias.dao;
import java.util.List;
import javax.annotation.Resource;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
public class GenericDaoHibernate<T> implements IGenericDao<T> {
@Resource(name = "sessionFactory")
protected SessionFactory sessionFactory;
private final Class<T> objectClass;
public GenericDaoHibernate(Class<T> objectClass) {
this.objectClass = objectClass;
}
public Class<T> getObjectClass() {
return objectClass;
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void save(T entity) {
getSessionFactory().getCurrentSession().merge(entity);
}
public void update(T entity) {
getSessionFactory().getCurrentSession().update(entity);
}
public void delete(T entity) {
getSessionFactory().getCurrentSession().delete(entity);
}
@SuppressWarnings("unchecked")
@Override
public List<T> listAll() {
List<T> lista = getSessionFactory().getCurrentSession()
.createCriteria(getObjectClass()).list();
return lista;
}
@SuppressWarnings("unchecked")
@Override
public T getById(int id, T i) {
Query query = getSessionFactory().getCurrentSession().createQuery("from T where codigo = :id");
query.setInteger("id", id);
return (T) query.uniqueResult();
}
}
DAO implementação:
package br.com.webdenuncias.dao;
import org.hibernate.Query;
import org.springframework.stereotype.Repository;
import br.com.webdenuncias.model.Usuario;
@Repository
public class UsuarioDao extends GenericDaoHibernate<Usuario> implements IUsuarioDao {
public UsuarioDao() {
super(Usuario.class);
}
@Override
public Usuario getByLogin(String login) {
Query query = null;
query = getSessionFactory()
.getCurrentSession().createQuery("from Usuario u "
+ "where u.login = :login");
query.setString("login", login);
return (Usuario) query.uniqueResult();
}
@Override
public Usuario carregerUsuario(Integer codigo) {
return (Usuario) getSessionFactory().getCurrentSession().get(Usuario.class, codigo);
}
}
Service:
package br.com.webdenuncias.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import br.com.webdenuncias.dao.IUsuarioDao;
import br.com.webdenuncias.model.Usuario;
@Service
@Transactional(readOnly=true)
public class UsuarioService implements IUsuarioService {
@Autowired
private IUsuarioDao usuarioDao;
@Override
@Transactional(readOnly=false)
public void salvar(Usuario usuario) {
Integer codigo = usuario.getCodigo();
if(codigo == null || codigo == 0){
usuario.getPermissao().add("ROLE_USUARIO");
getUsuarioDao().save(usuario);
System.out.println("Salvou :)");
}else{
System.out.println("Atualizou :(");
getUsuarioDao().update(usuario);
}
}
@Override
@Transactional(readOnly=false)
public void atualizar(Usuario usuario) {
getUsuarioDao().update(usuario);
}
@Override
@Transactional(readOnly=false)
public void deletar(Usuario usuario) {
getUsuarioDao().delete(usuario);
}
@Override
public List<Usuario> listaUsuario() {
return getUsuarioDao().listAll();
}
@Override
public Usuario getById(int codigo, Usuario usuario) {
return (Usuario) getUsuarioDao().getById(codigo, usuario);
}
@Override
public Usuario getByLogin(String login) {
return getUsuarioDao().getByLogin(login);
}
public IUsuarioDao getUsuarioDao() {
return usuarioDao;
}
@Transactional(readOnly=false)
public void setUsuarioDao(IUsuarioDao usuarioDao) {
this.usuarioDao = usuarioDao;
}
@Override
public Usuario carregerUsuario(Integer codigo) {
return getUsuarioDao().carregerUsuario(codigo);
}
}
Desde já agradeço a ajuda.