-->
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.  [ 10 posts ] 
Author Message
 Post subject: Many-to-many w/ composite-element causing delete and insert
PostPosted: Fri Feb 20, 2004 12:40 pm 
Newbie

Joined: Fri Feb 20, 2004 12:23 pm
Posts: 10
I'm using hibernate 2.1.1 under weblogic 8 with oracle 9.

I am seeing some strange behaviour with many-to-many mappings using composite-element. An unneccessary delete and insert statement is being sent to the database.

Tables:
PRODUCT
ID NUMBER(6) NOT NULL,
DESCRIPTION VARCHAR2(40 BYTE)

USER_ORDER
ID NUMBER(6) NOT NULL,
TOTAL NUMBER(6)

PRODUCT_USER_ORDER_MAP
PRODUCT_ID NUMBER(6) NOT NULL,
USER_ORDER_ID NUMBER(6) NOT NULL,
QUANTITY NUMBER(6)

OTHER
ID NUMBER(6) NOT NULL,
VALUE NUMBER(6)


Mapping documents:
Product
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="test.Product" table="PRODUCT" dynamic-insert="true" dynamic-update="true">
      <id name="id" unsaved-value="null" column="ID">
         <generator class="seqhilo">
            <param name="sequence">SEQ_HIBERNATE_TEST</param>
            <param name="max_lo">100</param>
         </generator>
      </id>
      <property name="description" column="DESCRIPTION"/>
     
      <set name="productUserOrderMap" table="PRODUCT_USER_ORDER_MAP" lazy="true">
         <key column="PRODUCT_ID"/>
         <composite-element class="test.ProductUserOrderMap">
            <property name="quantity" column="QUANTITY"/>
            <many-to-one name="userOrder" class="test.UserOrder" column="USER_ORDER_ID"/>
         </composite-element>
      </set>
   </class>
</hibernate-mapping>


UserOrder
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="test.UserOrder" table="USER_ORDER" dynamic-insert="true" dynamic-update="true">
      <id name="id" unsaved-value="null" column="ID">
         <generator class="seqhilo">
            <param name="sequence">SEQ_HIBERNATE_TEST</param>
            <param name="max_lo">100</param>
         </generator>
      </id>
      <property name="total" column="TOTAL"/>
     
      <set name="productUserOrderMap" table="PRODUCT_USER_ORDER_MAP" lazy="true">
         <key column="USER_ORDER_ID"/>
         <composite-element class="test.ProductUserOrderMap">
            <property name="quantity" column="QUANTITY"/>
            <many-to-one name="product" class="test.Product" column="PRODUCT_ID"/>
         </composite-element>
      </set>
   </class>
</hibernate-mapping>


Other
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="test.Other" table="OTHER" dynamic-insert="true" dynamic-update="true">
      <id name="id" unsaved-value="null" column="ID">
         <generator class="seqhilo">
            <param name="sequence">SEQ_HIBERNATE_TEST</param>
            <param name="max_lo">100</param>
         </generator>
      </id>
      <property name="value" column="VALUE"/>
   </class>
</hibernate-mapping>


Hibernate Config XML
Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration
    PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="connection.datasource">oraclePool</property>
        <property name="show_sql">true</property>
        <property name="dialect">net.sf.hibernate.dialect.Oracle9Dialect</property>
        <property name="transaction.factory_class">net.sf.hibernate.transaction.JTATransactionFactory</property>
        <property name="transaction.manager_lookup_class">net.sf.hibernate.transaction.WeblogicTransactionManagerLookup</property>
        <mapping resource="test/Product.hbm.xml"/>
        <mapping resource="test/UserOrder.hbm.xml"/>
        <mapping resource="test/Other.hbm.xml"/>
    </session-factory>
</hibernate-configuration>


POJOs:
Product
Code:
package test;

import java.util.Set;

public class Product {
   private Integer id;
   private String description;
   private Set productUserOrderMap;

