ObjectDB ObjectDB

LAZY @ManyToOne field functions as EAGER

#1

In the code example below (also attached) I would like to understand why I am able to print to console a lazy @ManyToOne field after the entity manager closes. There is a switch DO_VIEW_BEFORE_CLOSE, and when it is true the fields are accessed and output before the finding entity manager closes and as expected both a LAZY @ManyToOne field and an EAGER @ManyToOne field are viewable:

b.cLazy:{C}[2]"cLazy"

b.cEager:{C}[3]"cEager"

But when I switch DO_VIEW_BEFORE_CLOSE to false, so that the fields are only accessed after the finding entity manager closes, I can still view b.cLazy, whereas I would expect b.cLazy to not be still resolved. [By constrast, using this approach an unmapped @OneToMany list is not still viewable, although a mapped @OneToMany list is, which I will discuss in another forum posting]

Q: Why is b.cLazy viewable after the finding entity manager closes, when it is marked as @ManyToOne(fetch=FetchType.LAZY) ?

 

package com.greensoft.objectdb.test.console;

import javax.persistence.*;

/**
*
* @author Darren Kelly (Webel IT Australia)
*/
public class TestLazyManyToOne {
   
    /**
     * If true the console view of the fields of the entities will be
     * called after find before the relevant EntityManager closes.
     */
    final static boolean DO_VIEW_BEFORE_CLOSE = false;
   
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        String $connection = "objectdb:db/TestLazyManyToOne.tmp;drop";
        EntityManagerFactory emf =
            Persistence.createEntityManagerFactory($connection);
               
        EntityManager  em = emf.createEntityManager();
        em.getTransaction().begin();
        B b = new B("b");
        b.cLazy = new C("cLazy");
        b.cEager = new C("cEager");
       
        em.persist(b);
        em.getTransaction().commit();
        Long id = b.id;
        em.close();

        em = emf.createEntityManager();
        b = em.find(B.class, id);
        
        if (!DO_VIEW_BEFORE_CLOSE) em.close();
       
        //Output entities and fields
       
        System.out.println("b.cLazy:"+b.cLazy);
        System.out.println("b.cEager:"+b.cEager);

        if (DO_VIEW_BEFORE_CLOSE) em.close();
       
        emf.close();
               
    }
   
    @Entity
    abstract static public class A {
       
        @Id
        @GeneratedValue
        Long id;

        String name;
               
        protected A(String name) {
            this.name = name;
        }
       
        @Override public String toString() {
            return "{"+getClass().getSimpleName()+ "}"+ "["+id+"]\"" + name + "\"";
        }
                       
    }

    @Entity
    static public class B extends A {
               
        public B(String name) {
            super(name);
        }

        @ManyToOne(fetch=FetchType.LAZY, cascade= CascadeType.ALL)
        C cLazy;
       
        @ManyToOne(fetch=FetchType.EAGER, cascade= CascadeType.ALL)
        C cEager;              
       
    }
   
    @Entity
    static public class C extends A {
               
        public C(String name) {
            super(name);
        }

    }
}

 

edit
delete
#2

In JPA, LAZY (unlike EAGER) is merely a hint.

For example, ObjectDB always loads simple value fields eagerly (e.g. String fields), even if lazy loading is specified, since usually there is no benefit in lazy loading in these cases.

Regarding your example, ObjectDB can use lazy loading in OneToOne and ManyToOne relationships only in enhanced classes. If you run your test as recommended with enhancement enabled, e.g. 

java -javaagent:objectdb.jar com.greensoft.objectdb.test.console.TestLazyManyToOne

The output should be:

b.cLazy:{C}[2]"null"
b.cEager:{C}[3]"cEager"

But when classes are not enhanced, ObjectDB has to ignore lazy loading and load "to-one" relationships eagerly, since  there is no way for ObjectDB to know that such relationships are expected to be accessed (there is no trigger), so such fields have to be loaded in advance.

ObjectDB Support
edit
delete
#3

thanks for explanation, have tested and confirmed result.

edit
delete

Reply

To post on this website please sign in.