-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Iterating over a collection
PostPosted: Tue Nov 22, 2005 1:19 pm 
Regular
Regular

Joined: Wed Sep 10, 2003 2:26 pm
Posts: 56
Location: San Diego, CA
I'm including as much relevent information as makes sense below, but here's the gist: using hibernate 4.0.x in a Swing application. Because it's a Swing application, I'm trying to load the entire object graph into memory upfront, i.e. I turn off all lazy loading.

My Payee object is mapped to a collection of payment objects. When the collection is set on a payee object, I want to iterate over it and register a PropertyChangeSupport with every payment bean in the collection as well as calculate some totals:

Code:
   public void setPayments(Set payments)
   {
      if( this.payments == payments )
         return;

      unregisterUpdateListeners(this.payments);
      if( observablePayments != null )
         observablePayments.getHandler().removePostModificationListener(paymentsListener);

      this.payments = payments;
      this.observablePayments = ObservableSet.decorate(payments);

      paymentsListener = new PaymentsListener();

      if( observablePayments != null)
         observablePayments.getHandler().addPostModificationListener(paymentsListener);
      registerUpdateListeners(payments);

      updateDosCodeTotals();
   }


the setPayments method above is mapped to the payments property in OlzPayments.hbm.xml

Code:
      <set name="payments" cascade="all-delete-orphan" fetch="join" inverse="true">
         <key column="payee_id"/>
         <one-to-many class="edu.ucsd.som.onlinez.business.OlzPaymentDetail"/>
      </set>
(also see below)

The problem is (and this development is recent, I didn't use to have this issue before I upgraded from 2.x), that when setPayments is being called I get "LazyInitializationException: illegal access to loading collection"

I understand that the root cause of it is that the collection passed to setPayments isn't being finished initializing. But here's a list a questions I'd like to get answers to:

1) Why is it a LayInitializationException when I don't do any lazy loading?
2) Why would Hibernate give me an unitialized collection? Is there a way to tell it not to?
3) How do I change the design to work around this problem? How do I find out when a collection is done loading and do the necessary housekeeping stuff.
4) How do I do the above and still keep the business layer unaware of Hibernate and all the persistence related shenanigans ?


Thanks
Dmitry

Hibernate version:
3.0.5
Mapping documents:
Code:
<hibernate-mapping>
   <class name="edu.ucsd.som.onlinez.business.OlzPayee" table="olz_payee" where="current_pay_period='true'" lazy="false">

      <cache usage="read-write"/>

      <id name="_id" column="payee_id">
         <generator class="native"/>
      </id>

      <many-to-one name="payrollTitle" column="title_code"
            class="edu.ucsd.som.business.PayrollTitle" fetch="join"  update="false"/>

      <many-to-one name="employee" column="ucsd_id"
           class="edu.ucsd.som.business.payments.PaymentEmployee" access="field"
         fetch="join" update="false" />
      <many-to-one name="division" column="division_id"
           class="edu.ucsd.som.onlinez.business.OlzDivision"
         update="false" fetch="join" />

      <set name="payments" cascade="all-delete-orphan" fetch="join" inverse="true">
         <key column="payee_id"/>
         <one-to-many class="edu.ucsd.som.onlinez.business.OlzPaymentDetail"/>
      </set>
   </class>
</hibernate-mapping>

Code:
<hibernate-mapping>
   <class name="edu.ucsd.som.onlinez.business.OlzPaymentDetail" table="olz_pmnt_detail" where="dos_code='BYZ'" lazy="false">
      <id name="_id" column="detail_id" type="long">
         <generator class="native"/>
      </id>

      <version name="lastUpdate" column="update_ts" type="timestamp"/>

      <property name="index" column="index_num" type="string" access="field"/>
      <property name="amount" column="amount" type="float" access="field"/>
      <property name="preloadable" column="preloadable" type="boolean"/>
      <property name="employeeId" column="employee_id" type="string"/>

      <many-to-one name="payPeriod" column="pay_period_id"
           class="edu.ucsd.som.business.PayPeriod" access="field" fetch="join" />
      <many-to-one name="dosCode" column="dos_code"
           class="edu.ucsd.som.business.DosCode" fetch="join" />
      <many-to-one name="payee" column="payee_id"
           class="edu.ucsd.som.onlinez.business.OlzPayee" fetch="join" />
      <many-to-one name="owner" column="owner_id"
           class="edu.ucsd.som.portal.PortalUser" fetch="join" />

      <many-to-one name="olzType" column="z_type_id" fetch="join" />
   </class>