   public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   public String getDescription() { return description; }
   public void setDescription(String description) { this.description = description; }
   public Set getProductUserOrderMap() { return productUserOrderMap; }
   public void setProductUserOrderMap(Set productUserOrderMap) { this.productUserOrderMap = productUserOrderMap; }
}


UserOrder
Code:
package test;

import java.util.Set;

public class UserOrder {
   private Integer id;
   private Integer total;
   private Set productUserOrderMap;

   public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   public Integer getTotal() { return total; }
   public void setTotal(Integer total) { this.total = total; }
   public Set getProductUserOrderMap() { return productUserOrderMap; }
   public void setProductUserOrderMap(Set productUserOrderMap) { this.productUserOrderMap = productUserOrderMap; }
}


ProductUserOrderMap
Code:
package test;

public class ProductUserOrderMap {
   private Product product;
   private UserOrder userOrder;
   private Integer quantity;

   public Product getProduct() { return product; }
   public void setProduct(Product product) { this.product = product; }
   public UserOrder getUserOrder() { return userOrder; }
   public void setUserOrder(UserOrder userOrder) { this.userOrder = userOrder; }
   public Integer getQuantity() { return quantity; }
   public void setQuantity(Integer quantity) { this.quantity = quantity; }
}


Other
Code:
package test;

public class Other {
   private Integer id;
   private Integer value;

   public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   public Integer getValue() { return value; }
   public void setValue(Integer value) { this.value = value; }
}



Client code (method in a stateless session bean):
Code:
   public void productUserOrderTest() throws Exception {
      net.sf.hibernate.cfg.Configuration cfg = new net.sf.hibernate.cfg.Configuration();
      cfg.configure();
      net.sf.hibernate.SessionFactory sessionFactory = cfg.buildSessionFactory();
      net.sf.hibernate.Session session = sessionFactory.openSession();

      test.Product product = null;
      try {
         net.sf.hibernate.Criteria criteria = session.createCriteria(test.Product.class);
         criteria.add(net.sf.hibernate.expression.Expression.eq("id", new Integer(1)));
         criteria.setFetchMode("productUserOrderMap", net.sf.hibernate.FetchMode.EAGER);
         List list = criteria.list();
         product = (test.Product) list.get(0);

         test.Other other = new test.Other();
         other.setValue(new Integer(100));
         session.save(other);
         session.flush();
      } catch (HibernateException ex) {
         sessionContext_.setRollbackOnly();
         logger_.error(ex);
         throw new ClasswellRuntimeException(ex);
      } finally {
         try {
            session.close();
         } catch (HibernateException ex) {
            logger_.error(ex);
            throw new ClasswellRuntimeException(ex);
         }
      }
   }



