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>
UserOrderCode:
<?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>
OtherCode:
<?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 XMLCode:
<?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:ProductCode:
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; }
}
UserOrderCode:
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; }
}
ProductUserOrderMapCode:
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; }
}
OtherCode:
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