-->
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.  [ 6 posts ] 
Author Message
 Post subject: Lazy initialization and Table per hierarchy
PostPosted: Thu Dec 08, 2005 5:44 pm 
Newbie

Joined: Tue Feb 08, 2005 3:30 am
Posts: 6
Location: Bangalore
Hello there!

I am trying to implement the "table per class hierarchy. I have a class and 3 subclasses of the classes.

The parent class
Code:
public class Unit implements Serializable {

    private Long id;
    private Set relatedUnits = new HashSet();
    private Set keywords = new HashSet();
    private List faqs = new ArrayList();

...
}

Then I have 4 subclasses of Unit as follows

Code:
public class Product extends Unit {
private String name;
    private String description;
    private String longDescription;
    private String attributes;
    private String additionalInfo;
    private BigDecimal cost;
    private BigDecimal salePrice;
    private BigDecimal subPrice;
    private Set categories = new HashSet();
    private Set products = new HashSet(); //related products
...

}


Code:
public class Category extends Unit {

    private String name;
    private String description;
    private String longDescription;
    private String additionalInfo;
    private String image;
    private String thumbnail;
    //Relationship
    private Set products = new HashSet();
    private Set suites = new HashSet();
    private Catalog catalog;
...
...

}


Code:
public class Suite extends Unit {

    private String name;
    private String description;
    private String longDescription;
    private String additionalInfo;
    private String image;
    private String thumbnail;
    private BigDecimal num0;
    private BigDecimal num1;
    private BigDecimal num2;
    //Relationships
    private Set products = new HashSet();
    private Set categories = new HashSet();
...
...
}


Code:
public class Coupon extends Unit {

    private String     code;
    private String     description;
    private String     discountType;
//Relationship
    private Set products = new HashSet();
....
}


The complete listing of the Unit.hbm.xml file is as below

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
    PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>

    <class name="com.lbkgroup.businessobjects.Unit" table="UNIT">

        <id name="id" column="ID" type="long" unsaved-value="null">
            <generator class="hilo"/>
        </id>

        <discriminator column="RELATIONSHIP_TYPE" type="string"/>

        <set name="keywords"  inverse="false" lazy="true"
             table="UNIT_KEYWORD_LINK">
             <key column="UNIT_ID"/>
             <many-to-many class="com.lbkgroup.businessobjects.Keywords" column="KEYWORD_ID"/>
        </set>

        <list name="faqs" 
           inverse="true">
           <key column="UNIT_ID"/>
           <index column="SEQUENCE_NUMBER"/>
           <one-to-many class="com.lbkgroup.businessobjects.Faq"/>
        </list>

        <set name="relatedUnits"  inverse="false" lazy="true"
        table="UNIT_BINDING" >
        <key column="SOURCE_ID"/>
        <many-to-many class="com.lbkgroup.businessobjects.Unit" column="DESTINATION_ID"/>
   </set>
<!-- inverse was true -->
        <set name="customers"  lazy="true"
             inverse="false"
             cascade="save-update">
             <key column="UNIT_ID"/>
             <one-to-many class="com.lbkgroup.businessobjects.Customer"/>
        </set>

