Persist and Seam Managed Lifecycle
valtoni Nov 22, 2006 10:31 AMHello!
I´m a newbie, but with some direction.
I´m trying to do persistence with EJB3 injected EntityManager by annotation @PersistenceContext, but appear witch this EntityManager close the session all time that a call is made in page, because after the first call (all good occurs), in the second call, this appear:
"org.hibernate.PersistentObjectException: detached entity passed to persist: br.com.bdh.view.seam.entity.FuncionarioEntity".
I put all code from the registration seam example and the code of EJB appear well simpler then mine.
My ejb:
import static org.jboss.seam.ScopeType.EVENT;
import java.util.List;
import javax.annotation.Resource;
import javax.ejb.Remove;
import javax.ejb.SessionContext;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.hibernate.validator.InvalidValue;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.datamodel.DataModel;
import org.jboss.seam.annotations.datamodel.DataModelSelection;
import org.jboss.seam.core.FacesMessages;
import org.jboss.seam.log.Log;
import br.com.bdh.view.seam.ejb.Funcionario;
import br.com.bdh.view.seam.entity.FuncionarioEntity;
@Stateful
@Scope(EVENT)
@Name("cadastrofuncionario")
public class FuncionarioBean
implements Funcionario {
@DataModel
private List<FuncionarioEntity> listaFuncionarios;
@In(create = true)
private FuncionarioEntity funcionario;
@Out(required = false)
@DataModelSelection
private FuncionarioEntity funcionarioDaLista;
@PersistenceContext
private EntityManager em;
@In(create=true)
private transient FacesMessages facesMessages;
@Logger
private Log log;
private boolean isExists(FuncionarioEntity funcionario) {
return em.createQuery("from FuncionarioEntity f where f.nome = :nome")
.setParameter("nome", funcionario.getNome())
.getResultList().size() > 0;
}
public String criar() {
log.info("Tentativa de input de funcionário.");
if (em.contains(funcionario)) {
facesMessages.add("O funcionário #{funcionario.nome} já está cadastrado");
return null;
}
else {
try {
log.info("Funcionário a persistir: " + funcionario);
if (isExists(funcionario)) {
facesMessages.add("Este funcionário já existe. Não pode ser cadastrado novamente");
}
else {
//funcionario = em.merge(funcionario);
em.persist(funcionario);
//em.flush();
log.info("Novo funcionário #{funcionario.nome} cadastrado com sucesso");
facesMessages.add("O funcionário #{funcionario.nome} foi cadastrado com sucesso");
}
} catch (org.hibernate.validator.InvalidStateException e) {
InvalidValue[] vals = e.getInvalidValues();
String message = "Estados inválidos: ";
for (InvalidValue val: vals) {
message += "- " + val + "\n";
}
facesMessages.add(message);
return "/cadastroFuncionario.jsp";
} catch (RuntimeException e) {
ctx.setRollbackOnly();
facesMessages.add("Erro: " + e.getMessage());
}
return "/cadastroFuncionario.jsp";
}
}
@Factory("listaFuncionarios")
public void findFuncionarios() {
listaFuncionarios = em.createQuery("from FuncionarioEntity f order by f.nome desc")
.setMaxResults(100)
.getResultList();
log.debug("Lista de funcionários obtida: " + listaFuncionarios.size());
}
@Destroy @Remove
public void destroy() {
listaFuncionarios = null;
}
}
PS.: When i remove the comment of
//funcionario = em.merge(funcionario);it´s works perfectly. But in the examples this was not necessary... I don´t know the reason!!!
PS2.: I try to do @Transient field in entity and when his trying to read field "diasTrabalhados", the error "org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: br.com.bdh.view.seam.entity.FuncionarioEntity.diasTrabalhados, no session or session was closed" appear.
The code of entity:
import static org.jboss.seam.ScopeType.SESSION;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.hibernate.validator.Length;
import org.hibernate.validator.NotNull;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
@Entity
@Name("funcionario")
@Scope(SESSION)
@Table(name = "FUNCIONARIO")
public class FuncionarioEntity implements Serializable {
private static final long serialVersionUID = -7360165347366125305L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name="IDFUNCIONARIO")
private int id;
@NotNull @Length(min=10, max=100)
private String nome;
@OneToMany(mappedBy="funcionario")
@OrderBy("data desc")
private List<DiaUtilEntity> diasTrabalhados;
@Transient
public int getHorasTrabalhadas() {
if (diasTrabalhados == null) {
return 0;
}
else {
return diasTrabalhados.size();
}
//return 0;
}
public FuncionarioEntity() {
}
public FuncionarioEntity(int id, String nome) {
this.id = id;
this.nome = nome;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public List<DiaUtilEntity> getDiasTrabalhados() {
return diasTrabalhados;
}
public void setDiasTrabalhados(List<DiaUtilEntity> diasTrabalhados) {
this.diasTrabalhados = diasTrabalhados;
}
public String toString() {
int noDiasTrabalhados = 0;
if (getDiasTrabalhados() != null) {
noDiasTrabalhados = getDiasTrabalhados().size();
}
return "Id: " + id + " nome: " + nome + " dias trabalhados: " + noDiasTrabalhados;
}
}