Author: ppoddar
Date: Mon Dec 10 11:15:35 2007
New Revision: 603001
URL: http://svn.apache.org/viewvc?rev=603001&view=rev
Log:
OPENJPA-462: Narrow StoreException by SQLException.getSQLState()
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ObjectExistsException.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java?rev=603001&r1=603000&r2=603001&view=diff
==============================================================================
---
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
(original)
+++
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
Mon Dec 10 11:15:35 2007
@@ -98,7 +98,6 @@
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 @@
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,11 +4015,30 @@
*/
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
+ * [EMAIL PROTECTED] ReferentialIntegrityException} rather than more
general
+ * [EMAIL PROTECTED] 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;
}
/**
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java?rev=603001&r1=603000&r2=603001&view=diff
==============================================================================
---
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java
(original)
+++
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java
Mon Dec 10 11:15:35 2007
@@ -23,7 +23,12 @@
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 @@
setNestedThrowables(ses);
return dict.newStoreException(msg, ses, failed);
}
-
+
/**
* Returns an array of [EMAIL PROTECTED] SQLException} instances for the
* specified exception.
@@ -111,5 +116,33 @@
se = se.getNextException();
}
return (SQLException[]) errs.toArray(new SQLException[errs.size()]);
+ }
+
+ /**
+ * Narrows the given SQLException to a specific type of
+ * [EMAIL PROTECTED] StoreException#getSubtype() StoreException} by
analyzing the
+ * SQLState code supplied by SQLException. Each database-specific
+ * [EMAIL PROTECTED] DBDictionary dictionary} can supply a set of error
codes that will
+ * map to a specific specific type of StoreException via
+ * [EMAIL PROTECTED] DBDictionary#getSQLStates(int) getSQLStates()} method.
+ * The default behavior is to return generic [EMAIL PROTECTED]
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);
}
}
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ObjectExistsException.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ObjectExistsException.java?rev=603001&r1=603000&r2=603001&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ObjectExistsException.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ObjectExistsException.java
Mon Dec 10 11:15:35 2007
@@ -28,6 +28,10 @@
public class ObjectExistsException
extends StoreException {
+ public ObjectExistsException(String msg) {
+ super(msg);
+ }
+
public ObjectExistsException(Message msg) {
super(msg);
}
Modified:
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java?rev=603001&r1=603000&r2=603001&view=diff
==============================================================================
---
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java
(original)
+++
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java
Mon Dec 10 11:15:35 2007
@@ -146,6 +146,7 @@
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());