Lazy loading does not work

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Lazy loading does not work

janneefef
Hi,

I'm using Eclipselink to provide JPA. I'm using GlassFish 3.0.1.

I have a some simple Employer and Person entities with many-to-many
(using join table) and one-to-many relationships. I want to have the
relationships lazy loaded, but it looks like they are always eagerly
loaded. I am aware that lazy/eager is just a hint to the JPA
implementation, but I'm thinking that lazy loading is probably
supposed to work with Eclipselink?

Entities are along the lines of (likely irrelevant lines omitted):


@Entity
@NamedQueries({
    @NamedQuery(name = "Employer.findAllLatest2", query = "select o
from Employer o"),
})
public class Employer implements Serializable {
    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
    @JoinTable(name = "EMPLOYER_PERSON", joinColumns =
    @JoinColumn(name = "EMPLOYER_ID"), inverseJoinColumns =
    @JoinColumn(name = "PERSON_ID"))
    private Set<Person> persons;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "BOSS_ID")
    private Person boss;
}

@Entity
@NamedQueries({
  @NamedQuery(name = "EmployerPerson.findAll", query = "select o from
EmployerPerson o")
})
@Table(name = "EMPLOYER_PERSON")
@IdClass(EmployerPersonPK.class)
public class EmployerPerson implements Serializable {
    @Id
    @Column(name="EMPLOYER_ID", nullable = false, insertable = false,
            updatable = false)
    private Long employerId;
    @Id
    @Column(name="PERSON_ID", nullable = false, insertable = false,
            updatable = false)
    private Long personId;
    @ManyToOne
    @JoinColumn(name = "EMPLOYER_ID")
    private Employer employer;
    @ManyToOne
    @JoinColumn(name = "PERSON_ID")
    private Person person;
}

@Entity
public class Person implements Serializable {
    @ManyToMany(mappedBy="persons")
    private Set<Employer> employers;

@Stateless
@LocalBean
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class EmployerService {

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public List<Employer> findAll() {
        String namedQuery = "Employer.findAllLatest2";
        }
        List<Employer> employers = em.createNamedQuery(namedQuery,
Employer.class).getResultList();
        for (Employer e: employers) {
            em.detach(e);
        }
        return employers;
    }

Now, when I use findAll(), I would expect that Employer objects do not
have the person references fecthed. But they are. Accessing persons
succeeds even though I did add (extraneous) detach() -calls to make
sure the entities are detached after returning from findAll().
_______________________________________________
eclipselink-users mailing list
[hidden email]
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
Reply | Threaded
Open this post in threaded view
|

Re: Lazy loading does not work

Tom Ware
Hi Janne,

   Where in your code do you see the relationships traversed?  You can turn on
EclipseLink logging (persistence unit property:
eclipselink.logging.level=FINEST) to see all of the logging.  When do you see
the SQL that traverses the relationship?

   EclipseLink has some functionality that allows LAZY relationships to be
traversable after detachment if the connection is available.  I am wondering if
you are seeing that functionality in action.

-Tom

janne postilista wrote:

> Hi,
>
> I'm using Eclipselink to provide JPA. I'm using GlassFish 3.0.1.
>
> I have a some simple Employer and Person entities with many-to-many
> (using join table) and one-to-many relationships. I want to have the
> relationships lazy loaded, but it looks like they are always eagerly
> loaded. I am aware that lazy/eager is just a hint to the JPA
> implementation, but I'm thinking that lazy loading is probably
> supposed to work with Eclipselink?
>
> Entities are along the lines of (likely irrelevant lines omitted):
>
>
> @Entity
> @NamedQueries({
>     @NamedQuery(name = "Employer.findAllLatest2", query = "select o
> from Employer o"),
> })
> public class Employer implements Serializable {
>     @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
>     @JoinTable(name = "EMPLOYER_PERSON", joinColumns =
>     @JoinColumn(name = "EMPLOYER_ID"), inverseJoinColumns =
>     @JoinColumn(name = "PERSON_ID"))
>     private Set<Person> persons;
>
>     @ManyToOne(fetch = FetchType.LAZY)
>     @JoinColumn(name = "BOSS_ID")
>     private Person boss;
> }
>
> @Entity
> @NamedQueries({
>   @NamedQuery(name = "EmployerPerson.findAll", query = "select o from
> EmployerPerson o")
> })
> @Table(name = "EMPLOYER_PERSON")
> @IdClass(EmployerPersonPK.class)
> public class EmployerPerson implements Serializable {
>     @Id
>     @Column(name="EMPLOYER_ID", nullable = false, insertable = false,
>             updatable = false)
>     private Long employerId;
>     @Id
>     @Column(name="PERSON_ID", nullable = false, insertable = false,
>             updatable = false)
>     private Long personId;
>     @ManyToOne
>     @JoinColumn(name = "EMPLOYER_ID")
>     private Employer employer;
>     @ManyToOne
>     @JoinColumn(name = "PERSON_ID")
>     private Person person;
> }
>
> @Entity
> public class Person implements Serializable {
>     @ManyToMany(mappedBy="persons")
>     private Set<Employer> employers;
>
> @Stateless
> @LocalBean
> @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
> public class EmployerService {
>
>     @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
>     public List<Employer> findAll() {
>         String namedQuery = "Employer.findAllLatest2";
>         }
>         List<Employer> employers = em.createNamedQuery(namedQuery,
> Employer.class).getResultList();
>         for (Employer e: employers) {
>             em.detach(e);
>         }
>         return employers;
>     }
>
> Now, when I use findAll(), I would expect that Employer objects do not
> have the person references fecthed. But they are. Accessing persons
> succeeds even though I did add (extraneous) detach() -calls to make
> sure the entities are detached after returning from findAll().
> _______________________________________________
> eclipselink-users mailing list
> [hidden email]
> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
_______________________________________________
eclipselink-users mailing list
[hidden email]
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
Reply | Threaded
Open this post in threaded view
|

Re: Lazy loading does not work

janneefef
Well, yes, it sure seems like that is happening. Looking at the logs,
it seems that eclipselink first loads all Employers without the
persons (so lazy loading works)

[#|2010-09-14T17:44:32.494+0300|FINE|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projectszzz/glassfishv3-3/glassfish/domains/test-domai
n/applications/services-ear/services-ejb_jar/zzz-pu.sql|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|SELECT
ID, ZZZ, VERSION FROM EMPLOYER|#]

[#|2010-09-14T17:44:32.539+0300|FINER|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projects/zzz/sandbox/glassfishv3-3/glassfish/domains/test-doma
in/applications/services-ear/services-ejb_jar/zzz-pu.transaction|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|end
unit of work commit|
#]

then after exiting findAll() I am mapping the entities to JAXB beans
and accessing the person references. Eclipselink loads the person from
db:

[#|2010-09-14T17:44:32.676+0300|FINE|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projects/zzz/sandbox/glassfishv3-3/glassfish/domains/test-domai
n/applications/services-ear/services-ejb_jar/zzz-pu.sql|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|SELECT
t1.ID, t1.LAST_NAME, t1.TI
TLE_SE, ZZZ FROM EMPLOYER_PERSON t0, PERSON t1 WHERE ((t0.E
MPLOYER_ID = ?) AND (t1.ID = t0.PERSON_ID))
        bind => [20284]|#]

1. This seems counter-intuitive to me....how can Eclipselink fetch the
lazy relationships after a) the EJB transaction has already ended and
b) the entities have been explicitly detached? That's not at all what
I would be assuming
2. If I redo the same method call, Eclipselink logs show that SQL
queries go to database to fetch the Employers, but there's no SQL for
the persons on the second go. Seems like the persons come from some
2nd level cache or something? How does this work, I haven't configured
anything special related to caching? I have also noticed this in
practise, in that direct SQL updates to DB are not visible throught
the application. Does eclipseLink use 2nd level caching by default?


On Tue, Sep 14, 2010 at 4:47 PM, Tom Ware <[hidden email]> wrote:

> Hi Janne,
>
>  Where in your code do you see the relationships traversed?  You can turn on
> EclipseLink logging (persistence unit property:
> eclipselink.logging.level=FINEST) to see all of the logging.  When do you
> see the SQL that traverses the relationship?
>
>  EclipseLink has some functionality that allows LAZY relationships to be
> traversable after detachment if the connection is available.  I am wondering
> if you are seeing that functionality in action.
>
> -Tom
>
> janne postilista wrote:
>>
>> Hi,
>>
>> I'm using Eclipselink to provide JPA. I'm using GlassFish 3.0.1.
>>
>> I have a some simple Employer and Person entities with many-to-many
>> (using join table) and one-to-many relationships. I want to have the
>> relationships lazy loaded, but it looks like they are always eagerly
>> loaded. I am aware that lazy/eager is just a hint to the JPA
>> implementation, but I'm thinking that lazy loading is probably
>> supposed to work with Eclipselink?
>>
>> Entities are along the lines of (likely irrelevant lines omitted):
>>
>>
>> @Entity
>> @NamedQueries({
>>    @NamedQuery(name = "Employer.findAllLatest2", query = "select o
>> from Employer o"),
>> })
>> public class Employer implements Serializable {
>>    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
>>    @JoinTable(name = "EMPLOYER_PERSON", joinColumns =
>>    @JoinColumn(name = "EMPLOYER_ID"), inverseJoinColumns =
>>    @JoinColumn(name = "PERSON_ID"))
>>    private Set<Person> persons;
>>
>>    @ManyToOne(fetch = FetchType.LAZY)
>>    @JoinColumn(name = "BOSS_ID")
>>    private Person boss;
>> }
>>
>> @Entity
>> @NamedQueries({
>>  @NamedQuery(name = "EmployerPerson.findAll", query = "select o from
>> EmployerPerson o")
>> })
>> @Table(name = "EMPLOYER_PERSON")
>> @IdClass(EmployerPersonPK.class)
>> public class EmployerPerson implements Serializable {
>>    @Id
>>    @Column(name="EMPLOYER_ID", nullable = false, insertable = false,
>>            updatable = false)
>>    private Long employerId;
>>    @Id
>>    @Column(name="PERSON_ID", nullable = false, insertable = false,
>>            updatable = false)
>>    private Long personId;
>>    @ManyToOne
>>    @JoinColumn(name = "EMPLOYER_ID")
>>    private Employer employer;
>>    @ManyToOne
>>    @JoinColumn(name = "PERSON_ID")
>>    private Person person;
>> }
>>
>> @Entity
>> public class Person implements Serializable {
>>    @ManyToMany(mappedBy="persons")
>>    private Set<Employer> employers;
>>
>> @Stateless
>> @LocalBean
>> @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
>> public class EmployerService {
>>
>>    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
>>    public List<Employer> findAll() {
>>        String namedQuery = "Employer.findAllLatest2";
>>        }
>>        List<Employer> employers = em.createNamedQuery(namedQuery,
>> Employer.class).getResultList();
>>        for (Employer e: employers) {
>>            em.detach(e);
>>        }
>>        return employers;
>>    }
>>
>> Now, when I use findAll(), I would expect that Employer objects do not
>> have the person references fecthed. But they are. Accessing persons
>> succeeds even though I did add (extraneous) detach() -calls to make
>> sure the entities are detached after returning from findAll().
>> _______________________________________________
>> eclipselink-users mailing list
>> [hidden email]
>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>
> _______________________________________________
> eclipselink-users mailing list
> [hidden email]
> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>
_______________________________________________
eclipselink-users mailing list
[hidden email]
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
Reply | Threaded
Open this post in threaded view
|

Re: Lazy loading does not work

Tom Ware
1. We choose to allow LAZY relationships to be traversed in detached objects
where possible because we believe this provides a higher level of functionality.
  In other words... If we have everything we need to traverse the LAZY
relationship, why would be disable the functionality that allows you to traverse it.

2. Yes.  EclipseLink uses a 2nd level cache by default.  There are a number of
cache config settings. The following webpage shows a list of the caching options
that are available through JPA config.
http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_%28ELUG%29#Using_EclipseLink_JPA_Extensions_for_Entity_Caching

-Tom

janne postilista wrote:

> Well, yes, it sure seems like that is happening. Looking at the logs,
> it seems that eclipselink first loads all Employers without the
> persons (so lazy loading works)
>
> [#|2010-09-14T17:44:32.494+0300|FINE|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projectszzz/glassfishv3-3/glassfish/domains/test-domai
> n/applications/services-ear/services-ejb_jar/zzz-pu.sql|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|SELECT
> ID, ZZZ, VERSION FROM EMPLOYER|#]
>
> [#|2010-09-14T17:44:32.539+0300|FINER|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projects/zzz/sandbox/glassfishv3-3/glassfish/domains/test-doma
> in/applications/services-ear/services-ejb_jar/zzz-pu.transaction|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|end
> unit of work commit|
> #]
>
> then after exiting findAll() I am mapping the entities to JAXB beans
> and accessing the person references. Eclipselink loads the person from
> db:
>
> [#|2010-09-14T17:44:32.676+0300|FINE|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projects/zzz/sandbox/glassfishv3-3/glassfish/domains/test-domai
> n/applications/services-ear/services-ejb_jar/zzz-pu.sql|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|SELECT
> t1.ID, t1.LAST_NAME, t1.TI
> TLE_SE, ZZZ FROM EMPLOYER_PERSON t0, PERSON t1 WHERE ((t0.E
> MPLOYER_ID = ?) AND (t1.ID = t0.PERSON_ID))
>         bind => [20284]|#]
>
> 1. This seems counter-intuitive to me....how can Eclipselink fetch the
> lazy relationships after a) the EJB transaction has already ended and
> b) the entities have been explicitly detached? That's not at all what
> I would be assuming
> 2. If I redo the same method call, Eclipselink logs show that SQL
> queries go to database to fetch the Employers, but there's no SQL for
> the persons on the second go. Seems like the persons come from some
> 2nd level cache or something? How does this work, I haven't configured
> anything special related to caching? I have also noticed this in
> practise, in that direct SQL updates to DB are not visible throught
> the application. Does eclipseLink use 2nd level caching by default?
>
>
> On Tue, Sep 14, 2010 at 4:47 PM, Tom Ware <[hidden email]> wrote:
>> Hi Janne,
>>
>>  Where in your code do you see the relationships traversed?  You can turn on
>> EclipseLink logging (persistence unit property:
>> eclipselink.logging.level=FINEST) to see all of the logging.  When do you
>> see the SQL that traverses the relationship?
>>
>>  EclipseLink has some functionality that allows LAZY relationships to be
>> traversable after detachment if the connection is available.  I am wondering
>> if you are seeing that functionality in action.
>>
>> -Tom
>>
>> janne postilista wrote:
>>> Hi,
>>>
>>> I'm using Eclipselink to provide JPA. I'm using GlassFish 3.0.1.
>>>
>>> I have a some simple Employer and Person entities with many-to-many
>>> (using join table) and one-to-many relationships. I want to have the
>>> relationships lazy loaded, but it looks like they are always eagerly
>>> loaded. I am aware that lazy/eager is just a hint to the JPA
>>> implementation, but I'm thinking that lazy loading is probably
>>> supposed to work with Eclipselink?
>>>
>>> Entities are along the lines of (likely irrelevant lines omitted):
>>>
>>>
>>> @Entity
>>> @NamedQueries({
>>>    @NamedQuery(name = "Employer.findAllLatest2", query = "select o
>>> from Employer o"),
>>> })
>>> public class Employer implements Serializable {
>>>    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
>>>    @JoinTable(name = "EMPLOYER_PERSON", joinColumns =
>>>    @JoinColumn(name = "EMPLOYER_ID"), inverseJoinColumns =
>>>    @JoinColumn(name = "PERSON_ID"))
>>>    private Set<Person> persons;
>>>
>>>    @ManyToOne(fetch = FetchType.LAZY)
>>>    @JoinColumn(name = "BOSS_ID")
>>>    private Person boss;
>>> }
>>>
>>> @Entity
>>> @NamedQueries({
>>>  @NamedQuery(name = "EmployerPerson.findAll", query = "select o from
>>> EmployerPerson o")
>>> })
>>> @Table(name = "EMPLOYER_PERSON")
>>> @IdClass(EmployerPersonPK.class)
>>> public class EmployerPerson implements Serializable {
>>>    @Id
>>>    @Column(name="EMPLOYER_ID", nullable = false, insertable = false,
>>>            updatable = false)
>>>    private Long employerId;
>>>    @Id
>>>    @Column(name="PERSON_ID", nullable = false, insertable = false,
>>>            updatable = false)
>>>    private Long personId;
>>>    @ManyToOne
>>>    @JoinColumn(name = "EMPLOYER_ID")
>>>    private Employer employer;
>>>    @ManyToOne
>>>    @JoinColumn(name = "PERSON_ID")
>>>    private Person person;
>>> }
>>>
>>> @Entity
>>> public class Person implements Serializable {
>>>    @ManyToMany(mappedBy="persons")
>>>    private Set<Employer> employers;
>>>
>>> @Stateless
>>> @LocalBean
>>> @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
>>> public class EmployerService {
>>>
>>>    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
>>>    public List<Employer> findAll() {
>>>        String namedQuery = "Employer.findAllLatest2";
>>>        }
>>>        List<Employer> employers = em.createNamedQuery(namedQuery,
>>> Employer.class).getResultList();
>>>        for (Employer e: employers) {
>>>            em.detach(e);
>>>        }
>>>        return employers;
>>>    }
>>>
>>> Now, when I use findAll(), I would expect that Employer objects do not
>>> have the person references fecthed. But they are. Accessing persons
>>> succeeds even though I did add (extraneous) detach() -calls to make
>>> sure the entities are detached after returning from findAll().
>>> _______________________________________________
>>> eclipselink-users mailing list
>>> [hidden email]
>>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>> _______________________________________________
>> eclipselink-users mailing list
>> [hidden email]
>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>>
> _______________________________________________
> eclipselink-users mailing list
> [hidden email]
> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
_______________________________________________
eclipselink-users mailing list
[hidden email]
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
Reply | Threaded
Open this post in threaded view
|

Re: Lazy loading does not work

janneefef
Hi,

 not saying that this is feature is bad, it's just surprising initially.

Can you still clarify this a bit - since I have defined
EmployerService.findAll() with REQUIRES_NEW, the transaction that
fetched the Employer should be committed and closed at the point where
I am accessing the detached objects, correct? Does eclipseLink create
a new transaction for fetching the persons - one transaction for each
person, or what - how does it actually work?

On Tue, Sep 14, 2010 at 6:10 PM, Tom Ware <[hidden email]> wrote:

> 1. We choose to allow LAZY relationships to be traversed in detached objects
> where possible because we believe this provides a higher level of
> functionality.  In other words... If we have everything we need to traverse
> the LAZY relationship, why would be disable the functionality that allows
> you to traverse it.
>
> 2. Yes.  EclipseLink uses a 2nd level cache by default.  There are a number
> of cache config settings. The following webpage shows a list of the caching
> options that are available through JPA config.
> http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_%28ELUG%29#Using_EclipseLink_JPA_Extensions_for_Entity_Caching
>
> -Tom
>
> janne postilista wrote:
>>
>> Well, yes, it sure seems like that is happening. Looking at the logs,
>> it seems that eclipselink first loads all Employers without the
>> persons (so lazy loading works)
>>
>>
>> [#|2010-09-14T17:44:32.494+0300|FINE|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projectszzz/glassfishv3-3/glassfish/domains/test-domai
>>
>> n/applications/services-ear/services-ejb_jar/zzz-pu.sql|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|SELECT
>> ID, ZZZ, VERSION FROM EMPLOYER|#]
>>
>>
>> [#|2010-09-14T17:44:32.539+0300|FINER|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projects/zzz/sandbox/glassfishv3-3/glassfish/domains/test-doma
>>
>> in/applications/services-ear/services-ejb_jar/zzz-pu.transaction|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|end
>> unit of work commit|
>> #]
>>
>> then after exiting findAll() I am mapping the entities to JAXB beans
>> and accessing the person references. Eclipselink loads the person from
>> db:
>>
>>
>> [#|2010-09-14T17:44:32.676+0300|FINE|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projects/zzz/sandbox/glassfishv3-3/glassfish/domains/test-domai
>>
>> n/applications/services-ear/services-ejb_jar/zzz-pu.sql|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|SELECT
>> t1.ID, t1.LAST_NAME, t1.TI
>> TLE_SE, ZZZ FROM EMPLOYER_PERSON t0, PERSON t1 WHERE ((t0.E
>> MPLOYER_ID = ?) AND (t1.ID = t0.PERSON_ID))
>>        bind => [20284]|#]
>>
>> 1. This seems counter-intuitive to me....how can Eclipselink fetch the
>> lazy relationships after a) the EJB transaction has already ended and
>> b) the entities have been explicitly detached? That's not at all what
>> I would be assuming
>> 2. If I redo the same method call, Eclipselink logs show that SQL
>> queries go to database to fetch the Employers, but there's no SQL for
>> the persons on the second go. Seems like the persons come from some
>> 2nd level cache or something? How does this work, I haven't configured
>> anything special related to caching? I have also noticed this in
>> practise, in that direct SQL updates to DB are not visible throught
>> the application. Does eclipseLink use 2nd level caching by default?
>>
>>
>> On Tue, Sep 14, 2010 at 4:47 PM, Tom Ware <[hidden email]> wrote:
>>>
>>> Hi Janne,
>>>
>>>  Where in your code do you see the relationships traversed?  You can turn
>>> on
>>> EclipseLink logging (persistence unit property:
>>> eclipselink.logging.level=FINEST) to see all of the logging.  When do you
>>> see the SQL that traverses the relationship?
>>>
>>>  EclipseLink has some functionality that allows LAZY relationships to be
>>> traversable after detachment if the connection is available.  I am
>>> wondering
>>> if you are seeing that functionality in action.
>>>
>>> -Tom
>>>
>>> janne postilista wrote:
>>>>
>>>> Hi,
>>>>
>>>> I'm using Eclipselink to provide JPA. I'm using GlassFish 3.0.1.
>>>>
>>>> I have a some simple Employer and Person entities with many-to-many
>>>> (using join table) and one-to-many relationships. I want to have the
>>>> relationships lazy loaded, but it looks like they are always eagerly
>>>> loaded. I am aware that lazy/eager is just a hint to the JPA
>>>> implementation, but I'm thinking that lazy loading is probably
>>>> supposed to work with Eclipselink?
>>>>
>>>> Entities are along the lines of (likely irrelevant lines omitted):
>>>>
>>>>
>>>> @Entity
>>>> @NamedQueries({
>>>>   @NamedQuery(name = "Employer.findAllLatest2", query = "select o
>>>> from Employer o"),
>>>> })
>>>> public class Employer implements Serializable {
>>>>   @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
>>>>   @JoinTable(name = "EMPLOYER_PERSON", joinColumns =
>>>>   @JoinColumn(name = "EMPLOYER_ID"), inverseJoinColumns =
>>>>   @JoinColumn(name = "PERSON_ID"))
>>>>   private Set<Person> persons;
>>>>
>>>>   @ManyToOne(fetch = FetchType.LAZY)
>>>>   @JoinColumn(name = "BOSS_ID")
>>>>   private Person boss;
>>>> }
>>>>
>>>> @Entity
>>>> @NamedQueries({
>>>>  @NamedQuery(name = "EmployerPerson.findAll", query = "select o from
>>>> EmployerPerson o")
>>>> })
>>>> @Table(name = "EMPLOYER_PERSON")
>>>> @IdClass(EmployerPersonPK.class)
>>>> public class EmployerPerson implements Serializable {
>>>>   @Id
>>>>   @Column(name="EMPLOYER_ID", nullable = false, insertable = false,
>>>>           updatable = false)
>>>>   private Long employerId;
>>>>   @Id
>>>>   @Column(name="PERSON_ID", nullable = false, insertable = false,
>>>>           updatable = false)
>>>>   private Long personId;
>>>>   @ManyToOne
>>>>   @JoinColumn(name = "EMPLOYER_ID")
>>>>   private Employer employer;
>>>>   @ManyToOne
>>>>   @JoinColumn(name = "PERSON_ID")
>>>>   private Person person;
>>>> }
>>>>
>>>> @Entity
>>>> public class Person implements Serializable {
>>>>   @ManyToMany(mappedBy="persons")
>>>>   private Set<Employer> employers;
>>>>
>>>> @Stateless
>>>> @LocalBean
>>>> @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
>>>> public class EmployerService {
>>>>
>>>>   @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
>>>>   public List<Employer> findAll() {
>>>>       String namedQuery = "Employer.findAllLatest2";
>>>>       }
>>>>       List<Employer> employers = em.createNamedQuery(namedQuery,
>>>> Employer.class).getResultList();
>>>>       for (Employer e: employers) {
>>>>           em.detach(e);
>>>>       }
>>>>       return employers;
>>>>   }
>>>>
>>>> Now, when I use findAll(), I would expect that Employer objects do not
>>>> have the person references fecthed. But they are. Accessing persons
>>>> succeeds even though I did add (extraneous) detach() -calls to make
>>>> sure the entities are detached after returning from findAll().
>>>> _______________________________________________
>>>> eclipselink-users mailing list
>>>> [hidden email]
>>>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>>>
>>> _______________________________________________
>>> eclipselink-users mailing list
>>> [hidden email]
>>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>>>
>> _______________________________________________
>> eclipselink-users mailing list
>> [hidden email]
>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>
> _______________________________________________
> eclipselink-users mailing list
> [hidden email]
> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>
_______________________________________________
eclipselink-users mailing list
[hidden email]
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
Reply | Threaded
Open this post in threaded view
|

Re: Lazy loading does not work

janneefef
Can anyone explain how the transactions work in this case?

The whole picture is that MDB starts it's own transaction A (default
transaction attributes). It calls stateless EJB
EmployerService.findAll() which has been defined REQUIRES_NEW, so it
runs in another transaction B.

findAll() reads Employers from DB in transaction B. After findAll()
returns, B is committed.

MDB then accesses the detached employers and the persons that have not
been loaded yet. This triggers loading of persons with SELECT ... FROM
PERSON. Does this happen in transaction A?

How does this all really work?


On Wed, Sep 15, 2010 at 10:58 AM, janne postilista
<[hidden email]> wrote:

> Hi,
>
>  not saying that this is feature is bad, it's just surprising initially.
>
> Can you still clarify this a bit - since I have defined
> EmployerService.findAll() with REQUIRES_NEW, the transaction that
> fetched the Employer should be committed and closed at the point where
> I am accessing the detached objects, correct? Does eclipseLink create
> a new transaction for fetching the persons - one transaction for each
> person, or what - how does it actually work?
>
> On Tue, Sep 14, 2010 at 6:10 PM, Tom Ware <[hidden email]> wrote:
>> 1. We choose to allow LAZY relationships to be traversed in detached objects
>> where possible because we believe this provides a higher level of
>> functionality.  In other words... If we have everything we need to traverse
>> the LAZY relationship, why would be disable the functionality that allows
>> you to traverse it.
>>
>> 2. Yes.  EclipseLink uses a 2nd level cache by default.  There are a number
>> of cache config settings. The following webpage shows a list of the caching
>> options that are available through JPA config.
>> http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_%28ELUG%29#Using_EclipseLink_JPA_Extensions_for_Entity_Caching
>>
>> -Tom
>>
>> janne postilista wrote:
>>>
>>> Well, yes, it sure seems like that is happening. Looking at the logs,
>>> it seems that eclipselink first loads all Employers without the
>>> persons (so lazy loading works)
>>>
>>>
>>> [#|2010-09-14T17:44:32.494+0300|FINE|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projectszzz/glassfishv3-3/glassfish/domains/test-domai
>>>
>>> n/applications/services-ear/services-ejb_jar/zzz-pu.sql|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|SELECT
>>> ID, ZZZ, VERSION FROM EMPLOYER|#]
>>>
>>>
>>> [#|2010-09-14T17:44:32.539+0300|FINER|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projects/zzz/sandbox/glassfishv3-3/glassfish/domains/test-doma
>>>
>>> in/applications/services-ear/services-ejb_jar/zzz-pu.transaction|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|end
>>> unit of work commit|
>>> #]
>>>
>>> then after exiting findAll() I am mapping the entities to JAXB beans
>>> and accessing the person references. Eclipselink loads the person from
>>> db:
>>>
>>>
>>> [#|2010-09-14T17:44:32.676+0300|FINE|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projects/zzz/sandbox/glassfishv3-3/glassfish/domains/test-domai
>>>
>>> n/applications/services-ear/services-ejb_jar/zzz-pu.sql|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|SELECT
>>> t1.ID, t1.LAST_NAME, t1.TI
>>> TLE_SE, ZZZ FROM EMPLOYER_PERSON t0, PERSON t1 WHERE ((t0.E
>>> MPLOYER_ID = ?) AND (t1.ID = t0.PERSON_ID))
>>>        bind => [20284]|#]
>>>
>>> 1. This seems counter-intuitive to me....how can Eclipselink fetch the
>>> lazy relationships after a) the EJB transaction has already ended and
>>> b) the entities have been explicitly detached? That's not at all what
>>> I would be assuming
>>> 2. If I redo the same method call, Eclipselink logs show that SQL
>>> queries go to database to fetch the Employers, but there's no SQL for
>>> the persons on the second go. Seems like the persons come from some
>>> 2nd level cache or something? How does this work, I haven't configured
>>> anything special related to caching? I have also noticed this in
>>> practise, in that direct SQL updates to DB are not visible throught
>>> the application. Does eclipseLink use 2nd level caching by default?
>>>
>>>
>>> On Tue, Sep 14, 2010 at 4:47 PM, Tom Ware <[hidden email]> wrote:
>>>>
>>>> Hi Janne,
>>>>
>>>>  Where in your code do you see the relationships traversed?  You can turn
>>>> on
>>>> EclipseLink logging (persistence unit property:
>>>> eclipselink.logging.level=FINEST) to see all of the logging.  When do you
>>>> see the SQL that traverses the relationship?
>>>>
>>>>  EclipseLink has some functionality that allows LAZY relationships to be
>>>> traversable after detachment if the connection is available.  I am
>>>> wondering
>>>> if you are seeing that functionality in action.
>>>>
>>>> -Tom
>>>>
>>>> janne postilista wrote:
>>>>>
>>>>> Hi,
>>>>>
>>>>> I'm using Eclipselink to provide JPA. I'm using GlassFish 3.0.1.
>>>>>
>>>>> I have a some simple Employer and Person entities with many-to-many
>>>>> (using join table) and one-to-many relationships. I want to have the
>>>>> relationships lazy loaded, but it looks like they are always eagerly
>>>>> loaded. I am aware that lazy/eager is just a hint to the JPA
>>>>> implementation, but I'm thinking that lazy loading is probably
>>>>> supposed to work with Eclipselink?
>>>>>
>>>>> Entities are along the lines of (likely irrelevant lines omitted):
>>>>>
>>>>>
>>>>> @Entity
>>>>> @NamedQueries({
>>>>>   @NamedQuery(name = "Employer.findAllLatest2", query = "select o
>>>>> from Employer o"),
>>>>> })
>>>>> public class Employer implements Serializable {
>>>>>   @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
>>>>>   @JoinTable(name = "EMPLOYER_PERSON", joinColumns =
>>>>>   @JoinColumn(name = "EMPLOYER_ID"), inverseJoinColumns =
>>>>>   @JoinColumn(name = "PERSON_ID"))
>>>>>   private Set<Person> persons;
>>>>>
>>>>>   @ManyToOne(fetch = FetchType.LAZY)
>>>>>   @JoinColumn(name = "BOSS_ID")
>>>>>   private Person boss;
>>>>> }
>>>>>
>>>>> @Entity
>>>>> @NamedQueries({
>>>>>  @NamedQuery(name = "EmployerPerson.findAll", query = "select o from
>>>>> EmployerPerson o")
>>>>> })
>>>>> @Table(name = "EMPLOYER_PERSON")
>>>>> @IdClass(EmployerPersonPK.class)
>>>>> public class EmployerPerson implements Serializable {
>>>>>   @Id
>>>>>   @Column(name="EMPLOYER_ID", nullable = false, insertable = false,
>>>>>           updatable = false)
>>>>>   private Long employerId;
>>>>>   @Id
>>>>>   @Column(name="PERSON_ID", nullable = false, insertable = false,
>>>>>           updatable = false)
>>>>>   private Long personId;
>>>>>   @ManyToOne
>>>>>   @JoinColumn(name = "EMPLOYER_ID")
>>>>>   private Employer employer;
>>>>>   @ManyToOne
>>>>>   @JoinColumn(name = "PERSON_ID")
>>>>>   private Person person;
>>>>> }
>>>>>
>>>>> @Entity
>>>>> public class Person implements Serializable {
>>>>>   @ManyToMany(mappedBy="persons")
>>>>>   private Set<Employer> employers;
>>>>>
>>>>> @Stateless
>>>>> @LocalBean
>>>>> @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
>>>>> public class EmployerService {
>>>>>
>>>>>   @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
>>>>>   public List<Employer> findAll() {
>>>>>       String namedQuery = "Employer.findAllLatest2";
>>>>>       }
>>>>>       List<Employer> employers = em.createNamedQuery(namedQuery,
>>>>> Employer.class).getResultList();
>>>>>       for (Employer e: employers) {
>>>>>           em.detach(e);
>>>>>       }
>>>>>       return employers;
>>>>>   }
>>>>>
>>>>> Now, when I use findAll(), I would expect that Employer objects do not
>>>>> have the person references fecthed. But they are. Accessing persons
>>>>> succeeds even though I did add (extraneous) detach() -calls to make
>>>>> sure the entities are detached after returning from findAll().
>>>>> _______________________________________________
>>>>> eclipselink-users mailing list
>>>>> [hidden email]
>>>>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>>>>
>>>> _______________________________________________
>>>> eclipselink-users mailing list
>>>> [hidden email]
>>>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>>>>
>>> _______________________________________________
>>> eclipselink-users mailing list
>>> [hidden email]
>>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>>
>> _______________________________________________
>> eclipselink-users mailing list
>> [hidden email]
>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>>
>
_______________________________________________
eclipselink-users mailing list
[hidden email]
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
Reply | Threaded
Open this post in threaded view
|

Re: Lazy loading does not work

Tom Ware
Detached Objects get the connection need to traverse the LAZY relationship from
the EntityManagerFactory and will able able to use it as long as the
EntityManagerFactory is open.  The connection used in not the transactional one
and when you want to use the entity in a transaction it will have to be properly
merged.

janne postilista wrote:

> Can anyone explain how the transactions work in this case?
>
> The whole picture is that MDB starts it's own transaction A (default
> transaction attributes). It calls stateless EJB
> EmployerService.findAll() which has been defined REQUIRES_NEW, so it
> runs in another transaction B.
>
> findAll() reads Employers from DB in transaction B. After findAll()
> returns, B is committed.
>
> MDB then accesses the detached employers and the persons that have not
> been loaded yet. This triggers loading of persons with SELECT ... FROM
> PERSON. Does this happen in transaction A?
>
> How does this all really work?
>
>
> On Wed, Sep 15, 2010 at 10:58 AM, janne postilista
> <[hidden email]> wrote:
>> Hi,
>>
>>  not saying that this is feature is bad, it's just surprising initially.
>>
>> Can you still clarify this a bit - since I have defined
>> EmployerService.findAll() with REQUIRES_NEW, the transaction that
>> fetched the Employer should be committed and closed at the point where
>> I am accessing the detached objects, correct? Does eclipseLink create
>> a new transaction for fetching the persons - one transaction for each
>> person, or what - how does it actually work?
>>
>> On Tue, Sep 14, 2010 at 6:10 PM, Tom Ware <[hidden email]> wrote:
>>> 1. We choose to allow LAZY relationships to be traversed in detached objects
>>> where possible because we believe this provides a higher level of
>>> functionality.  In other words... If we have everything we need to traverse
>>> the LAZY relationship, why would be disable the functionality that allows
>>> you to traverse it.
>>>
>>> 2. Yes.  EclipseLink uses a 2nd level cache by default.  There are a number
>>> of cache config settings. The following webpage shows a list of the caching
>>> options that are available through JPA config.
>>> http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_%28ELUG%29#Using_EclipseLink_JPA_Extensions_for_Entity_Caching
>>>
>>> -Tom
>>>
>>> janne postilista wrote:
>>>> Well, yes, it sure seems like that is happening. Looking at the logs,
>>>> it seems that eclipselink first loads all Employers without the
>>>> persons (so lazy loading works)
>>>>
>>>>
>>>> [#|2010-09-14T17:44:32.494+0300|FINE|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projectszzz/glassfishv3-3/glassfish/domains/test-domai
>>>>
>>>> n/applications/services-ear/services-ejb_jar/zzz-pu.sql|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|SELECT
>>>> ID, ZZZ, VERSION FROM EMPLOYER|#]
>>>>
>>>>
>>>> [#|2010-09-14T17:44:32.539+0300|FINER|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projects/zzz/sandbox/glassfishv3-3/glassfish/domains/test-doma
>>>>
>>>> in/applications/services-ear/services-ejb_jar/zzz-pu.transaction|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|end
>>>> unit of work commit|
>>>> #]
>>>>
>>>> then after exiting findAll() I am mapping the entities to JAXB beans
>>>> and accessing the person references. Eclipselink loads the person from
>>>> db:
>>>>
>>>>
>>>> [#|2010-09-14T17:44:32.676+0300|FINE|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projects/zzz/sandbox/glassfishv3-3/glassfish/domains/test-domai
>>>>
>>>> n/applications/services-ear/services-ejb_jar/zzz-pu.sql|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|SELECT
>>>> t1.ID, t1.LAST_NAME, t1.TI
>>>> TLE_SE, ZZZ FROM EMPLOYER_PERSON t0, PERSON t1 WHERE ((t0.E
>>>> MPLOYER_ID = ?) AND (t1.ID = t0.PERSON_ID))
>>>>        bind => [20284]|#]
>>>>
>>>> 1. This seems counter-intuitive to me....how can Eclipselink fetch the
>>>> lazy relationships after a) the EJB transaction has already ended and
>>>> b) the entities have been explicitly detached? That's not at all what
>>>> I would be assuming
>>>> 2. If I redo the same method call, Eclipselink logs show that SQL
>>>> queries go to database to fetch the Employers, but there's no SQL for
>>>> the persons on the second go. Seems like the persons come from some
>>>> 2nd level cache or something? How does this work, I haven't configured
>>>> anything special related to caching? I have also noticed this in
>>>> practise, in that direct SQL updates to DB are not visible throught
>>>> the application. Does eclipseLink use 2nd level caching by default?
>>>>
>>>>
>>>> On Tue, Sep 14, 2010 at 4:47 PM, Tom Ware <[hidden email]> wrote:
>>>>> Hi Janne,
>>>>>
>>>>>  Where in your code do you see the relationships traversed?  You can turn
>>>>> on
>>>>> EclipseLink logging (persistence unit property:
>>>>> eclipselink.logging.level=FINEST) to see all of the logging.  When do you
>>>>> see the SQL that traverses the relationship?
>>>>>
>>>>>  EclipseLink has some functionality that allows LAZY relationships to be
>>>>> traversable after detachment if the connection is available.  I am
>>>>> wondering
>>>>> if you are seeing that functionality in action.
>>>>>
>>>>> -Tom
>>>>>
>>>>> janne postilista wrote:
>>>>>> Hi,
>>>>>>
>>>>>> I'm using Eclipselink to provide JPA. I'm using GlassFish 3.0.1.
>>>>>>
>>>>>> I have a some simple Employer and Person entities with many-to-many
>>>>>> (using join table) and one-to-many relationships. I want to have the
>>>>>> relationships lazy loaded, but it looks like they are always eagerly
>>>>>> loaded. I am aware that lazy/eager is just a hint to the JPA
>>>>>> implementation, but I'm thinking that lazy loading is probably
>>>>>> supposed to work with Eclipselink?
>>>>>>
>>>>>> Entities are along the lines of (likely irrelevant lines omitted):
>>>>>>
>>>>>>
>>>>>> @Entity
>>>>>> @NamedQueries({
>>>>>>   @NamedQuery(name = "Employer.findAllLatest2", query = "select o
>>>>>> from Employer o"),
>>>>>> })
>>>>>> public class Employer implements Serializable {
>>>>>>   @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
>>>>>>   @JoinTable(name = "EMPLOYER_PERSON", joinColumns =
>>>>>>   @JoinColumn(name = "EMPLOYER_ID"), inverseJoinColumns =
>>>>>>   @JoinColumn(name = "PERSON_ID"))
>>>>>>   private Set<Person> persons;
>>>>>>
>>>>>>   @ManyToOne(fetch = FetchType.LAZY)
>>>>>>   @JoinColumn(name = "BOSS_ID")
>>>>>>   private Person boss;
>>>>>> }
>>>>>>
>>>>>> @Entity
>>>>>> @NamedQueries({
>>>>>>  @NamedQuery(name = "EmployerPerson.findAll", query = "select o from
>>>>>> EmployerPerson o")
>>>>>> })
>>>>>> @Table(name = "EMPLOYER_PERSON")
>>>>>> @IdClass(EmployerPersonPK.class)
>>>>>> public class EmployerPerson implements Serializable {
>>>>>>   @Id
>>>>>>   @Column(name="EMPLOYER_ID", nullable = false, insertable = false,
>>>>>>           updatable = false)
>>>>>>   private Long employerId;
>>>>>>   @Id
>>>>>>   @Column(name="PERSON_ID", nullable = false, insertable = false,
>>>>>>           updatable = false)
>>>>>>   private Long personId;
>>>>>>   @ManyToOne
>>>>>>   @JoinColumn(name = "EMPLOYER_ID")
>>>>>>   private Employer employer;
>>>>>>   @ManyToOne
>>>>>>   @JoinColumn(name = "PERSON_ID")
>>>>>>   private Person person;
>>>>>> }
>>>>>>
>>>>>> @Entity
>>>>>> public class Person implements Serializable {
>>>>>>   @ManyToMany(mappedBy="persons")
>>>>>>   private Set<Employer> employers;
>>>>>>
>>>>>> @Stateless
>>>>>> @LocalBean
>>>>>> @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
>>>>>> public class EmployerService {
>>>>>>
>>>>>>   @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
>>>>>>   public List<Employer> findAll() {
>>>>>>       String namedQuery = "Employer.findAllLatest2";
>>>>>>       }
>>>>>>       List<Employer> employers = em.createNamedQuery(namedQuery,
>>>>>> Employer.class).getResultList();
>>>>>>       for (Employer e: employers) {
>>>>>>           em.detach(e);
>>>>>>       }
>>>>>>       return employers;
>>>>>>   }
>>>>>>
>>>>>> Now, when I use findAll(), I would expect that Employer objects do not
>>>>>> have the person references fecthed. But they are. Accessing persons
>>>>>> succeeds even though I did add (extraneous) detach() -calls to make
>>>>>> sure the entities are detached after returning from findAll().
>>>>>> _______________________________________________
>>>>>> eclipselink-users mailing list
>>>>>> [hidden email]
>>>>>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>>>>> _______________________________________________
>>>>> eclipselink-users mailing list
>>>>> [hidden email]
>>>>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>>>>>
>>>> _______________________________________________
>>>> eclipselink-users mailing list
>>>> [hidden email]
>>>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>>> _______________________________________________
>>> eclipselink-users mailing list
>>> [hidden email]
>>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>>>
> _______________________________________________
> eclipselink-users mailing list
> [hidden email]
> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
_______________________________________________
eclipselink-users mailing list
[hidden email]
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
Reply | Threaded
Open this post in threaded view
|

Re: Lazy loading does not work

janneefef
I see. It's now a little clearer to me.

Thanks for explaining this.


On Thu, Sep 16, 2010 at 5:48 PM, Tom Ware <[hidden email]> wrote:

> Detached Objects get the connection need to traverse the LAZY relationship
> from the EntityManagerFactory and will able able to use it as long as the
> EntityManagerFactory is open.  The connection used in not the transactional
> one and when you want to use the entity in a transaction it will have to be
> properly merged.
>
> janne postilista wrote:
>>
>> Can anyone explain how the transactions work in this case?
>>
>> The whole picture is that MDB starts it's own transaction A (default
>> transaction attributes). It calls stateless EJB
>> EmployerService.findAll() which has been defined REQUIRES_NEW, so it
>> runs in another transaction B.
>>
>> findAll() reads Employers from DB in transaction B. After findAll()
>> returns, B is committed.
>>
>> MDB then accesses the detached employers and the persons that have not
>> been loaded yet. This triggers loading of persons with SELECT ... FROM
>> PERSON. Does this happen in transaction A?
>>
>> How does this all really work?
>>
>>
>> On Wed, Sep 15, 2010 at 10:58 AM, janne postilista
>> <[hidden email]> wrote:
>>>
>>> Hi,
>>>
>>>  not saying that this is feature is bad, it's just surprising initially.
>>>
>>> Can you still clarify this a bit - since I have defined
>>> EmployerService.findAll() with REQUIRES_NEW, the transaction that
>>> fetched the Employer should be committed and closed at the point where
>>> I am accessing the detached objects, correct? Does eclipseLink create
>>> a new transaction for fetching the persons - one transaction for each
>>> person, or what - how does it actually work?
>>>
>>> On Tue, Sep 14, 2010 at 6:10 PM, Tom Ware <[hidden email]> wrote:
>>>>
>>>> 1. We choose to allow LAZY relationships to be traversed in detached
>>>> objects
>>>> where possible because we believe this provides a higher level of
>>>> functionality.  In other words... If we have everything we need to
>>>> traverse
>>>> the LAZY relationship, why would be disable the functionality that
>>>> allows
>>>> you to traverse it.
>>>>
>>>> 2. Yes.  EclipseLink uses a 2nd level cache by default.  There are a
>>>> number
>>>> of cache config settings. The following webpage shows a list of the
>>>> caching
>>>> options that are available through JPA config.
>>>>
>>>> http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_%28ELUG%29#Using_EclipseLink_JPA_Extensions_for_Entity_Caching
>>>>
>>>> -Tom
>>>>
>>>> janne postilista wrote:
>>>>>
>>>>> Well, yes, it sure seems like that is happening. Looking at the logs,
>>>>> it seems that eclipselink first loads all Employers without the
>>>>> persons (so lazy loading works)
>>>>>
>>>>>
>>>>>
>>>>> [#|2010-09-14T17:44:32.494+0300|FINE|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projectszzz/glassfishv3-3/glassfish/domains/test-domai
>>>>>
>>>>>
>>>>> n/applications/services-ear/services-ejb_jar/zzz-pu.sql|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|SELECT
>>>>> ID, ZZZ, VERSION FROM EMPLOYER|#]
>>>>>
>>>>>
>>>>>
>>>>> [#|2010-09-14T17:44:32.539+0300|FINER|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projects/zzz/sandbox/glassfishv3-3/glassfish/domains/test-doma
>>>>>
>>>>>
>>>>> in/applications/services-ear/services-ejb_jar/zzz-pu.transaction|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|end
>>>>> unit of work commit|
>>>>> #]
>>>>>
>>>>> then after exiting findAll() I am mapping the entities to JAXB beans
>>>>> and accessing the person references. Eclipselink loads the person from
>>>>> db:
>>>>>
>>>>>
>>>>>
>>>>> [#|2010-09-14T17:44:32.676+0300|FINE|glassfish3.0.1|org.eclipse.persistence.session.file:/D:/projects/zzz/sandbox/glassfishv3-3/glassfish/domains/test-domai
>>>>>
>>>>>
>>>>> n/applications/services-ear/services-ejb_jar/zzz-pu.sql|_ThreadID=17;_ThreadName=Thread-1;ClassName=null;MethodName=null;|SELECT
>>>>> t1.ID, t1.LAST_NAME, t1.TI
>>>>> TLE_SE, ZZZ FROM EMPLOYER_PERSON t0, PERSON t1 WHERE ((t0.E
>>>>> MPLOYER_ID = ?) AND (t1.ID = t0.PERSON_ID))
>>>>>       bind => [20284]|#]
>>>>>
>>>>> 1. This seems counter-intuitive to me....how can Eclipselink fetch the
>>>>> lazy relationships after a) the EJB transaction has already ended and
>>>>> b) the entities have been explicitly detached? That's not at all what
>>>>> I would be assuming
>>>>> 2. If I redo the same method call, Eclipselink logs show that SQL
>>>>> queries go to database to fetch the Employers, but there's no SQL for
>>>>> the persons on the second go. Seems like the persons come from some
>>>>> 2nd level cache or something? How does this work, I haven't configured
>>>>> anything special related to caching? I have also noticed this in
>>>>> practise, in that direct SQL updates to DB are not visible throught
>>>>> the application. Does eclipseLink use 2nd level caching by default?
>>>>>
>>>>>
>>>>> On Tue, Sep 14, 2010 at 4:47 PM, Tom Ware <[hidden email]> wrote:
>>>>>>
>>>>>> Hi Janne,
>>>>>>
>>>>>>  Where in your code do you see the relationships traversed?  You can
>>>>>> turn
>>>>>> on
>>>>>> EclipseLink logging (persistence unit property:
>>>>>> eclipselink.logging.level=FINEST) to see all of the logging.  When do
>>>>>> you
>>>>>> see the SQL that traverses the relationship?
>>>>>>
>>>>>>  EclipseLink has some functionality that allows LAZY relationships to
>>>>>> be
>>>>>> traversable after detachment if the connection is available.  I am
>>>>>> wondering
>>>>>> if you are seeing that functionality in action.
>>>>>>
>>>>>> -Tom
>>>>>>
>>>>>> janne postilista wrote:
>>>>>>>
>>>>>>> Hi,
>>>>>>>
>>>>>>> I'm using Eclipselink to provide JPA. I'm using GlassFish 3.0.1.
>>>>>>>
>>>>>>> I have a some simple Employer and Person entities with many-to-many
>>>>>>> (using join table) and one-to-many relationships. I want to have the
>>>>>>> relationships lazy loaded, but it looks like they are always eagerly
>>>>>>> loaded. I am aware that lazy/eager is just a hint to the JPA
>>>>>>> implementation, but I'm thinking that lazy loading is probably
>>>>>>> supposed to work with Eclipselink?
>>>>>>>
>>>>>>> Entities are along the lines of (likely irrelevant lines omitted):
>>>>>>>
>>>>>>>
>>>>>>> @Entity
>>>>>>> @NamedQueries({
>>>>>>>  @NamedQuery(name = "Employer.findAllLatest2", query = "select o
>>>>>>> from Employer o"),
>>>>>>> })
>>>>>>> public class Employer implements Serializable {
>>>>>>>  @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
>>>>>>>  @JoinTable(name = "EMPLOYER_PERSON", joinColumns =
>>>>>>>  @JoinColumn(name = "EMPLOYER_ID"), inverseJoinColumns =
>>>>>>>  @JoinColumn(name = "PERSON_ID"))
>>>>>>>  private Set<Person> persons;
>>>>>>>
>>>>>>>  @ManyToOne(fetch = FetchType.LAZY)
>>>>>>>  @JoinColumn(name = "BOSS_ID")
>>>>>>>  private Person boss;
>>>>>>> }
>>>>>>>
>>>>>>> @Entity
>>>>>>> @NamedQueries({
>>>>>>>  @NamedQuery(name = "EmployerPerson.findAll", query = "select o from
>>>>>>> EmployerPerson o")
>>>>>>> })
>>>>>>> @Table(name = "EMPLOYER_PERSON")
>>>>>>> @IdClass(EmployerPersonPK.class)
>>>>>>> public class EmployerPerson implements Serializable {
>>>>>>>  @Id
>>>>>>>  @Column(name="EMPLOYER_ID", nullable = false, insertable = false,
>>>>>>>          updatable = false)
>>>>>>>  private Long employerId;
>>>>>>>  @Id
>>>>>>>  @Column(name="PERSON_ID", nullable = false, insertable = false,
>>>>>>>          updatable = false)
>>>>>>>  private Long personId;
>>>>>>>  @ManyToOne
>>>>>>>  @JoinColumn(name = "EMPLOYER_ID")
>>>>>>>  private Employer employer;
>>>>>>>  @ManyToOne
>>>>>>>  @JoinColumn(name = "PERSON_ID")
>>>>>>>  private Person person;
>>>>>>> }
>>>>>>>
>>>>>>> @Entity
>>>>>>> public class Person implements Serializable {
>>>>>>>  @ManyToMany(mappedBy="persons")
>>>>>>>  private Set<Employer> employers;
>>>>>>>
>>>>>>> @Stateless
>>>>>>> @LocalBean
>>>>>>> @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
>>>>>>> public class EmployerService {
>>>>>>>
>>>>>>>  @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
>>>>>>>  public List<Employer> findAll() {
>>>>>>>      String namedQuery = "Employer.findAllLatest2";
>>>>>>>      }
>>>>>>>      List<Employer> employers = em.createNamedQuery(namedQuery,
>>>>>>> Employer.class).getResultList();
>>>>>>>      for (Employer e: employers) {
>>>>>>>          em.detach(e);
>>>>>>>      }
>>>>>>>      return employers;
>>>>>>>  }
>>>>>>>
>>>>>>> Now, when I use findAll(), I would expect that Employer objects do
>>>>>>> not
>>>>>>> have the person references fecthed. But they are. Accessing persons
>>>>>>> succeeds even though I did add (extraneous) detach() -calls to make
>>>>>>> sure the entities are detached after returning from findAll().
>>>>>>> _______________________________________________
>>>>>>> eclipselink-users mailing list
>>>>>>> [hidden email]
>>>>>>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>>>>>>
>>>>>> _______________________________________________
>>>>>> eclipselink-users mailing list
>>>>>> [hidden email]
>>>>>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>>>>>>
>>>>> _______________________________________________
>>>>> eclipselink-users mailing list
>>>>> [hidden email]
>>>>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>>>>
>>>> _______________________________________________
>>>> eclipselink-users mailing list
>>>> [hidden email]
>>>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>>>>
>> _______________________________________________
>> eclipselink-users mailing list
>> [hidden email]
>> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>
> _______________________________________________
> eclipselink-users mailing list
> [hidden email]
> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>
_______________________________________________
eclipselink-users mailing list
[hidden email]
https://dev.eclipse.org/mailman/listinfo/eclipselink-users