Lazy loading problem
maykell.mflores.uci.cu Sep 1, 2008 10:29 PMHi all, i have a problema with lazy loading i think.
I have an ordinary entity that have a collection of items, the getItems() method is annotated with fetchType.Lazy, the problem is that when i persist an item an go back to the entity detail page, and click on the tab that shows the list of items assosiated with the entity, the list is returning empty, nevertheless if i go to the menu bar(my project is a seam-gen generated one) and click on the entityList option, everything works just fine, the tab shows the collection of items without problem.
There is another clue, if i go again and add another item and go back to the entity detail page i get the tab showing the collection minus the last item that was persisted.
Somebody can explain me this behavior.
This is my code:
the entity class:
package com.prueba.domain; import java.util.ArrayList; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; import org.hibernate.validator.NotNull; import org.jboss.seam.annotations.AutoCreate; import org.jboss.seam.annotations.Name; @Name("expediente") @Entity @Table (name="EXPEDIENTE") public class Expediente { private Long id; private String nroExpediente; private List<Testigo> testigos = new ArrayList<Testigo>(); private List<Acusado> acusados = new ArrayList<Acusado>(); @OneToMany(cascade = CascadeType.ALL ,fetch = FetchType.LAZY, mappedBy="expediente") public List<Acusado> getAcusados() { return acusados; } public void setAcusados(List<Acusado> acusados) { this.acusados = acusados; } @Column (name="nroExpediente", nullable = false) @NotNull public String getNroExpediente() { return nroExpediente; } public void setNroExpediente(String nroExpediente) { this.nroExpediente = nroExpediente; } @Id @GeneratedValue public Long getId() { return id; } public void setId(Long id) { this.id = id; } @OneToMany(cascade=CascadeType.ALL,fetch = FetchType.LAZY, mappedBy = "expediente") public List<Testigo> getTestigos() { return testigos; } public void setTestigos(List<Testigo> testigoLista) { this.testigos = testigoLista; } }
The item class:
package com.prueba.domain; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.NoResultException; import javax.persistence.NonUniqueResultException; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; import org.hibernate.validator.NotNull; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; import org.jboss.seam.annotations.web.RequestParameter; @Name("acusado") @Entity @PrimaryKeyJoinColumn(name="PERSONA_ID") @Table (name="ACUSADO") public class Acusado extends Persona { private String descripcionFisica; private Expediente expediente; @ManyToOne (fetch = FetchType.LAZY) @JoinColumn(name="Expediente_ID",nullable = false) public Expediente getExpediente() { return expediente; } public void setExpediente(Expediente expediente) { this.expediente = expediente; } @Column (name="descripcionFisica", nullable = false) @NotNull public String getDescripcionFisica() { return descripcionFisica; } public void setDescripcionFisica(String descripcionFisica) { this.descripcionFisica = descripcionFisica; } }
The entityHome class:
package com.prueba.facade; import java.util.ArrayList; import java.util.List; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Begin; import org.jboss.seam.annotations.Out; import org.jboss.seam.annotations.Transactional; import org.jboss.seam.annotations.web.RequestParameter; import org.jboss.seam.framework.EntityHome; import com.prueba.domain.Acusado; import com.prueba.domain.Expediente; @Name("expedienteHome") public class ExpedienteHome extends EntityHome<Expediente> { @RequestParameter Long expedienteId; @Out List<Acusado> listaAcusados = new ArrayList<Acusado>(); @Override public Object getId() { if (expedienteId == null) { return super.getId(); } else { return expedienteId; } } @Override @Begin public void create() { super.create(); } @Transactional public List<Acusado> getAcusados() { if (getInstance() == null) return null; else { Object lista = getInstance().getAcusados(); this.listaAcusados = (List<Acusado>)lista; return (List<Acusado>)lista; } } }
The itemAction class:
package com.prueba.facade; import java.io.Serializable; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.NonUniqueResultException; import org.jboss.seam.Component; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.Begin; import org.jboss.seam.annotations.Conversational; import org.jboss.seam.annotations.FlushModeType; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Logger; import org.jboss.seam.annotations.Out; import org.jboss.seam.annotations.Scope; import org.jboss.seam.annotations.Transactional; import org.jboss.seam.annotations.web.RequestParameter; import org.jboss.seam.core.Events; import org.jboss.seam.log.Log; import org.jboss.seam.faces.FacesMessages; import com.prueba.domain.Acusado; import com.prueba.domain.Expediente; @Name("registerAcusadoAction") @Scope(ScopeType.CONVERSATION) public class RegisterAcusadoAction implements Serializable{ @Logger private Log log; @In FacesMessages facesMessages; @In private EntityManager entityManager; @RequestParameter String kaka; @RequestParameter String returnTo = "testigoList.xhtml"; String from = "/acusadoList.xhtml"; @Out(required = false) Acusado acusado; @In (create = true) ExpedienteHome expedienteHome; @Transactional @Begin(join=true) public void registerAcusado(Acusado acusadoLocal) { acusadoLocal.setExpediente(expedienteHome.getInstance()); entityManager.persist(acusadoLocal); entityManager.flush(); acusado = acusadoLocal; Events.instance().raiseTransactionSuccessEvent("EntidadCRUD","Acusado Registrado", "RegisterAcusadoAction.registerAcusado"); } public void updateAcusado(Acusado acusadoLocal) { boolean bol1 = entityManager.contains(acusadoLocal); entityManager.flush(); // Events.instance().raiseTransactionSuccessEvent("EntidadCRUD","Acusado Actualizado", "RegisterAcusadoAction.updateAcusado"); } @Transactional public void loadAcusado() { Events.instance().raiseTransactionSuccessEvent("EntidadCRUD","", "RegisterAcusadoAction.loadAcusado"); if (kaka != null ) { try { acusado = (Acusado) entityManager.find(Acusado.class, kaka); } catch (NoResultException nre) { } catch (NonUniqueResultException nure) { } }else { boolean bol1 = entityManager.contains(Component.getInstance("acusado")); if (acusado == null){ acusado = new Acusado(); log.info("El acusado vino null"); } } boolean bol = entityManager.contains(acusado); } public void verPaginaRetorno() { if (returnTo != null) from = returnTo; } public void cleanVar(String varName){ org.jboss.seam.contexts.Contexts.getConversationContext().remove(varName); } public String getReturnTo() { return returnTo; } public void setReturnTo(String returnTo) { this.returnTo = returnTo; } public String getFrom() { return from; } public void setFrom(String from) { this.from = from; } }
the entity detail page:
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:s="http://jboss.com/products/seam/taglib" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:rich="http://richfaces.org/rich" template="layout/template.xhtml"> <ui:define name="body"> <h:messages globalOnly="true" styleClass="message" /> <h:form id="expedienteForm"> <rich:panel> <f:facet name="header">expediente</f:facet> <s:decorate id="nameDecoration" template="layout/edit.xhtml"> <ui:define name="label">Numero de expediente</ui:define> <h:inputText id="nro" required="true" value="#{expedienteHome.instance.nroExpediente}" /> </s:decorate> <div style="clear: both" /> </rich:panel> <div class="actionButtons"><h:commandButton id="save" value="Salvar" action="#{expedienteHome.persist}" rendered="#{!expedienteHome.managed}" /> <h:commandButton id="update" value="Actualizar" action="#{expedienteHome.update}" rendered="#{expedienteHome.managed}" /> <h:commandButton id="delete" value="Eliminar" action="#{expedienteHome.remove}" immediate="true" rendered="#{expedienteHome.managed}" /> <s:button propagation="end" id="expedienteDone" value="Terminar" view="/expedienteList.xhtml" /></div> <rich:panel> <rich:tabPanel id="expCollections"> <rich:tab id="acusadosTab" label="Acusados"> <!-- <h:messages globalOnly="true" styleClass="message" /> --> <rich:panel> <f:facet name="header">Listado de acusados para el expediente actual</f:facet> <div class="results"><h:outputText value="No existen acusados asociados a este expediente aun" rendered="#{empty expedienteHome.getAcusados()}" /> <h:dataTable id="acusadoList" var="acusado" value="#{listaAcusados}" rendered="#{not empty listaAcusados}" cellpadding="2" rowClasses="graybg,whitebg"> <h:column> <f:facet name="header">CI</f:facet> #{acusado.ci} </h:column> <h:column> <f:facet name="header">Nombre</f:facet> <s:link id="nombreLink" value="#{acusado.nombre}" view="/registerAcusado.xhtml" propagation="join"> <f:param name="returnTo" value="/expediente.xhtml" /> </s:link> </h:column> <h:column> <f:facet name="header">Direccion</f:facet> #{acusado.direccionParticular} </h:column> <h:column> <f:facet name="header">Desc Fisica</f:facet> #{acusado.descripcionFisica} </h:column> </h:dataTable></div> </rich:panel> <div class="actionButtons"><s:button id="acusadoDone" value="Create acusado" view="/registerAcusado.xhtml"> <f:param name="returnTo" value="/expediente.xhtml" /> </s:button></div> </rich:tab> </rich:tabPanel> </rich:panel> </h:form> </ui:define> </ui:composition>