2 Replies Latest reply on Jan 15, 2006 6:20 PM by Cyril JOUI

    How to implement OneToMany LAZY relationship

    pvanonselen Newbie

      How to implement OneToMany LAZY relationship

      I am getting a LazyInitializationException: no Session.

      I have read numerous forums explaining that a client application cannot use a lazy relationship. One forum suggested to use two Session methods, one to get the parent object and another to get the children.

      I have tried to implement this but I am still getting the "Session closed" exception.

      Am I doing it wrong or am I missing something else.

      PS EAGER fetching is not an option in our environment

      Here is the stackTrace:

      [java] org.hibernate.LazyInitializationException: could not initialize proxy - no Session
       [java] at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:53)
       [java] at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:98)
       [java] at org.hibernate.proxy.CGLIBLazyInitializer.intercept(CGLIBLazyInitializer.java:133)
       [java] at src.za.co.engineparts.apps.CatEJB.CoUser$$EnhancerByCGLIB$$e4cbc886.getUserName(<generated>)
       [java] at src.za.co.engineparts.apps.CatEJB.testCatBook.main(testCatBook.java:24)


      There are a few classes involved here it is.

      Here is the client application:

       InitialContext ctx = new InitialContext();
       System.out.println("Program entry point");
      
       JobCardHomeIntf jobSession = (JobCardHomeIntf) ctx.lookup(JobCardHomeIntf.class.getName());
       JobCard job = jobSession.findById(3);
      
       CoUserHomeIntf userSession = (CoUserHomeIntf) ctx.lookup(CoUserHomeIntf.class.getName());
      
       CoUser user = userSession.findByJobCardAssigned(job.getJobCardId());



      Here is the Entity beans:

      @Entity
      @Table(name="coUser"
       ,schema="dbo"
       ,catalog="EpTest"
      , uniqueConstraints = { @UniqueConstraint( columnNames = { "UserCode" } ) }
      )
      
      public class CoUser implements java.io.Serializable {
      
      
       // Fields
      
       /**
       *
       */
       private static final long serialVersionUID = 3043149347512263993L;
       private String userCode;
       private Set<src.za.co.engineparts.apps.CatEJB.JobCard> jobCardsAssignedUsers;
      
       // Constructors
      
       /** default constructor */
       public CoUser() {
       }
      
       /** constructor with id */
       public CoUser(String userCode) {
       this.userCode = userCode;
       }
      
       // Property accessors
       @Id( generate=GeneratorType.NONE)
       @Column(name="UserCode", unique=true, nullable=false, insertable=true, updatable=true, length=20, precision=19, scale=2)
      
       public String getUserCode() {
       return this.userCode;
       }
      
       public void setUserCode(String userCode) {
       this.userCode = userCode;
       }
       @Column(name="UserName", unique=false, nullable=true, insertable=true, updatable=true, length=50, precision=19, scale=2)
      
       @OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.LAZY, mappedBy="assignedUser")
      
       public Set<src.za.co.engineparts.apps.CatEJB.JobCard> getJobCardsAssignedUsers() {
       return this.jobCardsAssignedUsers;
       }
      
       public void setJobCardsAssignedUsers(Set<src.za.co.engineparts.apps.CatEJB.JobCard> jobCardsAssignedUsers) {
       this.jobCardsAssignedUsers = jobCardsAssignedUsers;
       }
      
      }
      
      
      @Entity
      @Table(name="JobCard"
       ,schema="cat"
       ,catalog="EpTest"
      , uniqueConstraints = { @UniqueConstraint( columnNames = { "JobCardId" } ) }
      )
      
      public class JobCard implements java.io.Serializable {
      
       // Fields
      
       /**
       *
       */
       private Integer jobCardId;
      
       // Property accessors
       @Id( generate=GeneratorType.AUTO)
       @Column(name="JobCardId", unique=true, nullable=false, insertable=true, updatable=true, length=255, precision=19, scale=2)
      
       public Integer getJobCardId() {
       return this.jobCardId;
       }
      
       public void setJobCardId(Integer jobCardId) {
       this.jobCardId = jobCardId;
       }
      }
      


      And lastly hear is the session bean:

      @Stateless
      @Remote (JobCardHomeIntf.class)
      @Local(JobCardHomeIntfLocal.class)
      public class JobCardHome implements JobCardHomeIntf{
      
       private static final Log log = LogFactory.getLog(JobCardHome.class);
       // inject
       @PersistenceContext private EntityManager entityManager;
       @EJB private JobCardPriorityHomeIntf jobCardPriorityHome;
       @EJB private JobCardStatusHomeIntf jobCardStatusHome;
       @EJB private CoUserHomeIntf coUserHome;
       @EJB private ReviewHomeIntf reviewHome;
      
       @SuppressWarnings("unchecked")
       public Collection<JobCard> findByAssignedUserCode(String assignedUserCode) {
       log.debug("getting all JobCard instances with assignedUserCode: " + assignedUserCode);
       try {
       CoUser coUser = coUserHome.findById(assignedUserCode);
       log.debug("get successful");
       return coUser.getJobCardsAssignedUsers();
       }
       catch (RuntimeException re) {
       log.error("get failed", re);
       throw re;
       }
       }
      
      
      




        • 1. Re: How to implement OneToMany LAZY relationship
          pvanonselen Newbie

          Am I the only person with this problem?

          I am using Jboss 4.0.3SP1 and want to use lazy relationships on a ManyToOne relationship. Surely I am not the only one.

          Could anyone maybe suggest an alternative to use if using the relationship directly is not possible from within a SessionBean.

          This is the code for retrieving the relationship from the SessionBean (as sepcified above):

           CoUser coUser = coUserHome.findById(assignedUserCode);
           coUser.getJobCardsAssignedUsers();
          


          I have found a workarouond in the meantime using EJB QL doing a select with a JOIN FETCH on the ManyToOne relationship. This is not as elegant as the scenario specified above.

          Here is the code for the workaround:

           @SuppressWarnings("unchecked")
           public Collection<JobCard> findByAssignedUserCode(String assignedUserCode) {
          
           try {
           return entityManager.createQuery("select job " +
           "from JobCard as job " +
           "join fetch job.assignedUser as user " +
           "where user.userCode = :userCode ").setParameter("userCode",assignedUserCode).getResultList();
           }
           catch (RuntimeException re) {
           log.error("get failed", re);
           throw re;
           }
           }
          


          As you can see this is not as nice as the first peice of code. Any ideas, please help!!!!!