OPENJPA-462: Narrow StoreException by SQLException.getSQLState()

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@603001 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Pinaki Poddar 2007-12-10 19:15:35 +00:00
parent 88aa0ce910
commit a54f842624
4 changed files with 71 additions and 5 deletions

View File

@ -98,7 +98,6 @@ import org.apache.openjpa.util.GeneralException;
import org.apache.openjpa.util.InternalException;
import org.apache.openjpa.util.InvalidStateException;
import org.apache.openjpa.util.OpenJPAException;
import org.apache.openjpa.util.ReferentialIntegrityException;
import org.apache.openjpa.util.Serialization;
import org.apache.openjpa.util.StoreException;
import org.apache.openjpa.util.UnsupportedException;
@ -150,6 +149,16 @@ public class DBDictionary
private static final String ZERO_TIMESTAMP_STR =
"'" + new Timestamp(0) + "'";
public static final List EMPTY_STRING_LIST = Arrays.asList(new String[]{});
public static final List[] SQL_STATE_CODES =
{EMPTY_STRING_LIST, // 0: Default
Arrays.asList(new String[]{"41000"}), // 1: LOCK
EMPTY_STRING_LIST, // 2: OBJECT_NOT_FOUND
EMPTY_STRING_LIST, // 3: OPTIMISTIC
Arrays.asList(new String[]{"23000"}), // 4: REFERENTIAL_INTEGRITY
EMPTY_STRING_LIST // 5: OBJECT_EXISTS
};
private static final Localizer _loc = Localizer.forPackage
(DBDictionary.class);
@ -4006,13 +4015,32 @@ public class DBDictionary
*/
public OpenJPAException newStoreException(String msg, SQLException[] causes,
Object failed) {
if (causes.length > 0 && "23000".equals(causes[0].getSQLState()))
return new ReferentialIntegrityException(msg).
setFailedObject(failed).setNestedThrowables(causes);
if (causes != null && causes.length > 0) {
OpenJPAException ret = SQLExceptions.narrow(msg, causes[0], this);
ret.setFailedObject(failed).setNestedThrowables(causes);
return ret;
}
return new StoreException(msg).setFailedObject(failed).
setNestedThrowables(causes);
}
/**
* Gets the list of String, each represents an error that can help
* to narrow down a SQL exception to specific type of StoreException.<br>
* For example, error code <code>"23000"</code> represents referential
* integrity violation and hence can be narrowed down to
* {@link ReferentialIntegrityException} rather than more general
* {@link StoreException}.<br>
* JDBC Drivers are not uniform in return values of SQLState for the same
* error and hence each database specific Dictionary can specialize.<br>
* Default behavior is to return an empty list.
*/
public List/*<String>*/ getSQLStates(int exceptionType) {
if (exceptionType>=0 && exceptionType<SQL_STATE_CODES.length)
return SQL_STATE_CODES[exceptionType];
return EMPTY_STRING_LIST;
}
/**
* Closes the specified {@link DataSource} and releases any
* resources associated with it.

View File

@ -23,7 +23,12 @@ import java.util.LinkedList;
import java.util.List;
import org.apache.openjpa.lib.util.Localizer.Message;
import org.apache.openjpa.util.LockException;
import org.apache.openjpa.util.ObjectExistsException;
import org.apache.openjpa.util.ObjectNotFoundException;
import org.apache.openjpa.util.OpenJPAException;
import org.apache.openjpa.util.OptimisticException;
import org.apache.openjpa.util.ReferentialIntegrityException;
import org.apache.openjpa.util.StoreException;
/**
@ -112,4 +117,32 @@ public class SQLExceptions {
}
return (SQLException[]) errs.toArray(new SQLException[errs.size()]);
}
/**
* Narrows the given SQLException to a specific type of
* {@link StoreException#getSubtype() StoreException} by analyzing the
* SQLState code supplied by SQLException. Each database-specific
* {@link DBDictionary dictionary} can supply a set of error codes that will
* map to a specific specific type of StoreException via
* {@link DBDictionary#getSQLStates(int) getSQLStates()} method.
* The default behavior is to return generic {@link StoreException
* StoreException}.
*/
public static OpenJPAException narrow(String msg, SQLException se,
DBDictionary dict) {
String e = se.getSQLState();
if (dict.getSQLStates(StoreException.LOCK).contains(e))
return new LockException(msg);
else if (dict.getSQLStates(StoreException.OBJECT_EXISTS).contains(e))
return new ObjectExistsException(msg);
else if (dict.getSQLStates(StoreException.OBJECT_NOT_FOUND).contains(e))
return new ObjectNotFoundException(msg);
else if (dict.getSQLStates(StoreException.OPTIMISTIC).contains(e))
return new OptimisticException(msg);
else if (dict.getSQLStates(StoreException.REFERENTIAL_INTEGRITY)
.contains(e))
return new ReferentialIntegrityException(msg);
else
return new StoreException(msg);
}
}

View File

@ -28,6 +28,10 @@ import org.apache.openjpa.lib.util.Localizer.Message;
public class ObjectExistsException
extends StoreException {
public ObjectExistsException(String msg) {
super(msg);
}
public ObjectExistsException(Message msg) {
super(msg);
}

View File

@ -146,6 +146,7 @@ public class PersistenceExceptions
getFailedObject(ke), ke.isFatal());
break;
case StoreException.OPTIMISTIC:
case StoreException.LOCK:
e = new org.apache.openjpa.persistence.OptimisticLockException
(ke.getMessage(), getNestedThrowables(ke),
getFailedObject(ke), ke.isFatal());