</hibernate-mapping>

Code between sessionFactory.openSession() and session.close():

Full stack trace of any exception that occurs:
Quote:
edu.ucsd.som.util.DataStoreLoadException: org.hibernate.PropertyAccessException: Exception occurred inside setter of edu.ucsd.som.onlinez.business.OlzPayee.payments
at edu.ucsd.som.hibernate.AbstractHibernate3DataStore.load(AbstractHibernate3DataStore.java:191)
at edu.ucsd.som.util.PersistentObject.load(PersistentObject.java:194)
at edu.ucsd.som.onlinez.business.TestOlzPayee.testLoad(TestOlzPayee.java:22)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at com.intellij.rt.execution.junit2.JUnitStarter.main(JUnitStarter.java:31)
Caused by: org.hibernate.PropertyAccessException: Exception occurred inside setter of edu.ucsd.som.onlinez.business.OlzPayee.payments
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:51)
at org.hibernate.tuple.AbstractTuplizer.setPropertyValues(AbstractTuplizer.java:207)
at org.hibernate.tuple.PojoTuplizer.setPropertyValues(PojoTuplizer.java:176)
at org.hibernate.persister.entity.BasicEntityPersister.setPropertyValues(BasicEntityPersister.java:2919)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:113)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:530)
at org.hibernate.loader.Loader.doQuery(Loader.java:436)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:218)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1345)
at org.hibernate.loader.entity.EntityLoader.load(EntityLoader.java:116)
at org.hibernate.loader.entity.EntityLoader.load(EntityLoader.java:101)
at org.hibernate.persister.entity.BasicEntityPersister.load(BasicEntityPersister.java:2471)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:351)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:332)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:113)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:151)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:79)
at org.hibernate.impl.SessionImpl.load(SessionImpl.java:603)
at org.hibernate.impl.SessionImpl.load(SessionImpl.java:596)
at edu.ucsd.som.hibernate.AbstractHibernate3DataStore.load(AbstractHibernate3DataStore.java:183)
... 20 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:40)
... 39 more
Caused by: org.hibernate.LazyInitializationException: illegal access to loading collection
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:172)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:48)
at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:134)
at edu.ucsd.som.business.payments.Payee.registerUpdateListeners(Payee.java:158)
at edu.ucsd.som.business.payments.Payee.setPayments(Payee.java:104)
at edu.ucsd.som.onlinez.business.OlzPayee.setPayments(OlzPayee.java:56)
... 44 more

Name and version of the database you are using:
MySQL 4.0

