Lazy loading can operate when persistence context is closed?

View: New views
4 Messages — Rating Filter:   Alert me  

Lazy loading can operate when persistence context is closed?

by fcalfo :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Doesn't the persistence context have to be open for a lazy loaded collection to be fetched?

I thought if the persistence context was closed and you attempted to get a lazy loaded collection, you'd get a lazy load exception?  (is that just with Hibernate?)

I ran this bare bones test and my final assertion fails unexpectedly since when I call
contract.getSupplierContracts it actual fires the SQL query to get the collection without error even though the persistence context is closed (and I even committed the xact just to make sure the loop was closed)

I am making sure to run the static weaver (org.eclipse.persistence.tools.weaving.jpa.StaticWeave) before running my test.

Why is the collection being lazy loaded even when the persistence context is closed???

I'm using EclipseLink 1.1.1, JPA 1.0, against Oracle 10g, on Java SE 6

Here's my persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
        <persistence-unit name="JPASpike" transaction-type="RESOURCE_LOCAL">
                <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
                <class>jpa.Contract</class>
                <class>jpa.SupplierContract</class>
                <class>jpa.Supplier</class>
                <exclude-unlisted-classes>true</exclude-unlisted-classes>
                <properties>
                        <property name="eclipselink.jdbc.driver" value="oracle.jdbc.OracleDriver"/>
                        <property name="eclipselink.jdbc.read-connections.min" value="1"/>
                        <property name="eclipselink.jdbc.read-connections.max" value="2"/>
                        <property name="eclipselink.jdbc.write-connections.min" value="1"/>
                        <property name="eclipselink.jdbc.write-connections.max" value="2"/>
                        <property name="eclipselink.weaving" value="static"/>
                        <property name="eclipselink.weaving.lazy" value="true"/>
                        <property name="eclipselink.weaving.fetchgroups" value="false"/>
                        <property name="eclipselink.weaving.changetracking" value="false"/>
                        <property name="eclipselink.orm.throw.exceptions" value="true"/>
                        <property name="eclipselink.logging.level" value="FINE"/>
                        <property name="eclipselink.logging.logger" value="DefaultLogger"/>
                        <property name="eclipselink.target-database" value="Oracle"/>
                </properties>
        </persistence-unit>
</persistence>

Here's a fragment of my mapping with lazy load configured:

    @OneToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "SUPPLIER_CONTRACT", joinColumns = @JoinColumn(name = "CONTRACTID", referencedColumnName = "CONTRACTID"), inverseJoinColumns = @JoinColumn(name = "SUPPLIERID", referencedColumnName = "SUPPLIERID"))
    private List<SupplierContract> supplierContracts = new ArrayList<SupplierContract>();

And here's my test:

        Integer contractId = 101;
        Contract contract = null;
        EntityManager em = Persistence.createEntityManagerFactory("JPASpike").createEntityManager();
        EntityTransaction tx = em.getTransaction();

        try
        {
            tx.begin();
            System.out.println("### find contract");
            contract = em.find(Contract.class, contractId);
            tx.commit();
            assertNotNull("Contract should be found with id: " + contractId, contract);
            assertEquals("contract id", contractId, contract.getId());
        }
        catch (Exception e)
        {
            System.out.println("Persistence failed: " + e);
            e.printStackTrace();
            if (tx != null)
                tx.rollback(); // TODO this is failing with IllegalStateException no xact is active
            fail("Persistence failed: " + e);
        }
        finally
        {
            System.out.println("### finally");
            if (em != null)
                em.close();
        }

        // Now, outside of the persistence context, make sure the collection is not populated
        System.out.println("### verify collection not populated");
        System.out.println("### em is open: " + em.isOpen());
        assertTrue("collection should be empty after initial get", contract.getSupplierContracts().isEmpty());

Re: Lazy loading can operate when persistence context is closed?

by fcalfo :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


fcalfo wrote:
Doesn't the persistence context have to be open for a lazy loaded collection to be fetched?

I am making sure to run the static weaver (org.eclipse.persistence.tools.weaving.jpa.StaticWeave) before running my test.

More info on this: while inspecting the Contract.class file after the static weaver was applied, it looks like
it didn't weave in the lazy loading.

Here's the class definition from the class file after StaticWeave was run:

