-->
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.  [ 5 posts ] 
Author Message
 Post subject: One-to-one association with shared primary key ; N+1 selects
PostPosted: Fri Dec 21, 2007 8:59 pm 
Newbie

Joined: Thu May 24, 2007 12:13 am
Posts: 2
Hibernate version:3.2.4SP1

Car<-->Engine ( A simple one to one bidirectional association with shared primary key)

Mapping Car
---------------------------

<class name="Car" table="OS_CAR">
<id name="Id" column="ID" type="string">
<generator class="uuid"/>
</id>

<one-to-one name="Engine" cascade="merge, delete" />

</class>

Engine Mapping ( Note the generator foreign shared key, and constrained=true)
----------------------------------

<class name="Engine" table="OS_ENGINE">

<id name="Id" column="ID">
<generator class="foreign">
<param name="property">Car</param>
</generator>
</id>

<one-to-one name="Car" constrained="true" />

</class>

The case is:
If I query a Engine, however, I get a proxy for the 'Car'.
This is GOOD AND LAZY load semantics are honored from the Engine Side of the relationship

If I query a Car, using session.get(Car,id), I always get an initialized 'Engine' - It is never a proxy.

How can I specify lazy load semantics from Car side of the relationship ?
I need the Engine to be a proxy, but instead Hibernate issues a LEFT OUTER JOIN with Engine to get me the results which I dont need.

The generated SQL (show_sql=true):

select car0_.ID as ID7_1_, , engine1_.VERSION as VERSION8_0_, engine1_.SERIAL_NUMBER as SERIAL3_8_0_, engine1_.MODEL as MODEL8_0_ from OS_CAR car0_ left outer join OS_ENGINE engine1_ on car0_.ID=engine1_.ID where car0_.ID=?

Note mappings are lazy by default.

Even a simple HQL 'from Car' results in 2 SQL's
Select from CAR ---
Select from Engine ---

Why is Hibernate pre-fetching the other end of the relationship, even though the mappings say it is lazy?


Database: MySQL:


Top
 Profile  
 
 Post subject: Re: One-to-one association with shared primary key ; N+1 sel
PostPosted: Mon Dec 24, 2007 12:04 pm 
Expert
Expert

Joined: Wed Apr 11, 2007 11:39 am
Posts: 735
Location: Montreal, QC
My rough guess is that it has something to do with the primary key specification and the foreign key generator class. It might relay on the Car property at some point. What happens if you change it to assigned? I understand this will somehow increase complexity of your code depending on usage scenarios you have for these two classes.


Farzad-


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 07, 2008 6:18 pm 
Newbie

Joined: Tue Apr 17, 2007 6:17 pm
Posts: 3
I'm having the exact same issue. Did you ever find a solution?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 07, 2008 9:31 pm 
Expert
Expert

Joined: Mon Nov 26, 2007 2:29 pm
Posts: 443
try constrained="true", lazy="no proxy".

_________________
Gonzalo Díaz


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 08, 2008 5:16 pm 
Newbie

Joined: Tue Apr 17, 2007 6:17 pm
Posts: 3
Quote:
try constrained="true", lazy="no proxy"

I was hoping to not have to implement any byte-code instrumentation, which the lazy="no-proxy" requires.

In order to attempt to solve my explicit problem, allow me to explain my issue in more detail. I have an object called PropertyVO that represents a Hotel property, and it only contains the most basic information about a property. This PropertyVO contains a PropertyInfoVO . The following is the code and mapping file for the PropertyVO:

Code:
public class PropertyVO {

    private Long propertyId;
    private PropertyInfoVO propertyInfo;
    private String marshaCode;

   public PropertyVO() {
   }

   public Long getPropertyId() {
      return this.propertyId;
   }

   public void setPropertyId(Long propertyId) {
      this.propertyId = propertyId;
   }

    public PropertyInfoVO getPropertyInfo() {
        return propertyInfo;
    }
   
    public void setPropertyInfo(PropertyInfoVO propertyInfo) {
        this.propertyInfo = propertyInfo;
    }

    public String getMarshaCode() {
        return marshaCode;
    }
   
    public void setMarshaCode(String mCode) {
        this.marshaCode = mCode;
    }


Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.vo.PropertyVO" table="property" >
        <comment></comment>
        <id name="propertyId" type="long">
            <column name="property_id" />
            <generator class="sequence">
              <param name="sequence">Seq_Property_ID</param>
          </generator>
        </id>
        <one-to-one name="propertyInfo"
           class="com.generalinfo.vo.PropertyInfoVO"
           cascade="save-update"/>

         <property name="marshaCode" type="string">
            <column name="Marsha_Code" length="5"/>
        </property>

</class>
</hibernate-mapping>

PropertyInfoVO shares a primary key with the PropertyVO. The following are the code and mapping files for PropertyInfoVO:

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

<hibernate-mapping>
    <class name="com.generalinfo.vo.PropertyInfoVO"
       table="PROPERTY_INFO">
       
      <id name="propertyId" type="long">
            <column name="PROPERTY_ID" />
            <generator class="foreign">
               <param name="property">property</param>
            </generator>
        </id>
       
        <one-to-one name="property"
           class="com.vo.PropertyVO"
           constrained="true"/> 
       
        <property name="propertyNameDisplay" type="string">
            <column name="PROPERTY_NAME_DISPLAY" length="100"/>
        </property>

    </class>
</hibernate-mapping>


When I make a get call on the org.hibernate.Session (i.e., session.get(PropertyVO.class, id)), the following sql is executed against the database:
Code:
/* load com.vo.PropertyVO */ select
        propertyvo0_.property_id as property1_26_1_,
        propertyvo0_.Marsha_Code as Marsha2_26_1_,
        propertyin1_.PROPERTY_ID as PROPERTY1_27_0_,
        propertyin1_.PROPERTY_NAME_DISPLAY as PROPERTY2_27_0_
    from
        property propertyvo0_
    left outer join
        PROPERTY_INFO propertyin1_
            on propertyvo0_.property_id=propertyin1_.PROPERTY_ID
    where
        propertyvo0_.property_id=?


According to the Hibernate reference documentation, if constrained="false", proxying is impossible and Hibernate will eager fetch the association. I'm assuming then that if constrained="true", lazy loading is possible. Since lazy defaults to "proxy" I thought that the PropertyInfoVO would be a proxy.

Am I missing something here? Why can I not get the PropertyInfoVO to be a proxy? Why is an eager fetch always being performed?

Thanks,

Sean


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