Path: blob/master/src/java.sql/share/classes/java/sql/BatchUpdateException.java
41153 views
/*1* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.sql;2627import java.io.IOException;28import java.io.InvalidObjectException;29import java.io.ObjectInputStream;30import java.io.ObjectOutputStream;31import java.util.Arrays;3233/**34* The subclass of {@link SQLException} thrown when an error35* occurs during a batch update operation. In addition to the36* information provided by {@link SQLException}, a37* {@code BatchUpdateException} provides the update38* counts for all commands that were executed successfully during the39* batch update, that is, all commands that were executed before the error40* occurred. The order of elements in an array of update counts41* corresponds to the order in which commands were added to the batch.42* <P>43* After a command in a batch update fails to execute properly44* and a {@code BatchUpdateException} is thrown, the driver45* may or may not continue to process the remaining commands in46* the batch. If the driver continues processing after a failure,47* the array returned by the method48* {@code BatchUpdateException.getUpdateCounts} will have49* an element for every command in the batch rather than only50* elements for the commands that executed successfully before51* the error. In the case where the driver continues processing52* commands, the array element for any command53* that failed is {@code Statement.EXECUTE_FAILED}.54* <P>55* A JDBC driver implementation should use56* the constructor {@code BatchUpdateException(String reason, String SQLState,57* int vendorCode, long []updateCounts,Throwable cause) } instead of58* constructors that take {@code int[]} for the update counts to avoid the59* possibility of overflow.60* <p>61* If {@code Statement.executeLargeBatch} method is invoked it is recommended that62* {@code getLargeUpdateCounts} be called instead of {@code getUpdateCounts}63* in order to avoid a possible overflow of the integer update count.64* @since 1.265*/6667public class BatchUpdateException extends SQLException {6869/**70* Constructs a {@code BatchUpdateException} object initialized with a given71* {@code reason}, {@code SQLState}, {@code vendorCode} and72* {@code updateCounts}.73* The {@code cause} is not initialized, and may subsequently be74* initialized by a call to the75* {@link Throwable#initCause(java.lang.Throwable)} method.76* <p>77* <strong>Note:</strong> There is no validation of {@code updateCounts} for78* overflow and because of this it is recommended that you use the constructor79* {@code BatchUpdateException(String reason, String SQLState,80* int vendorCode, long []updateCounts,Throwable cause) }.81* </p>82* @param reason a description of the error83* @param SQLState an XOPEN or SQL:2003 code identifying the exception84* @param vendorCode an exception code used by a particular85* database vendor86* @param updateCounts an array of {@code int}, with each element87* indicating the update count, {@code Statement.SUCCESS_NO_INFO} or88* {@code Statement.EXECUTE_FAILED} for each SQL command in89* the batch for JDBC drivers that continue processing90* after a command failure; an update count or91* {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch92* prior to the failure for JDBC drivers that stop processing after a command93* failure94* @since 1.295* @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],96* java.lang.Throwable)97*/98public BatchUpdateException( String reason, String SQLState, int vendorCode,99int[] updateCounts ) {100super(reason, SQLState, vendorCode);101this.updateCounts = (updateCounts == null) ? null : Arrays.copyOf(updateCounts, updateCounts.length);102this.longUpdateCounts = (updateCounts == null) ? null : copyUpdateCount(updateCounts);103}104105/**106* Constructs a {@code BatchUpdateException} object initialized with a given107* {@code reason}, {@code SQLState} and108* {@code updateCounts}.109* The {@code cause} is not initialized, and may subsequently be110* initialized by a call to the111* {@link Throwable#initCause(java.lang.Throwable)} method. The vendor code112* is initialized to 0.113* <p>114* <strong>Note:</strong> There is no validation of {@code updateCounts} for115* overflow and because of this it is recommended that you use the constructor116* {@code BatchUpdateException(String reason, String SQLState,117* int vendorCode, long []updateCounts,Throwable cause) }.118* </p>119* @param reason a description of the exception120* @param SQLState an XOPEN or SQL:2003 code identifying the exception121* @param updateCounts an array of {@code int}, with each element122* indicating the update count, {@code Statement.SUCCESS_NO_INFO} or123* {@code Statement.EXECUTE_FAILED} for each SQL command in124* the batch for JDBC drivers that continue processing125* after a command failure; an update count or126* {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch127* prior to the failure for JDBC drivers that stop processing after a command128* failure129* @since 1.2130* @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],131* java.lang.Throwable)132*/133public BatchUpdateException(String reason, String SQLState,134int[] updateCounts) {135this(reason, SQLState, 0, updateCounts);136}137138/**139* Constructs a {@code BatchUpdateException} object initialized with a given140* {@code reason} and {@code updateCounts}.141* The {@code cause} is not initialized, and may subsequently be142* initialized by a call to the143* {@link Throwable#initCause(java.lang.Throwable)} method. The144* {@code SQLState} is initialized to {@code null}145* and the vendor code is initialized to 0.146* <p>147* <strong>Note:</strong> There is no validation of {@code updateCounts} for148* overflow and because of this it is recommended that you use the constructor149* {@code BatchUpdateException(String reason, String SQLState,150* int vendorCode, long []updateCounts,Throwable cause) }.151* </p>152* @param reason a description of the exception153* @param updateCounts an array of {@code int}, with each element154* indicating the update count, {@code Statement.SUCCESS_NO_INFO} or155* {@code Statement.EXECUTE_FAILED} for each SQL command in156* the batch for JDBC drivers that continue processing157* after a command failure; an update count or158* {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch159* prior to the failure for JDBC drivers that stop processing after a command160* failure161* @since 1.2162* @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],163* java.lang.Throwable)164*/165public BatchUpdateException(String reason, int[] updateCounts) {166this(reason, null, 0, updateCounts);167}168169/**170* Constructs a {@code BatchUpdateException} object initialized with a given171* {@code updateCounts}.172* initialized by a call to the173* {@link Throwable#initCause(java.lang.Throwable)} method. The {@code reason}174* and {@code SQLState} are initialized to null and the vendor code175* is initialized to 0.176* <p>177* <strong>Note:</strong> There is no validation of {@code updateCounts} for178* overflow and because of this it is recommended that you use the constructor179* {@code BatchUpdateException(String reason, String SQLState,180* int vendorCode, long []updateCounts,Throwable cause) }.181* </p>182* @param updateCounts an array of {@code int}, with each element183* indicating the update count, {@code Statement.SUCCESS_NO_INFO} or184* {@code Statement.EXECUTE_FAILED} for each SQL command in185* the batch for JDBC drivers that continue processing186* after a command failure; an update count or187* {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch188* prior to the failure for JDBC drivers that stop processing after a command189* failure190* @since 1.2191* @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],192* java.lang.Throwable)193*/194public BatchUpdateException(int[] updateCounts) {195this(null, null, 0, updateCounts);196}197198/**199* Constructs a {@code BatchUpdateException} object.200* The {@code reason}, {@code SQLState} and {@code updateCounts}201* are initialized to {@code null} and the vendor code is initialized to 0.202* The {@code cause} is not initialized, and may subsequently be203* initialized by a call to the204* {@link Throwable#initCause(java.lang.Throwable)} method.205*206* @since 1.2207* @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],208* java.lang.Throwable)209*/210public BatchUpdateException() {211this(null, null, 0, null);212}213214/**215* Constructs a {@code BatchUpdateException} object initialized with216* a given {@code cause}.217* The {@code SQLState} and {@code updateCounts}218* are initialized219* to {@code null} and the vendor code is initialized to 0.220* The {@code reason} is initialized to {@code null} if221* {@code cause==null} or to {@code cause.toString()} if222* {@code cause!=null}.223* @param cause the underlying reason for this {@code SQLException}224* (which is saved for later retrieval by the {@code getCause()} method);225* may be null indicating the cause is non-existent or unknown.226* @since 1.6227* @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],228* java.lang.Throwable)229*/230public BatchUpdateException(Throwable cause) {231this((cause == null ? null : cause.toString()), null, 0, (int[])null, cause);232}233234/**235* Constructs a {@code BatchUpdateException} object initialized with a236* given {@code cause} and {@code updateCounts}.237* The {@code SQLState} is initialized238* to {@code null} and the vendor code is initialized to 0.239* The {@code reason} is initialized to {@code null} if240* {@code cause==null} or to {@code cause.toString()} if241* {@code cause!=null}.242* <p>243* <strong>Note:</strong> There is no validation of {@code updateCounts} for244* overflow and because of this it is recommended that you use the constructor245* {@code BatchUpdateException(String reason, String SQLState,246* int vendorCode, long []updateCounts,Throwable cause) }.247* </p>248* @param updateCounts an array of {@code int}, with each element249* indicating the update count, {@code Statement.SUCCESS_NO_INFO} or250* {@code Statement.EXECUTE_FAILED} for each SQL command in251* the batch for JDBC drivers that continue processing252* after a command failure; an update count or253* {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch254* prior to the failure for JDBC drivers that stop processing after a command255* failure256* @param cause the underlying reason for this {@code SQLException}257* (which is saved for later retrieval by the {@code getCause()} method); may be null indicating258* the cause is non-existent or unknown.259* @since 1.6260* @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],261* java.lang.Throwable)262*/263public BatchUpdateException(int []updateCounts , Throwable cause) {264this((cause == null ? null : cause.toString()), null, 0, updateCounts, cause);265}266267/**268* Constructs a {@code BatchUpdateException} object initialized with269* a given {@code reason}, {@code cause}270* and {@code updateCounts}. The {@code SQLState} is initialized271* to {@code null} and the vendor code is initialized to 0.272* <p>273* <strong>Note:</strong> There is no validation of {@code updateCounts} for274* overflow and because of this it is recommended that you use the constructor275* {@code BatchUpdateException(String reason, String SQLState,276* int vendorCode, long []updateCounts,Throwable cause) }.277* </p>278* @param reason a description of the exception279* @param updateCounts an array of {@code int}, with each element280* indicating the update count, {@code Statement.SUCCESS_NO_INFO} or281* {@code Statement.EXECUTE_FAILED} for each SQL command in282* the batch for JDBC drivers that continue processing283* after a command failure; an update count or284* {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch285* prior to the failure for JDBC drivers that stop processing after a command286* failure287* @param cause the underlying reason for this {@code SQLException} (which is saved for later retrieval by the {@code getCause()} method);288* may be null indicating289* the cause is non-existent or unknown.290* @since 1.6291* @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],292* java.lang.Throwable)293*/294public BatchUpdateException(String reason, int []updateCounts, Throwable cause) {295this(reason, null, 0, updateCounts, cause);296}297298/**299* Constructs a {@code BatchUpdateException} object initialized with300* a given {@code reason}, {@code SQLState},{@code cause}, and301* {@code updateCounts}. The vendor code is initialized to 0.302*303* @param reason a description of the exception304* @param SQLState an XOPEN or SQL:2003 code identifying the exception305* @param updateCounts an array of {@code int}, with each element306* indicating the update count, {@code Statement.SUCCESS_NO_INFO} or307* {@code Statement.EXECUTE_FAILED} for each SQL command in308* the batch for JDBC drivers that continue processing309* after a command failure; an update count or310* {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch311* prior to the failure for JDBC drivers that stop processing after a command312* failure313* <p>314* <strong>Note:</strong> There is no validation of {@code updateCounts} for315* overflow and because of this it is recommended that you use the constructor316* {@code BatchUpdateException(String reason, String SQLState,317* int vendorCode, long []updateCounts,Throwable cause) }.318* </p>319* @param cause the underlying reason for this {@code SQLException}320* (which is saved for later retrieval by the {@code getCause()} method);321* may be null indicating322* the cause is non-existent or unknown.323* @since 1.6324* @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],325* java.lang.Throwable)326*/327public BatchUpdateException(String reason, String SQLState,328int []updateCounts, Throwable cause) {329this(reason, SQLState, 0, updateCounts, cause);330}331332/**333* Constructs a {@code BatchUpdateException} object initialized with334* a given {@code reason}, {@code SQLState}, {@code vendorCode}335* {@code cause} and {@code updateCounts}.336*337* @param reason a description of the error338* @param SQLState an XOPEN or SQL:2003 code identifying the exception339* @param vendorCode an exception code used by a particular340* database vendor341* @param updateCounts an array of {@code int}, with each element342*indicating the update count, {@code Statement.SUCCESS_NO_INFO} or343* {@code Statement.EXECUTE_FAILED} for each SQL command in344* the batch for JDBC drivers that continue processing345* after a command failure; an update count or346* {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch347* prior to the failure for JDBC drivers that stop processing after a command348* failure349* <p>350* <strong>Note:</strong> There is no validation of {@code updateCounts} for351* overflow and because of this it is recommended that you use the constructor352* {@code BatchUpdateException(String reason, String SQLState,353* int vendorCode, long []updateCounts,Throwable cause) }.354* </p>355* @param cause the underlying reason for this {@code SQLException} (which is saved for later retrieval by the {@code getCause()} method);356* may be null indicating357* the cause is non-existent or unknown.358* @since 1.6359* @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],360* java.lang.Throwable)361*/362public BatchUpdateException(String reason, String SQLState, int vendorCode,363int []updateCounts,Throwable cause) {364super(reason, SQLState, vendorCode, cause);365this.updateCounts = (updateCounts == null) ? null : Arrays.copyOf(updateCounts, updateCounts.length);366this.longUpdateCounts = (updateCounts == null) ? null : copyUpdateCount(updateCounts);367}368369/**370* Retrieves the update count for each update statement in the batch371* update that executed successfully before this exception occurred.372* A driver that implements batch updates may or may not continue to373* process the remaining commands in a batch when one of the commands374* fails to execute properly. If the driver continues processing commands,375* the array returned by this method will have as many elements as376* there are commands in the batch; otherwise, it will contain an377* update count for each command that executed successfully before378* the {@code BatchUpdateException} was thrown.379* <P>380* The possible return values for this method were modified for381* the Java 2 SDK, Standard Edition, version 1.3. This was done to382* accommodate the new option of continuing to process commands383* in a batch update after a {@code BatchUpdateException} object384* has been thrown.385*386* @return an array of {@code int} containing the update counts387* for the updates that were executed successfully before this error388* occurred. Or, if the driver continues to process commands after an389* error, one of the following for every command in the batch:390* <OL>391* <LI>an update count392* <LI>{@code Statement.SUCCESS_NO_INFO} to indicate that the command393* executed successfully but the number of rows affected is unknown394* <LI>{@code Statement.EXECUTE_FAILED} to indicate that the command395* failed to execute successfully396* </OL>397* @since 1.3398* @see #getLargeUpdateCounts()399*/400public int[] getUpdateCounts() {401return (updateCounts == null) ? null : Arrays.copyOf(updateCounts, updateCounts.length);402}403404/**405* Constructs a {@code BatchUpdateException} object initialized with406* a given {@code reason}, {@code SQLState}, {@code vendorCode}407* {@code cause} and {@code updateCounts}.408* <p>409* This constructor should be used when the returned update count may exceed410* {@link Integer#MAX_VALUE}.411*412* @param reason a description of the error413* @param SQLState an XOPEN or SQL:2003 code identifying the exception414* @param vendorCode an exception code used by a particular415* database vendor416* @param updateCounts an array of {@code long}, with each element417*indicating the update count, {@code Statement.SUCCESS_NO_INFO} or418* {@code Statement.EXECUTE_FAILED} for each SQL command in419* the batch for JDBC drivers that continue processing420* after a command failure; an update count or421* {@code Statement.SUCCESS_NO_INFO} for each SQL command in the batch422* prior to the failure for JDBC drivers that stop processing after a command423* failure424* @param cause the underlying reason for this {@code SQLException}425* (which is saved for later retrieval by the {@code getCause()} method);426* may be null indicating the cause is non-existent or unknown.427* @since 1.8428*/429public BatchUpdateException(String reason, String SQLState, int vendorCode,430long []updateCounts,Throwable cause) {431super(reason, SQLState, vendorCode, cause);432this.longUpdateCounts = (updateCounts == null) ? null : Arrays.copyOf(updateCounts, updateCounts.length);433this.updateCounts = (longUpdateCounts == null) ? null : copyUpdateCount(longUpdateCounts);434}435436/**437* Retrieves the update count for each update statement in the batch438* update that executed successfully before this exception occurred.439* A driver that implements batch updates may or may not continue to440* process the remaining commands in a batch when one of the commands441* fails to execute properly. If the driver continues processing commands,442* the array returned by this method will have as many elements as443* there are commands in the batch; otherwise, it will contain an444* update count for each command that executed successfully before445* the {@code BatchUpdateException} was thrown.446* <p>447* This method should be used when {@code Statement.executeLargeBatch} is448* invoked and the returned update count may exceed {@link Integer#MAX_VALUE}.449*450* @return an array of {@code long} containing the update counts451* for the updates that were executed successfully before this error452* occurred. Or, if the driver continues to process commands after an453* error, one of the following for every command in the batch:454* <OL>455* <LI>an update count456* <LI>{@code Statement.SUCCESS_NO_INFO} to indicate that the command457* executed successfully but the number of rows affected is unknown458* <LI>{@code Statement.EXECUTE_FAILED} to indicate that the command459* failed to execute successfully460* </OL>461* @since 1.8462*/463public long[] getLargeUpdateCounts() {464return (longUpdateCounts == null) ? null :465Arrays.copyOf(longUpdateCounts, longUpdateCounts.length);466}467468/**469* The array that describes the outcome of a batch execution.470* @serial471* @since 1.2472*/473private int[] updateCounts;474475/*476* Starting with Java SE 8, JDBC has added support for returning an update477* count > Integer.MAX_VALUE. Because of this the following changes were made478* to BatchUpdateException:479* <ul>480* <li>Add field longUpdateCounts</li>481* <li>Add Constructor which takes long[] for update counts</li>482* <li>Add getLargeUpdateCounts method</li>483* </ul>484* When any of the constructors are called, the int[] and long[] updateCount485* fields are populated by copying the one array to each other.486*487* As the JDBC driver passes in the updateCounts, there has always been the488* possibility for overflow and BatchUpdateException does not need to account489* for that, it simply copies the arrays.490*491* JDBC drivers should always use the constructor that specifies long[] and492* JDBC application developers should call getLargeUpdateCounts.493*/494495/**496* The array that describes the outcome of a batch execution.497* @serial498* @since 1.8499*/500private long[] longUpdateCounts;501502private static final long serialVersionUID = 5977529877145521757L;503504/*505* Utility method to copy int[] updateCount to long[] updateCount506*/507private static long[] copyUpdateCount(int[] uc) {508long[] copy = new long[uc.length];509for(int i= 0; i< uc.length; i++) {510copy[i] = uc[i];511}512return copy;513}514515/*516* Utility method to copy long[] updateCount to int[] updateCount.517* No checks for overflow will be done as it is expected a user will call518* getLargeUpdateCounts.519*/520private static int[] copyUpdateCount(long[] uc) {521int[] copy = new int[uc.length];522for(int i= 0; i< uc.length; i++) {523copy[i] = (int) uc[i];524}525return copy;526}527/**528* readObject is called to restore the state of the529* {@code BatchUpdateException} from a stream.530* @param s the {@code ObjectInputStream} to read from.531*532* @throws ClassNotFoundException if the class of a serialized object533* could not be found.534* @throws IOException if an I/O error occurs.535*/536private void readObject(ObjectInputStream s)537throws IOException, ClassNotFoundException {538539ObjectInputStream.GetField fields = s.readFields();540int[] tmp = (int[])fields.get("updateCounts", null);541long[] tmp2 = (long[])fields.get("longUpdateCounts", null);542if(tmp != null && tmp2 != null && tmp.length != tmp2.length)543throw new InvalidObjectException("update counts are not the expected size");544if (tmp != null)545updateCounts = tmp.clone();546if (tmp2 != null)547longUpdateCounts = tmp2.clone();548if(updateCounts == null && longUpdateCounts != null)549updateCounts = copyUpdateCount(longUpdateCounts);550if(longUpdateCounts == null && updateCounts != null)551longUpdateCounts = copyUpdateCount(updateCounts);552553}554555/**556* writeObject is called to save the state of the {@code BatchUpdateException}557* to a stream.558* @param s the {@code ObjectOutputStream} to write to.559* @throws IOException if an I/O error occurs.560*/561private void writeObject(ObjectOutputStream s)562throws IOException {563564ObjectOutputStream.PutField fields = s.putFields();565fields.put("updateCounts", updateCounts);566fields.put("longUpdateCounts", longUpdateCounts);567s.writeFields();568}569}570571572