<!-- inverse was true -->
        <set name="salesOrders" lazy="true"
             inverse="false"
             cascade="save-update">
             <key column="UNIT_ID"/>
             <one-to-many class="com.lbkgroup.businessobjects.SalesOrder"/>
        </set>

        <subclass name="com.lbkgroup.businessobjects.Category" discriminator-value="CATEGORY">
            <property name="name">
                <column name="NAME" />
            </property>

            <property name="description">
                <column name="DESCRIPTION" />
            </property>

            <property name="longDescription">
                <column name="LONG_DESCRIPTION" />
            </property> 
   
          <property name="additionalInfo">
                <column name="ADDITIONAL_INFO" />
            </property>

           <property name="image">
               <column name="IMAGE" />
           </property>       

           <property name="thumbnail">
               <column name="THUMBNAIL" />
           </property>
   
           <property name="customField1">
              <column name="CUSTOM_FIELD1" />
           </property>
   
         <property name="customField2">
              <column name="CUSTOM_FIELD2" />
          </property>
   
        <property name="customField3">
               <column name="CUSTOM_FIELD3" />
          </property>
   
     <property name="customField4">
               <column name="CUSTOM_FIELD4" />
          </property>

          <!--Category has  products -->
          <set name="products"  inverse="true" lazy="true"
        table="UNIT_BINDING" >
        <key column="SOURCE_ID"/>
        <many-to-many class="com.lbkgroup.businessobjects.Product" column="DESTINATION_ID"/>
     </set>

          <!--Category has  suites -->
          <set name="suites"  inverse="true" lazy="true"
        table="UNIT_BINDING" >
        <key column="SOURCE_ID"/>
        <many-to-many class="com.lbkgroup.businessobjects.Suite" column="DESTINATION_ID"/>
     </set>

     <many-to-one name="catalog"
                column="CATALOG_ID"
           class="com.lbkgroup.businessobjects.Catalog" />
        </subclass>

        <subclass name="com.lbkgroup.businessobjects.Suite" discriminator-value="SUITE">
            <property name="name">
                <column name="NAME" />
            </property>

            <property name="description">
                <column name="DESCRIPTION" />
            </property>

            <property name="longDescription">
                <column name="LONG_DESCRIPTION" />
            </property> 
   
          <property name="additionalInfo">
                <column name="ADDITIONAL_INFO" />
            </property>

           <property name="image">
               <column name="IMAGE" />
           </property>       

           <property name="thumbnail">
               <column name="THUMBNAIL" />
           </property>

     <property name="num0">
             <column name="NUM0" />
          </property>

        <property name="num1">
             <column name="NUM1" />
          </property>

     <property name="num2">
              <column name="NUM2" />
          </property>

     <property name="num3">
              <column name="NUM3" />
          </property>

     <property name="strA">
            <column name="STR_A" />
          </property>

     <property name="strB">
              <column name="STR_B" />
          </property>

     <property name="strC">
              <column name="STR_C" />
          </property>

     <property name="strD">
              <column name="STR_D" />
          </property>
     <property name="sku">
              <column name="SKU" />
          </property>

     <property name="onhandQuantity">
              <column name="ONHAND_QUANTITY" />
          </property>
     <property name="inventoryThreshold">
              <column name="INVENTORY_THRESHOLD" />
          </property>
     <property name="customField4">
               <column name="CUSTOM_FIELD4" />
          </property>

          <!--Suite has products -->
          <set name="products"  inverse="false" lazy="true"
        table="UNIT_BINDING" >
        <key column="SOURCE_ID"/>
        <many-to-many class="com.lbkgroup.businessobjects.Product" column="DESTINATION_ID"/>
     </set>

        <!--Suite belongs to categories  -->
        <set name="categories"  inverse="false" lazy="true"
        table="UNIT_BINDING" >
        <key column="DESTINATION_ID"/>
        <many-to-many class="com.lbkgroup.businessobjects.Category" column="SOURCE_ID"/>
   </set>
        </subclass>

        <subclass name="com.lbkgroup.businessobjects.Coupon" discriminator-value="COUPON">
            <property name="code">
                <column name="NAME" />
            </property>

            <property name="description">
                <column name="DESCRIPTION" />
            </property>

       <property name="discountType">
              <column name="STR_A" />
            </property>

       <property name="discountAmount">
               <column name="NUM0" />
            </property>

          <property name="comparator">
               <column name="NUM1" />
            </property>

       <property name="couponType">
              <column name="STR_B" />
            </property>

            <!--Coupon has products -->
            <set name="products"  inverse="false" lazy="true"
          table="UNIT_BINDING" >
          <key column="SOURCE_ID"/>
          <many-to-many class="com.lbkgroup.businessobjects.Product" column="DESTINATION_ID"/>
       </set>

        </subclass>

        <subclass name="com.lbkgroup.businessobjects.Product" discriminator-value="PRODUCT">
           <property name="name">
            <column name="NAME" />
           </property>

           <property name="description">
               <column name="DESCRIPTION" />
           </property>

           <property name="longDescription">
               <column name="LONG_DESCRIPTION" />
           </property>       
   
      <property name="attributes">
            <column name="STR_D" />
           </property>

      <property name="additionalInfo">
            <column name="ADDITIONAL_INFO" />
           </property>
   
      <property name="cost">
               <column name="NUM0" />
           </property>
   
      <property name="salePrice">
            <column name="NUM1" />
           </property>
   
      <property name="subPrice">
            <column name="NUM2" />
           </property>
   
      <property name="quantity">
              <column name="ONHAND_QUANTITY" />
           </property>
   
      <property name="sku">
               <column name="SKU" />
           </property>

           <property name="image1">
            <column name="IMAGE" />
           </property>
   
      <property name="image2">
            <column name="STR_A" />
           </property>
   
      <property name="image3">
            <column name="STR_B" />
           </property>

           <property name="thumbnail">
            <column name="THUMBNAIL" />
           </property>
   
      <property name="inventoryThreshold">
               <column name="INVENTORY_THRESHOLD" />
           </property>
   
      <property name="customField1">
               <column name="CUSTOM_FIELD1" />
           </property>
   
           <property name="customField2">
               <column name="CUSTOM_FIELD2" />
           </property>
   
      <property name="customField3">
            <column name="CUSTOM_FIELD3" />
           </property>

      <property name="customField4">
            <column name="CUSTOM_FIELD4" />
           </property>

           <!--Product has related products -->
           <set name="products"  inverse="false" lazy="true"
              table="UNIT_BINDING" >
              <key column="DESTINATION_ID"/>
              <many-to-many class="com.lbkgroup.businessobjects.Product" column="SOURCE_ID"/>
         </set>

           <!--Product has categories  -->
           <set name="categories" inverse="false" lazy="true"
              table="UNIT_BINDING" >
              <key column="DESTINATION_ID"/>
           <many-to-many class="com.lbkgroup.businessobjects.Category" column="SOURCE_ID"/>
         </set>

      <many-to-one name="vendor"
                column="VENDOR_ID"
           class="com.lbkgroup.businessobjects.Vendor"/>
            
           <many-to-one name="warehouse"
                column="WAREHOUSE_ID"
           class="com.lbkgroup.businessobjects.Warehouse"/>

        </subclass>
    </class>
   
