Adding field to BatchUpdateException

Lance Andersen - Oracle lance.andersen at oracle.com
Sat Nov 24 22:05:27 UTC 2012


Hi, 

For JDBC 4.2, I am adding methods to allow for larger update counts (request from JDBC driver vendors)  and because of this I have to tweak BatchUpdateException

The Statement interface has the method

int[] executeBatch()

I am planning to add

long[] executeLargeBatch().

To accomodate this change, I  also need to add a new field and the method getLargeUpdateCount to BatchUpdateException.

I have exchanged emails on this with Alan and he indicated that the changes seemed reasonable but to send a general email out to see if anything was  missed from the serialization perspective.

I have added JDBC Unit tests to validate that the serialization/deserialization works between JDBC 4.1 and JDBC 4.2 and they run without a problem.


Best
Lance

new-host-2:sql lanceandersen$ diff BatchUpdateException.java ~/NetBeansProjects/JDBC4.2/jdbc4.0/src/java/sql/
2c2
<  * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
---
>  * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
27a28,31
> import java.io.IOException;
> import java.io.InvalidObjectException;
> import java.io.ObjectInputStream;
> import java.io.ObjectOutputStream;
83a88
>       this.longUpdateCounts = (updateCounts == null) ? null : copyUpdateCount(updateCounts);
192c197
<         this((cause == null ? null : cause.toString()), null, 0, null, cause);
---
>         this((cause == null ? null : cause.toString()), null, 0, (int[])null, cause);
295a301
>         this.longUpdateCounts = (updateCounts == null) ? null : copyUpdateCount(updateCounts);
331c337,401
< 
---
>     
>   /**
>    * Constructs a <code>BatchUpdateException</code> object initialized with
>    * a given <code>reason</code>, <code>SQLState</code>, <code>vendorCode</code>
>    * <code>cause</code> and <code>updateCounts</code>.
>    * <p>
>    * This constructor should be used when the returned update count may exceed
>    * {@link Integer.MAX_VALUE}.
>    * <p>
>    * @param reason a description of the error
>    * @param SQLState an XOPEN or SQL:2003 code identifying the exception
>    * @param vendorCode an exception code used by a particular
>    * database vendor
>    * @param updateCounts an array of <code>long</code>, with each element
>    *indicating the update count, <code>Statement.SUCCESS_NO_INFO</code> or
>    * <code>Statement.EXECUTE_FAILED</code> for each SQL command in
>    * the batch for JDBC drivers that continue processing
>    * after a command failure; an update count or
>    * <code>Statement.SUCCESS_NO_INFO</code> for each SQL command in the batch
>    * prior to the failure for JDBC drivers that stop processing after a command
>    * failure
>    * @param cause the underlying reason for this <code>SQLException</code>
>    * (which is saved for later retrieval by the <code>getCause()</code> method);
>    * may be null indicating the cause is non-existent or unknown.
>    * @since 1.8
>    */
>   public BatchUpdateException(String reason, String SQLState, int vendorCode,
>           long []updateCounts,Throwable cause) {
>       super(reason, SQLState, vendorCode, cause);
>       this.longUpdateCounts  = (updateCounts == null) ? null : Arrays.copyOf(updateCounts, updateCounts.length);
>       this.updateCounts = (longUpdateCounts == null) ? null : copyUpdateCount(longUpdateCounts);
>   }
>  
>   /**
>    * Retrieves the update count for each update statement in the batch
>    * update that executed successfully before this exception occurred.
>    * A driver that implements batch updates may or may not continue to
>    * process the remaining commands in a batch when one of the commands
>    * fails to execute properly. If the driver continues processing commands,
>    * the array returned by this method will have as many elements as
>    * there are commands in the batch; otherwise, it will contain an
>    * update count for each command that executed successfully before
>    * the <code>BatchUpdateException</code> was thrown.
>    * <p>
>    * This method should be used when the returned update count may exceed
>    * {@link Integer.MAX_VALUE}.
>    * <p>
>    * @return an array of <code>long</code> containing the update counts
>    * for the updates that were executed successfully before this error
>    * occurred.  Or, if the driver continues to process commands after an
>    * error, one of the following for every command in the batch:
>    * <OL>
>    * <LI>an update count
>    *  <LI><code>Statement.SUCCESS_NO_INFO</code> to indicate that the command
>    *     executed successfully but the number of rows affected is unknown
>    *  <LI><code>Statement.EXECUTE_FAILED</code> to indicate that the command
>    *     failed to execute successfully
>    * </OL>
>    * @since 1.8
>    */
>   public long[] getLargeUpdateCounts() {
>       return (longUpdateCounts == null) ? null : 
>               Arrays.copyOf(longUpdateCounts, longUpdateCounts.length);
>   }
>   
337c407,414
<   private final int[] updateCounts;
---
>   private  int[] updateCounts;
> 
>   /**
>    * The array that describes the outcome of a batch execution.
>    * @serial
>    * @since 1.8
>    */
>   private  long[] longUpdateCounts;
339a417,474
>   
>   /*
>    * Utility method to copy int[] updateCount to long[] updateCount
>    */
>   private static long[] copyUpdateCount(int[] uc) {
>       long[] copy = new long[uc.length];
>       for(int i= 0; i< uc.length; i++) {
>           copy[i] = uc[i];
>           
>       }
>       return copy;
>   }
>  
>   /*
>    * Utility method to copy int[] updateCount to long[] updateCount
>    */
>   private static int[] copyUpdateCount(long[] uc) {
>       int[] copy = new int[uc.length];
>       for(int i= 0; i< uc.length; i++) {
>           copy[i] = (int) uc[i];        
>       }
>       return copy;
>   }
>     /**
>      * readObject is called to restore the state of the
>      * {@code BatchUpdateException} from a stream.
>      */
>     private void readObject(ObjectInputStream s)
>             throws IOException, ClassNotFoundException {
>         
>        ObjectInputStream.GetField fields = s.readFields();
>        int[] tmp = (int[])fields.get("updateCounts", null);   
>        long[] tmp2 = (long[])fields.get("longUpdateCounts", null);
>        if(tmp != null && tmp2 != null && tmp.length != tmp2.length)
>            throw new InvalidObjectException("update counts are not the expected size");      
>        if (tmp != null)
>            updateCounts = tmp.clone();
>        if (tmp2 != null)
>            longUpdateCounts = tmp2.clone();
>        if(updateCounts == null && longUpdateCounts != null)
>            updateCounts = copyUpdateCount(longUpdateCounts);
>        if(longUpdateCounts == null && updateCounts != null)
>            longUpdateCounts = copyUpdateCount(updateCounts);
> 
>     }
>     
>     /**
>      * writeObject is called to save the state of the {@code BatchUpdateException}
>      * to a stream.
>      */
>     private void writeObject(ObjectOutputStream s)
>             throws IOException, ClassNotFoundException {
> 
>         ObjectOutputStream.PutField fields = s.putFields();
>         fields.put("updateCounts", updateCounts);
>         fields.put("longUpdateCounts", longUpdateCounts);
>         s.writeFields();    
>     }



Lance Andersen| Principal Member of Technical Staff | +1.781.442.2037
Oracle Java Engineering 
1 Network Drive 
Burlington, MA 01803
Lance.Andersen at oracle.com





More information about the core-libs-dev mailing list