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.InternalException;
|
||||||
import org.apache.openjpa.util.InvalidStateException;
|
import org.apache.openjpa.util.InvalidStateException;
|
||||||
import org.apache.openjpa.util.OpenJPAException;
|
import org.apache.openjpa.util.OpenJPAException;
|
||||||
import org.apache.openjpa.util.ReferentialIntegrityException;
|
|
||||||
import org.apache.openjpa.util.Serialization;
|
import org.apache.openjpa.util.Serialization;
|
||||||
import org.apache.openjpa.util.StoreException;
|
import org.apache.openjpa.util.StoreException;
|
||||||
import org.apache.openjpa.util.UnsupportedException;
|
import org.apache.openjpa.util.UnsupportedException;
|
||||||
|
@ -150,6 +149,16 @@ public class DBDictionary
|
||||||
private static final String ZERO_TIMESTAMP_STR =
|
private static final String ZERO_TIMESTAMP_STR =
|
||||||
"'" + new Timestamp(0) + "'";
|
"'" + 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
|
private static final Localizer _loc = Localizer.forPackage
|
||||||
(DBDictionary.class);
|
(DBDictionary.class);
|
||||||
|
|
||||||
|
@ -4006,12 +4015,31 @@ public class DBDictionary
|
||||||
*/
|
*/
|
||||||
public OpenJPAException newStoreException(String msg, SQLException[] causes,
|
public OpenJPAException newStoreException(String msg, SQLException[] causes,
|
||||||
Object failed) {
|
Object failed) {
|
||||||
if (causes.length > 0 && "23000".equals(causes[0].getSQLState()))
|
if (causes != null && causes.length > 0) {
|
||||||
return new ReferentialIntegrityException(msg).
|
OpenJPAException ret = SQLExceptions.narrow(msg, causes[0], this);
|
||||||
setFailedObject(failed).setNestedThrowables(causes);
|
ret.setFailedObject(failed).setNestedThrowables(causes);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
return new StoreException(msg).setFailedObject(failed).
|
return new StoreException(msg).setFailedObject(failed).
|
||||||
setNestedThrowables(causes);
|
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
|
* Closes the specified {@link DataSource} and releases any
|
||||||
|
|
|
@ -23,7 +23,12 @@ import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.openjpa.lib.util.Localizer.Message;
|
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.OpenJPAException;
|
||||||
|
import org.apache.openjpa.util.OptimisticException;
|
||||||
|
import org.apache.openjpa.util.ReferentialIntegrityException;
|
||||||
import org.apache.openjpa.util.StoreException;
|
import org.apache.openjpa.util.StoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -96,7 +101,7 @@ public class SQLExceptions {
|
||||||
setNestedThrowables(ses);
|
setNestedThrowables(ses);
|
||||||
return dict.newStoreException(msg, ses, failed);
|
return dict.newStoreException(msg, ses, failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of {@link SQLException} instances for the
|
* Returns an array of {@link SQLException} instances for the
|
||||||
* specified exception.
|
* specified exception.
|
||||||
|
@ -112,4 +117,32 @@ public class SQLExceptions {
|
||||||
}
|
}
|
||||||
return (SQLException[]) errs.toArray(new SQLException[errs.size()]);
|
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
|
public class ObjectExistsException
|
||||||
extends StoreException {
|
extends StoreException {
|
||||||
|
|
||||||
|
public ObjectExistsException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
public ObjectExistsException(Message msg) {
|
public ObjectExistsException(Message msg) {
|
||||||
super(msg);
|
super(msg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,6 +146,7 @@ public class PersistenceExceptions
|
||||||
getFailedObject(ke), ke.isFatal());
|
getFailedObject(ke), ke.isFatal());
|
||||||
break;
|
break;
|
||||||
case StoreException.OPTIMISTIC:
|
case StoreException.OPTIMISTIC:
|
||||||
|
case StoreException.LOCK:
|
||||||
e = new org.apache.openjpa.persistence.OptimisticLockException
|
e = new org.apache.openjpa.persistence.OptimisticLockException
|
||||||
(ke.getMessage(), getNestedThrowables(ke),
|
(ke.getMessage(), getNestedThrowables(ke),
|
||||||
getFailedObject(ke), ke.isFatal());
|
getFailedObject(ke), ke.isFatal());
|
||||||
|
|
Loading…
Reference in New Issue