Stack Overflow em Português Asked by Gleison on October 14, 2020
Estou fazendo um CRUD simples, usando JSF, JPA e CDI.
Tenho duas telas:
Tenho um bean ViewScoped
para cuidar de ambas telas e passo os parâmetros de uma tela para a outra com o f:setPropertyActionListener
, tudo funciona de acordo, tanto o inserir quanto o editar.
Agora quando o bean ao validar alguma regra de negócio impede o usuário de editar (neste caso retornando null
ao action do botão), a tela volta para o usuário corrigir o dado e submeter novamente, mas quando isso acontece o meu EntityManager
já fechou, pois ele esta configurado para viver no escopo de request
(o que para o controle do banco é ótimo).
Neste momento o erro é org.hibernate.PersistentObjectException: detached entity passed to persist
.
Se o bean
não acusa erro o editar funciona, visto o EntityManager já estar aberto, pois ele foi usado para carregar o objeto que é apresentado na tela.
Mudar o escopo do EntityManager criaria o problema de ter que gerenciá-lo quando fechar e eu não quero isso.
Gostaria de saber o que posso fazer pra contornar esse problema e como voces resolvem isso.
Produtor do EntityManager
@Produces
@RequestScoped
public EntityManager createEntityManager() {
return factory.createEntityManager();
}
public void closeEntityManager(@Disposes EntityManager manager) {
manager.close();
}
Bean que cuida da tela de listar e do formulário.
@Named
@ViewScoped
public class PaisMB implements Serializable {
private static final long serialVersionUID = 1L;
@Inject
private PaisFA paisFa;
private LazyDataModel<Pais> lazyModel = null;
private Pais paisSelecionado = null;
public LazyDataModel<Pais> getLazyModel() {
if (lazyModel == null) {
lazyModel = paisFa.listaPais();
}
return lazyModel;
}
public Pais getPaisSelecionado() {
if (paisSelecionado == null) {
paisSelecionado = new Pais();
}
return paisSelecionado;
}
public void setPaisSelecionado(Pais paisSelecionado) {
this.paisSelecionado = paisSelecionado;
}
public void deletePaisSelecionado() {
try {
paisFa.deletePais(getPaisSelecionado());
JSFUtil.sendInfoMessageToUser("O país "" + getPaisSelecionado().getNome() + "" foi deletado com sucesso.");
} catch (Exception ex) {
(...)
}
}
public String salvarPaisSelecionado() {
try {
paisFa.savePais(getPaisSelecionado());
JSFUtil.sendInfoMessageToUser("O país "" + getPaisSelecionado().getNome() + "" foi salvo com sucesso.");
return "/paisLista?faces-redirect=true";
} catch (Exception ex) {
(...)
}
return null;
}
}
Item editar do na listagem de dados.
<p:menuitem value="Editar" icon="fa fa-edit" action="paisForm?faces-redirect=true&includeViewParams=true">
<f:setPropertyActionListener target="#{paisMB.paisSelecionado}" value="#{paisMB.paisSelecionado}" />
</p:menuitem>
Recebendo o parâmetro no formulário.
<f:metadata>
<f:viewParam name="pais" value="#{paisMB.paisSelecionado}" converter="#{dbEntityCO}" />
</f:metadata>
Converter
@Named("dbEntityCO")
@ApplicationScoped
public class DBEntityCO implements Converter {
@Inject
private EntityManager entityManager;
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
// aqui usa o EntityManager
(...)
return objeto;
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
(...)
return string;
}
}
Cara, aqui eu uso assim.
@ApplicationScoped
public class EntityManagerProducer {
private EntityManagerFactory factory;
public EntityManagerProducer() {
factory = Persistence.createEntityManagerFactory("Thunder");
}
@Produces
@RequestScoped
public EntityManager createEntityManager(){
return factory.createEntityManager();
}
public void closeEntityManager(@Disposes EntityManager manager){
manager.close();
}
}
Answered by Jonathan on October 14, 2020
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP