4 Replies Latest reply on Apr 25, 2006 10:16 AM by ejb3workshop

    FetchType.LAZY doesn't work

    psmith

      I have two beans A and B

      package au.com.pulse.online.persistence.ejb.crm;

      import java.util.List;

      import javax.persistence.Column;
      import javax.persistence.FetchType;
      import javax.persistence.GeneratedValue;
      import javax.persistence.GenerationType;
      import javax.persistence.Id;
      import javax.persistence.JoinColumn;
      import javax.persistence.OneToMany;
      import javax.persistence.Table;

      @javax.persistence.Entity
      @Table(name = "A")
      public class A {

      private long col1;
      private String col2;
      private String col3;
      private List bvals;

      @Id()
      @GeneratedValue( strategy=GenerationType.AUTO )
      @Column(name = "COL_1")
      public long getCol1() {
      return col1;
      }
      public void setCol1(long col1) {
      this.col1 = col1;
      }

      @Column(name = "COL_2")
      public String getCol2() {
      return col2;
      }
      public void setCol2(String col2) {
      this.col2 = col2;
      }

      @Column(name = "COL_3")
      public String getCol3() {
      return col3;
      }
      public void setCol3(String col3) {
      this.col3 = col3;
      }

      @OneToMany(fetch = FetchType.LAZY)
      @Column(name="COL_1")
      @JoinColumn(name="COL_2")
      public List getBs() {
      return bvals;
      }

      public void setBs(List bvals) {
      this.bvals = bvals;
      }
      }

      package au.com.pulse.online.persistence.ejb.crm;

      import javax.persistence.Column;
      import javax.persistence.GeneratedValue;
      import javax.persistence.GenerationType;
      import javax.persistence.Id;
      import javax.persistence.Table;

      @javax.persistence.Entity
      @Table(name = "B")
      public class B {
      private long col1;
      private long col2;
      private String col3;

      @Id()
      @GeneratedValue( strategy=GenerationType.AUTO )
      @Column(name = "COL_1")
      public long getCol1() {
      return col1;
      }
      public void setCol1(long col1) {
      this.col1 = col1;
      }

      @Column(name = "COL_2")
      public long getCol2() {
      return col2;
      }
      public void setCol2(long col2) {
      this.col2 = col2;
      }

      @Column(name = "COL_3")
      public String getCol3() {
      return col3;
      }
      public void setCol3(String col3) {
      this.col3 = col3;
      }


      }


      And a session bean that has the following method:

      @TransactionAttribute(TransactionAttributeType.REQUIRED)
      public A getA() {
      try {
      A a = (A) em.createQuery("from A where col1 = 1").getSingleResult();
      List bs = a.getBs();
      return a;
      } catch (Exception e) {
      log.info(e);
      return null;
      }
      }

      If I define the following:

      @OneToMany(fetch = FetchType.EAGER)

      then the list of B's gets populated when the query runs. If I leave it as LAZY then it never gets populated. Does anybody know what I'm missing here?

        • 1. Re: FetchType.LAZY doesn't work
          psmith

          Forgot to mention that I'm using JBoss 4.0.4RC2 with EJB3 RC6

          • 2. Re: FetchType.LAZY doesn't work
            psmith

            I don't know whether this is a bug or how it's supposed to work but the returned List appears to be empty (with lazy fetch) until you invoke some method on it eg) .size() or .get(0), whereupon the sql is invoked and the list populated. Peculiar behaviour.

            • 3. Re: FetchType.LAZY doesn't work
              mazz

              There is already a thread on this very topic on the forum. Do a search - there was a conversation on whether this was the right thing to do or not.

              You need to access elements of the "lazy" fetched data (size() for example) to get it to load.

              • 4. Re: FetchType.LAZY doesn't work
                ejb3workshop

                I would have expected this to be the "idea" behind LAZY. It allows you to configure what objects are loaded during an operation. If you need to extend this behaviour you might want to look into using the extended persistence context

                eg:

                @PersistenceContext(type=javax.persistence.PersistenceContextType.EXTENDED)
                private EntityManager manager;
                



                Then you can access defer the lazy loading until a later stage, but not later then the destruction of the "session".