</hibernate-mapping>



If lazy = "false" hibernate gives the below error
Code:

net.sf.hibernate.WrongClassException: Object with id: 490010 was not of the specified subclass: com.lbkgroup.businessobjects.Category (loaded object was of wrong class)

hibernate should get the records based on the discriminator values, doesn't it suppose to do that?.

But, If I have lazy = "true" hibernate would get the records from the database (distinguished) by the discriminator value (which is what I want), So, I got by this problem by adding the lazy="true" , but If I go to product details and category details then it would give me

Code:
et.sf.hibernate.LazyInitializationException: Failed to lazily initialize a collection - no session or session was closed
        at net.sf.hibernate.collection.PersistentCollection.initialize(PersistentCollection.java:209)
        at net.sf.hibernate.collection.PersistentCollection.read(PersistentCollection.java:71)
        at net.sf.hibernate.collection.Set.iterator(Set.java:130)
        at org.apache.jsp.pages.layouts.categoryLayout_jsp._jspService(categoryLayout_jsp.java:99)
        at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:94)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
        at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:324)
        at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292)
        at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
        at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:704)
        at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:590)
        at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:510)
        at org.apache.jasper.runtime.JspRuntimeLibrary.include(JspRuntimeLibrary.java:966)
        at org.apache.jasper.runtime.PageContextImpl.include(PageContextImpl.java:581)
        at org.apache.struts.tiles.TilesUtilImpl.doInclude(TilesUtilImpl.java:137)
        at org.apache.struts.tiles.TilesUtil.doInclude(TilesUtil.java:177)
        at org.apache.struts.taglib.tiles.InsertTag.doInclude(InsertTag.java:756)
        at org.apache.struts.taglib.tiles.InsertTag$InsertHandler.doEndTag(InsertTag.java:881)
        at org.apache.struts.taglib.tiles.InsertTag.doEndTag(InsertTag.java:473)
        at org.apache.jsp.pages.categoryView_jsp._jspx_meth_tiles_insert_0(categoryView_jsp.java:141)
        at org.apache.jsp.pages.categoryView_jsp._jspService(categoryView_jsp.java:91)
        at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:94)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
        at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:324)
        at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292)
        at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
        at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:704)
        at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:474)


