mirror of https://github.com/apache/openjpa.git
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:
parent
88aa0ce910
commit
a54f842624
|
@ -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,12 +4015,31 @@ 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
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -96,7 +101,7 @@ public class SQLExceptions {
|
|||
setNestedThrowables(ses);
|
||||
return dict.newStoreException(msg, ses, failed);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of {@link SQLException} instances for the
|
||||
* specified exception.
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
Loading…
Reference in New Issue