public class jpa.Contract implements java.lang.Cloneable, org.eclipse.persistence.internal.weaving.PersistenceWeaved, org.eclipse.persistence.internal.descriptors.PersistenceEntity, org.eclipse.persistence.internal.descriptors.PersistenceObject {

It did something since it added the PersistenceWeaved interface

but it should have also added the PersistenceWeavedLazy interface.

Why didn't it add that even though I added the lazy fetch type on the supplierContracts collection and the eclipselink.weaving.lazy property is set to true?

(I do have this working on another class so I'm wondering what I'm missing here)

Re: Lazy loading can operate when persistence context is closed?

by christopher delahunt :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

That is just with Hibernate.  EclipseLink/TopLink has a feature to allow
loading entities as described by Doug:
  http://forums.oracle.com/forums/thread.jspa?messageID=1706796

So you can still access lazy loaded attributes as long as the entity has
not been serialized.

Best Regards,
Chris

fcalfo wrote:

> Doesn't the persistence context have to be open for a lazy loaded collection
> to be fetched?
>
> I thought if the persistence context was closed and you attempted to get a
> lazy loaded collection, you'd get a lazy load exception?  (is that just with
> Hibernate?)
>
> I ran this bare bones test and my final assertion fails unexpectedly since
> when I call
> contract.getSupplierContracts it actual fires the SQL query to get the
> collection without error even though the persistence context is closed (and
> I even committed the xact just to make sure the loop was closed)
>
> I am making sure to run the static weaver
> (org.eclipse.persistence.tools.weaving.jpa.StaticWeave) before running my
> test.
>
> Why is the collection being lazy loaded even when the persistence context is
> closed???
>
> I'm using EclipseLink 1.1.1, JPA 1.0, against Oracle 10g, on Java SE 6
>
> Here's my persistence.xml
>
> <?xml version="1.0" encoding="UTF-8"?>
> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
> http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
> <persistence-unit name="JPASpike" transaction-type="RESOURCE_LOCAL">
> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
> <class>jpa.Contract</class>
> <class>jpa.SupplierContract</class>
> <class>jpa.Supplier</class>
> <exclude-unlisted-classes>true</exclude-unlisted-classes>
> <properties>
> <property name="eclipselink.jdbc.driver"
> value="oracle.jdbc.OracleDriver"/>
> <property name="eclipselink.jdbc.read-connections.min" value="1"/>
> <property name="eclipselink.jdbc.read-connections.max" value="2"/>
> <property name="eclipselink.jdbc.write-connections.min" value="1"/>
> <property name="eclipselink.jdbc.write-connections.max" value="2"/>
> <property name="eclipselink.weaving" value="static"/>
> <property name="eclipselink.weaving.lazy" value="true"/>
> <property name="eclipselink.weaving.fetchgroups" value="false"/>
> <property name="eclipselink.weaving.changetracking" value="false"/>
> <property name="eclipselink.orm.throw.exceptions" value="true"/>
> <property name="eclipselink.logging.level" value="FINE"/>
> <property name="eclipselink.logging.logger" value="DefaultLogger"/>
> <property name="eclipselink.target-database" value="Oracle"/>
> </properties>
> </persistence-unit>
> </persistence>
>
> Here's a fragment of my mapping with lazy load configured:
>
>     @OneToMany(fetch = FetchType.LAZY)
>     @JoinTable(name = "SUPPLIER_CONTRACT", joinColumns = @JoinColumn(name =
> "CONTRACTID", referencedColumnName = "CONTRACTID"), inverseJoinColumns =
> @JoinColumn(name = "SUPPLIERID", referencedColumnName = "SUPPLIERID"))
>     private List<SupplierContract> supplierContracts = new
> ArrayList<SupplierContract>();
>
> And here's my test:
>
>         Integer contractId = 101;
>         Contract contract = null;
>         EntityManager em =
> Persistence.createEntityManagerFactory("JPASpike").createEntityManager();
>         EntityTransaction tx = em.getTransaction();
>
>         try
>         {
>             tx.begin();
>             System.out.println("### find contract");
>             contract = em.find(Contract.class, contractId);
>             tx.commit();
>             assertNotNull("Contract should be found with id: " + contractId,
> contract);
>             assertEquals("contract id", contractId, contract.getId());
>         }
>         catch (Exception e)
>         {
>             System.out.println("Persistence failed: " + e);
>             e.printStackTrace();
>             if (tx != null)
>                 tx.rollback(); // TODO this is failing with
> IllegalStateException no xact is active
>             fail("Persistence failed: " + e);
>         }
>         finally
>         {
>             System.out.println("### finally");
>             if (em != null)
>                 em.close();
>         }
>
>         // Now, outside of the persistence context, make sure the collection
> is not populated
>         System.out.println("### verify collection not populated");
>         System.out.println("### em is open: " + em.isOpen());
>         assertTrue("collection should be empty after initial get",
> contract.getSupplierContracts().isEmpty());
>
>  
_______________________________________________
eclipselink-users mailing list
eclipselink-users@...
https://dev.eclipse.org/mailman/listinfo/eclipselink-users

Re: Lazy loading can operate when persistence context is closed?

by tware :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

   The JPA specification does not specify what the persistence provider should
do to lazy relationships when the persistence context is closed.  EclipseLink
has chosen to retrieve them when possible.

   Our implementation of lazy relationships for xToMany relationships does not
require the use of weaving.  We, instead, use a subclass of your collection
class.  (In your case we use a class called IndirectList - if you want, you can
take a look at it in the source to see what it does.)

-Tom

fcalfo wrote:

>
>
> fcalfo wrote:
>> Doesn't the persistence context have to be open for a lazy loaded
>> collection to be fetched?
>>
>> I am making sure to run the static weaver
>> (org.eclipse.persistence.tools.weaving.jpa.StaticWeave) before running my
>> test.
>>
>>
>
>
> More info on this: while inspecting the Contract.class file after the static
> weaver was applied, it looks like
> it didn't weave in the lazy loading.
>
> Here's the class definition from the class file after StaticWeave was run:
>
> public class jpa.Contract implements java.lang.Cloneable,
> org.eclipse.persistence.internal.weaving.PersistenceWeaved,
> org.eclipse.persistence.internal.descriptors.PersistenceEntity,
> org.eclipse.persistence.internal.descriptors.PersistenceObject {
>
> It did something since it added the PersistenceWeaved interface
>
> but it should have also added the PersistenceWeavedLazy interface.
>
> Why didn't it add that even though I added the lazy fetch type on the
> supplierContracts collection and the eclipselink.weaving.lazy property is
> set to true?
>
> (I do have this working on another class so I'm wondering what I'm missing
> here)
_______________________________________________
eclipselink-users mailing list
eclipselink-users@...
https://dev.eclipse.org/mailman/listinfo/eclipselink-users