Log file output:
Code:
- Hibernate 2.1.1
- hibernate.properties not found
- using CGLIB reflection optimizer
- configuring from resource: /hibernate.cfg.xml
- Configuration resource: /hibernate.cfg.xml
- Mapping resource: test/Product.hbm.xml
- Mapping class: test.Product -> PRODUCT
- Mapping collection: test.Product.productUserOrderMap -> PRODUCT_USER_ORDER_MAP
- Mapping resource: test/UserOrder.hbm.xml
- Mapping class: test.UserOrder -> USER_ORDER
- Mapping collection: test.UserOrder.productUserOrderMap -> PRODUCT_USER_ORDER_MAP
- Mapping resource: test/Other.hbm.xml
- Mapping class: test.Other -> OTHER
- Configured SessionFactory: null
- processing one-to-many association mappings
- processing one-to-one association property references
- processing foreign key constraints
- Using dialect: net.sf.hibernate.dialect.Oracle9Dialect
- Use outer join fetching: true
- JNDI InitialContext properties:{}
- Using datasource: classwellOraclePool
- Transaction strategy: net.sf.hibernate.transaction.JTATransactionFactory
- JNDI InitialContext properties:{}
- instantiating TransactionManagerLookup: net.sf.hibernate.transaction.WeblogicTransactionManagerLookup
- instantiated TransactionManagerLookup
- JNDI InitialContext properties:{}
- instantiating TransactionManagerLookup: net.sf.hibernate.transaction.WeblogicTransactionManagerLookup
- instantiated TransactionManagerLookup
- Use scrollable result sets: true
- JDBC 2 max batch size: 15
- echoing all SQL to stdout
- Query language substitutions: {}
- cache provider: net.sf.ehcache.hibernate.Provider
- instantiating and configuring caches
- building session factory
- no JNDI name configured
- JNDI InitialContext properties:{}
Hibernate: select this.ID as ID1_, this.DESCRIPTION as DESCRIPT2_1_, productuse1_.QUANTITY as QUANTITY__, productuse1_.USER_ORDER_ID as USER_ORD3___, productuse1_.PRODUCT_ID as PRODUCT_ID__, userorder2_.ID as ID0_, userorder2_.TOTAL as TOTAL0_ from PRODUCT this left outer join PRODUCT_USER_ORDER_MAP productuse1_ on this.ID=productuse1_.PRODUCT_ID left outer join USER_ORDER userorder2_ on productuse1_.USER_ORDER_ID=userorder2_.ID where this.ID=?
Hibernate: select SEQ_HIBERNATE_TEST.nextval from dual
Hibernate: insert into OTHER (VALUE, ID) values (?, ?)
Hibernate: delete from PRODUCT_USER_ORDER_MAP where PRODUCT_ID=? and QUANTITY=? and USER_ORDER_ID=?
Hibernate: insert into PRODUCT_USER_ORDER_MAP (PRODUCT_ID, QUANTITY, USER_ORDER_ID) values (?, ?, ?)



Note the last two lines of the log file delete and insert into the many-to-many mapping table even though no such data has been manipulated. Any ideas?

thanks,
-shreyank


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 20, 2004 1:43 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
No dirty collection in the debug logs ?

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 20, 2004 1:56 pm 
Newbie

Joined: Fri Feb 20, 2004 12:23 pm
Posts: 10
No, the log I pasted in my original post is the entire output. I do not have the optimistic-lock attribute defined in any of my class hibernate mapping docs.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 23, 2004 12:16 pm 
Newbie

Joined: Fri Feb 20, 2004 12:23 pm
Posts: 10
I tried changing a couple of things to see what effect they would have on this delete-insert problem but I didn't really get any closer to figuring out what is going on here. Does anyone have any better ideas?

These are the two things I changed:

I removed the FetchMode.EAGER loading and removed the lazy loading. Hibernate loaded all of the relevant relationships and ended up with the same number of delete and insert statements as relationship rows.

I tried setting the optimistic-lock class attribute to all and dirty, but neither made a difference.


Thanks,
-shreyank


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 24, 2004 5:06 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Did you show the full debug logs ?

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 24, 2004 5:24 pm 
Newbie

Joined: Fri Feb 20, 2004 12:23 pm
Posts: 10
The log I pasted in my original post is the entire output from hibernate.
I have show_sql set to true in my configuration:

Code:
<hibernate-configuration>
    <session-factory>
        ......
        <property name="show_sql">true</property>
        ......
    </session-factory>
</hibernate-configuration>

Is there a config setting to get more detailed logs? Or am I not understanding your question?

-shreyank


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 24, 2004 5:31 pm 
Expert
Expert

Joined: Thu Jan 08, 2004 6:17 pm
Posts: 278
Yes, you can get much, much more logging from Hibernate. You can set your log4j.configuration or your JDK 1.4 logging configuration to set net.sf.hibernate.level=DEBUG or the equivalent. And then get ready for the deluge!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 24, 2004 5:33 pm 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
Do you have equals/hashCode implemented correctly for ProductUserOrderMap?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 24, 2004 5:35 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Michael is right, this is probably an equals/hashCode error.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 24, 2004 5:54 pm 
Newbie

Joined: Fri Feb 20, 2004 12:23 pm
Posts: 10
Ha! I can't believe I forgot to implement those.
I read the through the documentation including Section 7.2: "Note: if you define a Set of composite elements, it is very important to implement equals() and hashCode() correctly." But I completely forgot.

Sorry about that.


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