Please help me, I spend 3 days on this.


Thanks in advance


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 09, 2005 2:00 am 
Regular
Regular

Joined: Thu Oct 27, 2005 8:06 am
Posts: 55
Location: München, Germany
I didn't study your mapping too closely, because your lazy initialization exception most probably has nothing to do with your mapping details. Otherwise I would have questioned those parts of the mapping around those "inverse was true" comments.

The lazy init error most probably has the following cause. You had some object handled by Hibernate in a previous session. It was maybe created, or loaded from the database, and possibly stored. Then the Hibernate session ended, but you kept the object itself in memory, which made it detached from Hibernate's standpoint.

Now, as you still have the object in memory, you try to access a reference to another object, and you rely on Hibernate's lazy loading mechanism to get that object for you. However, the original object isn't under Hibernate's control any more. That's what the error message indicates.

To resolve this, either get rid of the original object after closing the first Hibernate session, and get it again from the data base in the second. This is often recommended in the literature, in particular for web applications, as it will clear those lots of sleeping objects from memory in your server. If you can afford to keep it there, just issue a Hibernate lock operation on this object rather early, before any of your application code can get the idea to change it or access its object references.

After having resolved this, you might try to turn lazy loading off again and look whether the original error disappears. I'm not sure whether that was also caused by that session problem.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 09, 2005 6:02 am 
Newbie

Joined: Tue Feb 08, 2005 3:30 am
Posts: 6
Location: Bangalore
Hi Thomas,

Thanks for your reply,

The point that the code breaks is when I try to get the products from the category like [code]category.getProducts()[\code]

There are 2 issues here

1. Hibernate doesn't distinguish the records in the Unit table wihout lazy=true.

2. When I set lazy = "true" then it has problem creating the object tree.

with lazy="true" I am able to get the categories by an HQL query.

select category from com.lbkgroup.businessobjecs.Category

now with the category object, if I say category.getProduct(), it give me the error with the session being closed or not open.

Why would hibernate detach the object instance and not create the object map? This is strange unless I am missing something.

Is there any param that I need to set like the cache usage= "read-write"?

Can you point me to some literature? The book "Hibernate in Action" doesn't talk much about the 'Table per hierarchy' implementation.

Thanks in advance


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 12, 2005 6:37 pm 
Regular
Regular

Joined: Thu Oct 27, 2005 8:06 am
Posts: 55
Location: München, Germany
Your basic problem is working with detached objects without re-attaching them. This has nothing to do with table per hierarchy. The part in Hibernate in Action to read would mostly be chapter 4 about transient, persistent, and detached objects, and part of chapter 5 talking about transactions and sessions.

Somewhere in your application you closed the session that was handling the object, and outside of this session you try to use Hibernate's lazy loading mechanism. This isn't allowed, as lazy loading means getting the associated object from the database, which is unsafe unless it's done in a transaction.

Do you use a framework like Spring? I ask this question because in that case, all that session/transaction stuff is handled implicitly for you. So you might be lulled into thinking that sessions and transactions aren't relevant any more. In fact, you have to find out where your session ends, and start another one (e.g. by locking the root object of your object graph) before trying lazy evaluation.


Top
 Profile  
 
 Post subject: try Hibernate.initialize(Object)
PostPosted: Tue Dec 13, 2005 10:07 am 
Beginner
Beginner

Joined: Wed Feb 23, 2005 10:26 am
Posts: 22
when you
retrieve your Categrory object
you could add this line
Hibernate.initialize(category.getProducts)
before ending your transaction or closing your session.

Then in your code you have access to the Collection and will hopefully not give you this error


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 14, 2005 2:21 pm 
Newbie

Joined: Tue Feb 08, 2005 3:30 am
Posts: 6
Location: Bangalore
yes, that was it!. Thank you everybody for sharing the thoughts

For the benefit of others, This point is mentioned in the book on page 151.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 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.