Author: lmeadors
Date: Mon Sep  3 14:41:03 2007
New Revision: 572429

URL: http://svn.apache.org/viewvc?rev=572429&view=rev
Log:
Rolling back generated keys when an insert fails.

Modified:
    
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/impl/SqlMapExecutorDelegate.java
    
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/statement/SelectKeyStatement.java
    ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/StatementTest.java
    ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/maps/LineItem.xml

Modified: 
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/impl/SqlMapExecutorDelegate.java
URL: 
http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/impl/SqlMapExecutorDelegate.java?rev=572429&r1=572428&r2=572429&view=diff
==============================================================================
--- 
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/impl/SqlMapExecutorDelegate.java
 (original)
+++ 
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/impl/SqlMapExecutorDelegate.java
 Mon Sep  3 14:41:03 2007
@@ -358,13 +358,27 @@
         selectKeyStatement = ((InsertStatement) ms).getSelectKeyStatement();
       }
 
+      // Here we get the old value for the key property. We'll want it later 
if for some reason the
+      // insert fails.
+      Object oldKeyValue = null;
+      String keyProperty = null;
+      boolean resetKeyValueOnFailure = false;
       if (selectKeyStatement != null && !selectKeyStatement.isRunAfterSQL()) {
+        keyProperty = selectKeyStatement.getKeyProperty();
+        oldKeyValue = PROBE.getObject(param, keyProperty);
         generatedKey = executeSelectKey(sessionScope, trans, ms, param);
+        resetKeyValueOnFailure = true;
       }
 
       StatementScope statementScope = beginStatementScope(sessionScope, ms);
       try {
         ms.executeUpdate(statementScope, trans, param);
+      }catch (SQLException e){
+        // uh-oh, the insert failed, so if we set the reset flag earlier, 
we'll put the old value
+        // back...
+        if(resetKeyValueOnFailure) PROBE.setObject(param, keyProperty, 
oldKeyValue);
+        // ...and still throw the exception.
+        throw e;
       } finally {
         endStatementScope(statementScope);
       }

Modified: 
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/statement/SelectKeyStatement.java
URL: 
http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/statement/SelectKeyStatement.java?rev=572429&r1=572428&r2=572429&view=diff
==============================================================================
--- 
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/statement/SelectKeyStatement.java
 (original)
+++ 
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/statement/SelectKeyStatement.java
 Mon Sep  3 14:41:03 2007
@@ -45,7 +45,7 @@
 
   public List executeQueryForList(StatementScope statementScope, Transaction 
trans, Object parameterObject, int skipResults, int maxResults)
       throws SQLException {
-    throw new SQLException("Select statements cannot be executed for a list.");
+    throw new SQLException("Select Key statements cannot be executed for a 
list.");
   }
 
   public void executeQueryWithRowHandler(StatementScope statementScope, 
Transaction trans, Object parameterObject, RowHandler rowHandler)

Modified: 
ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/StatementTest.java
URL: 
http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/StatementTest.java?rev=572429&r1=572428&r2=572429&view=diff
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/StatementTest.java 
(original)
+++ ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/StatementTest.java 
Mon Sep  3 14:41:03 2007
@@ -685,6 +685,28 @@
     assertEquals(10, testItem.getId());
   }
 
+  public void testInsertGeneratedKeyFailure() throws SQLException {
+    LineItem item = new LineItem();
+
+    item.setId(0);
+    item.setItemCode("blah");
+    item.setOrderId(333);
+    item.setPrice(new BigDecimal("44.00"));
+    item.setQuantity(1);
+
+    Object key = new Integer(-1);
+
+    try{
+      key = sqlMap.insert("insertLineItemOrDie", item);
+    }catch(SQLException e){
+      // this is expected
+    }
+
+    assertEquals(key, new Integer(-1)); // this should not be changed from 
above
+    assertEquals(0, item.getId()); // this should not be changed from above
+
+  }
+
   public void testInsertPreKey() throws SQLException {
     LineItem item = new LineItem();
 

Modified: 
ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/maps/LineItem.xml
URL: 
http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/maps/LineItem.xml?rev=572429&r1=572428&r2=572429&view=diff
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/maps/LineItem.xml 
(original)
+++ ibatis/trunk/java/mapper/mapper2/test/com/ibatis/sqlmap/maps/LineItem.xml 
Mon Sep  3 14:41:03 2007
@@ -58,6 +58,16 @@
       (#id#, #orderId#, #itemCode#, #quantity#, #price#)
   </insert>
 
+  <insert id="insertLineItemOrDie" parameterClass="testdomain.LineItem">
+    <selectKey resultClass="int" keyProperty="id" type="post">
+      select 99 from LINE_ITEM where LIN_ID = 1 and LIN_ORD_ID=1
+    </selectKey>
+    insert into LINE_ITEM_LOL
+      (LIN_ID, LIN_ORD_ID, LIN_ITM_CODE, LIN_QUANTITY, LIN_PRICE)
+    values
+      (#id#, #orderId#, #itemCode#, #quantity#, #price#)
+  </insert>
+
   <insert id="insertLineItemPreKey" parameterClass="testdomain.LineItem">
     <selectKey resultClass="int" keyProperty="id">
       select 99 from LINE_ITEM where LIN_ID = 1 and LIN_ORD_ID=1


Reply via email to