| 
					
						 In setting up some unit tests for my DAO, I came across  strange behavior in Session#merge(). It appears that merging a detached object which has a non-existent primary key (where normally the keys are "natively" generated) causes the row to be inserted, ignoring the bogus primary key. Has anyone else noticed this behavior?
 
 This is undesirable since it could cause rows to be inserted where an update was intended. This could happen if the target row was concurrently deleted in another session, or if the id in the detached object being merged was somehow corrupted.
 
 Hibernate version: 3.0.5
 
 Mapping documents:
 
 <hibernate-mapping package="testutils.widget">
   <class name="Widget" table="WIDGETS" lazy="false">	
     <id name="id" type="java.lang.Long" column="WIDGET_ID">   
       <generator class="native"/>
     </id>
     <property name="name">
       <column name="WIDGET_NAME" not-null="true" unique="true"/>
     </property>
     <property name="description">
       <column name="WIDGET_DESC"/>
     </property>    
  </class>
 
 Code between sessionFactory.openSession() and session.close():
 
     String w1Name = "foo";
     String w1Desc = "a test widget";
     Widget w1 = new Widget(w1Name,w1Desc);
     w1.setId(2718281L); // setting nonexistent primary key for test
     Transaction tx = session.beginTransaction();
     session.merge(w1); // row is inserted but with generated id
     tx.commit();
 
 Name and version of the database you are using: HSQLDB 1.0ea4
 
 The generated SQL (show_sql=true):
 
   Hibernate: select widget0_.WIDGET_ID as WIDGET1_0_, widget0_.WIDGET_NAME as WIDGET2_0_0_, widget0_.WIDGET_DESC as WIDGET3_0_0_ from WIDGETS widget0_ where widget0_.WIDGET_ID=?
   Hibernate: insert into WIDGETS (WIDGET_NAME, WIDGET_DESC, WIDGET_ID) values (?, ?, null)
   Hibernate: call identity()
 
 Debug level Hibernate log excerpt:
 
 opened session at timestamp: 4613822072254464
 begin
 opening JDBC connection
 current autocommit status: true
 disabling autocommit
 id unsaved-value: null
 detached instance of: testutils.widget.Widget
 merging detached instance
 loading entity: [testutils.widget.Widget#2718281]
 attempting to resolve: [testutils.widget.Widget#2718281]
 object not resolved in any cache: [testutils.widget.Widget#2718281]
 Materializing entity: [testutils.widget.Widget#2718281]
 loading entity: [testutils.widget.Widget#2718281]
 about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
 select widget0_.WIDGET_ID as WIDGET1_0_, widget0_.WIDGET_NAME as WIDGET2_0_0_, widget0_.WIDGET_DESC as WIDGET3_0_0_ from WIDGETS widget0_ where widget0_.WIDGET_ID=?
 Hibernate: select widget0_.WIDGET_ID as WIDGET1_0_, widget0_.WIDGET_NAME as WIDGET2_0_0_, widget0_.WIDGET_DESC as WIDGET3_0_0_ from WIDGETS widget0_ where widget0_.WIDGET_ID=?
 preparing statement
 binding '2718281' to parameter: 1
 about to open ResultSet (open ResultSets: 0, globally: 0)
 processing result set
 done processing result set (0 rows)
 about to close ResultSet (open ResultSets: 1, globally: 1)
 about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
 closing statement
 total objects hydrated: 0
 initializing non-lazy collections
 done entity load
 merging transient instance
 saving [testutils.widget.Widget#<null>]
 executing insertions
 Inserting entity: testutils.widget.Widget (native id)
 about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
 insert into WIDGETS (WIDGET_NAME, WIDGET_DESC, WIDGET_ID) values (?, ?, null)
 Hibernate: insert into WIDGETS (WIDGET_NAME, WIDGET_DESC, WIDGET_ID) values (?, ?, null)
 preparing statement
 Dehydrating entity: [testutils.widget.Widget#<null>]
 binding 'foo' to parameter: 1
 binding 'a test widget' to parameter: 2
 about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
 closing statement
 about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
 call identity()
 Hibernate: call identity()
 preparing statement
 Natively generated identity: 1
 about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
 closing statement
 commit
 automatically flushing session
 flushing session
 processing flush-time cascades
 dirty checking collections
 Flushing entities and processing referenced collections
 Processing unreferenced collections
 Scheduling collection removes/(re)creates/updates
 Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects
 Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
 listing entities:
 testutils.widget.Widget{description=a test widget, name=foo, id=1}
 executing flush
 post flush
 before transaction completion
 before transaction completion
 re-enabling autocommit
 committed JDBC Connection
 after transaction completion
 after transaction completion
 closing session
 closing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
 after transaction completion
 after transaction completion 
					
  
						
					 |