The generated SQL (show_sql=true):
Quote:
[main] DEBUG org.hibernate.SQL - select olzpayee0_.payee_id as payee1_11_, olzpayee0_.title_code as title2_13_11_, olzpayee0_.ucsd_id as ucsd3_13_11_, olzpayee0_.division_id as division4_13_11_, payrolltit1_.code as code0_, payrolltit1_.name as name4_0_, payrolltit1_.ttl_title_unit_code as ttl3_4_0_, payrolltit1_.ttl_personnel_program_code as ttl4_4_0_, payrolltit1_.annual_max as annual5_4_0_, payrolltit1_.annual_min as annual6_4_0_, paymentemp2_.employee_id as employee1_1_, paymentemp2_.employee_id as employee1_11_1_, paymentemp2_.last_name as last2_11_1_, paymentemp2_.first_name as first3_11_1_, paymentemp2_.annual_rate as annual4_11_1_, paymentemp2_.hire_date as hire5_11_1_, paymentemp2_.home_department_id as home6_11_1_, department3_.som_department_id as som1_2_, department3_.name as name2_2_, department3_.som_department_id as som1_2_2_, department3_.dbo_ucsd_id as dbo3_2_2_, department3_.major_group_id as major4_2_2_, olzdivisio4_.division_id as division1_3_, olzdivisio4_.name as name3_3_, olzdivisio4_.department_id as department4_3_3_, olzdepartm5_.som_department_id as som1_4_, olzdepartm5_.name as name2_4_, olzdepartm5_.som_department_id as som1_2_4_, olzdepartm5_.major_group_id as major4_2_4_, olzdepartm5_.dbo_ucsd_id as dbo3_2_4_, olzmajorgr6_.som_major_group_id as som1_5_, olzmajorgr6_.name as name1_5_, payments7_.payee_id as payee9_13_, payments7_.detail_id as detail1_13_, payments7_.detail_id as detail1_6_, payments7_.update_ts as update2_12_6_, payments7_.index_num as index3_12_6_, payments7_.amount as amount12_6_, payments7_.preloadable as preloada5_12_6_, payments7_.employee_id as employee6_12_6_, payments7_.pay_period_id as pay7_12_6_, payments7_.dos_code as dos8_12_6_, payments7_.payee_id as payee9_12_6_, payments7_.owner_id as owner10_12_6_, payments7_.z_type_id as z11_12_6_, payperiod8_.tpp_period_id as tpp1_7_, payperiod8_.tpp_period_type_code as tpp2_14_7_, payperiod8_.tpp_period_begin_date as tpp3_14_7_, payperiod8_.tpp_period_end_date as tpp4_14_7_, payperiod8_.tpp_period_pay_date as tpp5_14_7_, payperiod8_.tpp_period_cutoff_date as tpp6_14_7_, payperiod8_.tpp_period_extract_date as tpp7_14_7_, payperiod8_.som_editing_cutoff_date as som8_14_7_, payperiod8_.tpp_period_standard_hours as tpp9_14_7_, doscode9_.code as code8_, doscode9_.title as title7_8_, portaluser10_.core_user_id as core1_9_, portaluser10_.name as name8_9_, portaluser10_.first_name as first3_8_9_, portaluser10_.last_name as last4_8_9_, portaluser10_.email as email8_9_, portaluser10_.employee_id as employee6_8_9_, ztype11_.z_type_id as z1_10_, ztype11_.name as name15_10_, ztype11_.code as code15_10_ from olz_payee olzpayee0_ left outer join som_payroll_title payrolltit1_ on olzpayee0_.title_code=payrolltit1_.code left outer join pmnt_employee paymentemp2_ on olzpayee0_.ucsd_id=paymentemp2_.employee_id left outer join som_department department3_ on paymentemp2_.home_department_id=department3_.som_department_id left outer join som_division olzdivisio4_ on olzpayee0_.division_id=olzdivisio4_.division_id left outer join som_department olzdepartm5_ on olzdivisio4_.department_id=olzdepartm5_.som_department_id left outer join som_major_group olzmajorgr6_ on olzdepartm5_.major_group_id=olzmajorgr6_.som_major_group_id left outer join olz_pmnt_detail payments7_ on olzpayee0_.payee_id=payments7_.payee_id left outer join som_pay_period payperiod8_ on payments7_.pay_period_id=payperiod8_.tpp_period_id left outer join som_dos_code doscode9_ on payments7_.dos_code=doscode9_.code left outer join core_user portaluser10_ on payments7_.owner_id=portaluser10_.core_user_id left outer join som_z_type ztype11_ on payments7_.z_type_id=ztype11_.z_type_id where olzpayee0_.payee_id=? and olzpayee0_.current_pay_period='true'

Debug level Hibernate log excerpt:


Top
 Profile  
 
 Post subject: Lazyness
PostPosted: Fri Nov 24, 2006 2:30 pm 
Newbie

Joined: Mon Oct 24, 2005 6:34 pm
Posts: 14
Location: Guadalajara, Jalisco. México.
Hibernate is lazy by default (answer 1), so non lazy collections should be mapped lazy=false (answer 2), collections will be loaded non lazily (when properly mapped) by the end of your getElements() call, transparently to you (ideally) (answer 3), you can call explicit eager fetch through mappings or FETCH JOIN in HQL, all of this inside a Hibernate Session (or EJB3 Transaction) (answer 4)


... hope this helps.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.