diff --git a/src/java/com/samskivert/jdbc/depot/DatabaseException.java b/src/java/com/samskivert/jdbc/depot/DatabaseException.java new file mode 100644 index 0000000..8d2e524 --- /dev/null +++ b/src/java/com/samskivert/jdbc/depot/DatabaseException.java @@ -0,0 +1,53 @@ +// +// $Id$ +// +// samskivert library - useful routines for java programs +// Copyright (C) 2001-2008 Michael Bayne +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.samskivert.jdbc.depot; + +/** + * Represents a failure reported by the underlying database. + */ +public class DatabaseException extends RuntimeException +{ + /** + * Constructs a database exception with the specified error message. + */ + public DatabaseException (String message) + { + super(message); + } + + /** + * Constructs a database exception with the specified error message and the chained causing + * event. + */ + public DatabaseException (String message, Throwable cause) + { + super(message); + initCause(cause); + } + + /** + * Constructs a database exception with the specified chained causing event. + */ + public DatabaseException (Throwable cause) + { + initCause(cause); + } +} diff --git a/src/java/com/samskivert/jdbc/depot/DepotMarshaller.java b/src/java/com/samskivert/jdbc/depot/DepotMarshaller.java index f21456e..716b999 100644 --- a/src/java/com/samskivert/jdbc/depot/DepotMarshaller.java +++ b/src/java/com/samskivert/jdbc/depot/DepotMarshaller.java @@ -36,7 +36,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import com.samskivert.io.PersistenceException; import com.samskivert.jdbc.depot.annotation.Computed; import com.samskivert.jdbc.depot.annotation.Entity; import com.samskivert.jdbc.depot.annotation.FullTextIndex; @@ -525,7 +524,7 @@ public class DepotMarshaller * database schema, it will be migrated. */ protected void init (PersistenceContext ctx) - throws PersistenceException + throws DatabaseException { if (_initialized) { // sanity check throw new IllegalStateException( @@ -632,7 +631,7 @@ public class DepotMarshaller log.info("Waiting for migration lock for " + _pClass.getName() + "."); Thread.sleep(5000); } catch (InterruptedException ie) { - throw new PersistenceException("Interrupted while waiting for migration lock."); + throw new DatabaseException("Interrupted while waiting for migration lock."); } } @@ -672,7 +671,7 @@ public class DepotMarshaller protected void createTable (PersistenceContext ctx, final SQLBuilder builder, final ColumnDefinition[] declarations) - throws PersistenceException + throws DatabaseException { log.info("Creating initial table '" + getTableName() + "'."); @@ -721,7 +720,7 @@ public class DepotMarshaller protected void runMigrations (PersistenceContext ctx, TableMetaData metaData, final SQLBuilder builder, int currentVersion) - throws PersistenceException + throws DatabaseException { log.info("Migrating " + getTableName() + " from " + currentVersion + " to " + _schemaVersion + "..."); @@ -928,7 +927,7 @@ public class DepotMarshaller * Checks that there are no database columns for which we no longer have Java fields. */ protected void checkForStaleness (TableMetaData meta, PersistenceContext ctx, SQLBuilder builder) - throws PersistenceException + throws DatabaseException { for (String fname : _columnFields) { FieldMarshaller fmarsh = _fields.get(fname); @@ -992,7 +991,7 @@ public class DepotMarshaller public Set pkColumns = new HashSet(); public static TableMetaData load (PersistenceContext ctx, final String tableName) - throws PersistenceException + throws DatabaseException { return ctx.invoke(new Query.TrivialQuery() { @Override public TableMetaData invoke (Connection conn, DatabaseLiaison dl) diff --git a/src/java/com/samskivert/jdbc/depot/DepotRepository.java b/src/java/com/samskivert/jdbc/depot/DepotRepository.java index 7297176..ff54738 100644 --- a/src/java/com/samskivert/jdbc/depot/DepotRepository.java +++ b/src/java/com/samskivert/jdbc/depot/DepotRepository.java @@ -30,7 +30,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import com.samskivert.io.PersistenceException; import com.samskivert.util.ArrayUtil; import com.samskivert.jdbc.ConnectionProvider; @@ -81,7 +80,7 @@ public abstract class DepotRepository */ protected T load (Class type, Comparable primaryKey, QueryClause... clauses) - throws PersistenceException + throws DatabaseException { clauses = ArrayUtil.append(clauses, _ctx.getMarshaller(type).makePrimaryKey(primaryKey)); return load(type, clauses); @@ -92,7 +91,7 @@ public abstract class DepotRepository */ protected T load (Class type, String ix, Comparable val, QueryClause... clauses) - throws PersistenceException + throws DatabaseException { clauses = ArrayUtil.append(clauses, new Key(type, ix, val)); return load(type, clauses); @@ -104,7 +103,7 @@ public abstract class DepotRepository protected T load (Class type, String ix1, Comparable val1, String ix2, Comparable val2, QueryClause... clauses) - throws PersistenceException + throws DatabaseException { clauses = ArrayUtil.append(clauses, new Key(type, ix1, val1, ix2, val2)); return load(type, clauses); @@ -116,7 +115,7 @@ public abstract class DepotRepository protected T load (Class type, String ix1, Comparable val1, String ix2, Comparable val2, String ix3, Comparable val3, QueryClause... clauses) - throws PersistenceException + throws DatabaseException { clauses = ArrayUtil.append(clauses, new Key(type, ix1, val1, ix2, val2, ix3, val3)); return load(type, clauses); @@ -127,7 +126,7 @@ public abstract class DepotRepository */ protected T load ( Class type, Collection clauses) - throws PersistenceException + throws DatabaseException { return load(type, clauses.toArray(new QueryClause[clauses.size()])); } @@ -136,7 +135,7 @@ public abstract class DepotRepository * Loads the first persistent object that matches the supplied query clauses. */ protected T load (Class type, QueryClause... clauses) - throws PersistenceException + throws DatabaseException { return _ctx.invoke(new FindOneQuery(_ctx, type, clauses)); } @@ -155,7 +154,7 @@ public abstract class DepotRepository */ protected List findAll ( Class type, Collection clauses) - throws PersistenceException + throws DatabaseException { DepotMarshaller marsh = _ctx.getMarshaller(type); boolean useExplicit = @@ -175,7 +174,7 @@ public abstract class DepotRepository * A varargs version of {@link #findAll(Class,Collection)}. */ protected List findAll (Class type, QueryClause... clauses) - throws PersistenceException + throws DatabaseException { return findAll(type, Arrays.asList(clauses)); } @@ -187,7 +186,7 @@ public abstract class DepotRepository * @return the number of rows modified by this action, this should always be one. */ protected int insert (T record) - throws PersistenceException + throws DatabaseException { @SuppressWarnings("unchecked") final Class pClass = (Class) record.getClass(); final DepotMarshaller marsh = _ctx.getMarshaller(pClass); @@ -238,7 +237,7 @@ public abstract class DepotRepository * @return the number of rows modified by this action. */ protected int update (T record) - throws PersistenceException + throws DatabaseException { @SuppressWarnings("unchecked") Class pClass = (Class) record.getClass(); requireNotComputed(pClass, "update"); @@ -275,7 +274,7 @@ public abstract class DepotRepository * @return the number of rows modified by this action. */ protected int update (T record, final String... modifiedFields) - throws PersistenceException + throws DatabaseException { @SuppressWarnings("unchecked") Class pClass = (Class) record.getClass(); @@ -322,7 +321,7 @@ public abstract class DepotRepository */ protected int updatePartial ( Class type, Comparable primaryKey, Map updates) - throws PersistenceException + throws DatabaseException { Object[] fieldsValues = new Object[updates.size()*2]; int idx = 0; @@ -345,7 +344,7 @@ public abstract class DepotRepository */ protected int updatePartial ( Class type, Comparable primaryKey, Object... fieldsValues) - throws PersistenceException + throws DatabaseException { return updatePartial(_ctx.getMarshaller(type).makePrimaryKey(primaryKey), fieldsValues); } @@ -364,7 +363,7 @@ public abstract class DepotRepository protected int updatePartial ( Class type, String ix1, Comparable val1, String ix2, Comparable val2, Object... fieldsValues) - throws PersistenceException + throws DatabaseException { return updatePartial(new Key(type, ix1, val1, ix2, val2), fieldsValues); } @@ -383,7 +382,7 @@ public abstract class DepotRepository protected int updatePartial ( Class type, String ix1, Comparable val1, String ix2, Comparable val2, String ix3, Comparable val3, Object... fieldsValues) - throws PersistenceException + throws DatabaseException { return updatePartial(new Key(type, ix1, val1, ix2, val2, ix3, val3), fieldsValues); } @@ -398,7 +397,7 @@ public abstract class DepotRepository * @return the number of rows modified by this action. */ protected int updatePartial (Key key, Object... fieldsValues) - throws PersistenceException + throws DatabaseException { return updatePartial(key.condition.getPersistentClass(), key, key, fieldsValues); } @@ -420,7 +419,7 @@ public abstract class DepotRepository */ protected int updatePartial ( Class type, final WhereClause key, CacheInvalidator invalidator, Object... fieldsValues) - throws PersistenceException + throws DatabaseException { if (invalidator instanceof ValidatingCacheInvalidator) { ((ValidatingCacheInvalidator)invalidator).validateFlushType(type); // sanity check @@ -470,7 +469,7 @@ public abstract class DepotRepository */ protected int updateLiteral ( Class type, Comparable primaryKey, Map fieldsToValues) - throws PersistenceException + throws DatabaseException { Key key = _ctx.getMarshaller(type).makePrimaryKey(primaryKey); return updateLiteral(type, key, key, fieldsToValues); @@ -496,7 +495,7 @@ public abstract class DepotRepository protected int updateLiteral ( Class type, String ix1, Comparable val1, String ix2, Comparable val2, Map fieldsToValues) - throws PersistenceException + throws DatabaseException { Key key = new Key(type, ix1, val1, ix2, val2); return updateLiteral(type, key, key, fieldsToValues); @@ -522,7 +521,7 @@ public abstract class DepotRepository protected int updateLiteral ( Class type, String ix1, Comparable val1, String ix2, Comparable val2, String ix3, Comparable val3, Map fieldsToValues) - throws PersistenceException + throws DatabaseException { Key key = new Key(type, ix1, val1, ix2, val2, ix3, val3); return updateLiteral(type, key, key, fieldsToValues); @@ -548,7 +547,7 @@ public abstract class DepotRepository protected int updateLiteral ( Class type, final WhereClause key, CacheInvalidator invalidator, Map fieldsToValues) - throws PersistenceException + throws DatabaseException { requireNotComputed(type, "updateLiteral"); @@ -592,7 +591,7 @@ public abstract class DepotRepository * @return true if the record was created, false if it was updated. */ protected boolean store (T record) - throws PersistenceException + throws DatabaseException { @SuppressWarnings("unchecked") final Class pClass = (Class) record.getClass(); requireNotComputed(pClass, "store"); @@ -665,7 +664,7 @@ public abstract class DepotRepository * @return the number of rows deleted by this action. */ protected int delete (T record) - throws PersistenceException + throws DatabaseException { @SuppressWarnings("unchecked") Class type = (Class)record.getClass(); Key primaryKey = _ctx.getMarshaller(type).getPrimaryKey(record); @@ -683,7 +682,7 @@ public abstract class DepotRepository */ protected int delete ( Class type, Comparable primaryKeyValue) - throws PersistenceException + throws DatabaseException { return delete(type, _ctx.getMarshaller(type).makePrimaryKey(primaryKeyValue)); } @@ -695,7 +694,7 @@ public abstract class DepotRepository * @return the number of rows deleted by this action. */ protected int delete (Class type, Key primaryKey) - throws PersistenceException + throws DatabaseException { return deleteAll(type, primaryKey, primaryKey); } @@ -707,7 +706,7 @@ public abstract class DepotRepository */ protected int deleteAll ( Class type, final WhereClause key, CacheInvalidator invalidator) - throws PersistenceException + throws DatabaseException { if (invalidator instanceof ValidatingCacheInvalidator) { ((ValidatingCacheInvalidator)invalidator).validateFlushType(type); // sanity check @@ -733,14 +732,14 @@ public abstract class DepotRepository // make sure the given type corresponds to a concrete class protected void requireNotComputed (Class type, String action) - throws PersistenceException + throws DatabaseException { DepotMarshaller marsh = _ctx.getMarshaller(type); if (marsh == null) { - throw new PersistenceException("Unknown persistent type [class=" + type + "]"); + throw new DatabaseException("Unknown persistent type [class=" + type + "]"); } if (marsh.getTableName() == null) { - throw new PersistenceException( + throw new DatabaseException( "Can't " + action + " computed entities [class=" + type + "]"); } } diff --git a/src/java/com/samskivert/jdbc/depot/DepotTypes.java b/src/java/com/samskivert/jdbc/depot/DepotTypes.java index e416636..d51f9c1 100644 --- a/src/java/com/samskivert/jdbc/depot/DepotTypes.java +++ b/src/java/com/samskivert/jdbc/depot/DepotTypes.java @@ -29,7 +29,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import com.samskivert.io.PersistenceException; import com.samskivert.jdbc.depot.clause.QueryClause; import com.samskivert.jdbc.depot.expression.SQLExpression; @@ -40,9 +39,9 @@ import com.samskivert.jdbc.depot.expression.SQLExpression; * constructed. * * The main motivation for breaking this functionality out into its own class is to encapsulate the - * operation that throws {@link PersistenceException} as separate from the operations that throw + * operation that throws {@link DatabaseException} as separate from the operations that throw * {@link SQLException}. Once this class has been constructed, it may be used to create {@link - * SQLBuilder} instances without any {@link PersistenceException} worries. + * SQLBuilder} instances without any {@link DatabaseException} worries. */ public class DepotTypes { @@ -56,7 +55,7 @@ public class DepotTypes */ public static DepotTypes getDepotTypes ( PersistenceContext ctx, Collection clauses) - throws PersistenceException + throws DatabaseException { Set> classSet = new HashSet>(); @@ -73,7 +72,7 @@ public class DepotTypes */ public static DepotTypes getDepotTypes ( PersistenceContext ctx, QueryClause... clauses) - throws PersistenceException + throws DatabaseException { return getDepotTypes(ctx, Arrays.asList(clauses)); } @@ -83,7 +82,7 @@ public class DepotTypes * persistent record classes. */ public DepotTypes (PersistenceContext ctx, Collection> others) - throws PersistenceException + throws DatabaseException { for (Class c : others) { addClass(ctx, c); @@ -95,7 +94,7 @@ public class DepotTypes * persistent record. */ public DepotTypes (PersistenceContext ctx, Class pClass) - throws PersistenceException + throws DatabaseException { addClass(ctx, pClass); } @@ -165,7 +164,7 @@ public class DepotTypes * Register a new persistent class with this object. */ public void addClass (PersistenceContext ctx, Class type) - throws PersistenceException + throws DatabaseException { if (_classMap.containsKey(type)) { return; diff --git a/src/java/com/samskivert/jdbc/depot/DuplicateKeyException.java b/src/java/com/samskivert/jdbc/depot/DuplicateKeyException.java new file mode 100644 index 0000000..9096089 --- /dev/null +++ b/src/java/com/samskivert/jdbc/depot/DuplicateKeyException.java @@ -0,0 +1,33 @@ +// +// $Id$ +// +// samskivert library - useful routines for java programs +// Copyright (C) 2001-2008 Michael Bayne +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.samskivert.jdbc.depot; + +/** + * Thrown when an insert or update results in a duplicate key on a column that has a uniqueness + * constraint. + */ +public class DuplicateKeyException extends DatabaseException +{ + public DuplicateKeyException (String message) + { + super(message); + } +} diff --git a/src/java/com/samskivert/jdbc/depot/FieldMarshaller.java b/src/java/com/samskivert/jdbc/depot/FieldMarshaller.java index 6628749..3d7b672 100644 --- a/src/java/com/samskivert/jdbc/depot/FieldMarshaller.java +++ b/src/java/com/samskivert/jdbc/depot/FieldMarshaller.java @@ -33,7 +33,6 @@ import java.sql.SQLException; import java.sql.Time; import java.sql.Timestamp; -import com.samskivert.io.PersistenceException; import com.samskivert.jdbc.ColumnDefinition; import com.samskivert.jdbc.depot.annotation.Column; import com.samskivert.jdbc.depot.annotation.Computed; @@ -116,7 +115,7 @@ public abstract class FieldMarshaller * definition according to the appropriate database dialect. */ public void init (SQLBuilder builder) - throws PersistenceException + throws DatabaseException { _columnDefinition = builder.buildColumnDefinition(this); } diff --git a/src/java/com/samskivert/jdbc/depot/FindAllQuery.java b/src/java/com/samskivert/jdbc/depot/FindAllQuery.java index 976299d..6ee84cb 100644 --- a/src/java/com/samskivert/jdbc/depot/FindAllQuery.java +++ b/src/java/com/samskivert/jdbc/depot/FindAllQuery.java @@ -34,8 +34,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import com.samskivert.io.PersistenceException; - import com.samskivert.jdbc.DatabaseLiaison; import com.samskivert.jdbc.JDBCUtil; @@ -63,7 +61,7 @@ public abstract class FindAllQuery { public WithCache (PersistenceContext ctx, Class type, Collection clauses) - throws PersistenceException + throws DatabaseException { super(ctx, type); @@ -84,7 +82,8 @@ public abstract class FindAllQuery _clauses = clauses; } - public List invoke (Connection conn, DatabaseLiaison liaison) throws SQLException + public List invoke (Connection conn, DatabaseLiaison liaison) + throws SQLException { Map, T> entities = new HashMap, T>(); List> allKeys = new ArrayList>(); @@ -205,7 +204,7 @@ public abstract class FindAllQuery { public Explicitly (PersistenceContext ctx, Class type, Collection clauses) - throws PersistenceException + throws DatabaseException { super(ctx, type); SelectClause select = new SelectClause(type, _marsh.getFieldNames(), clauses); @@ -213,7 +212,8 @@ public abstract class FindAllQuery _builder.newQuery(select); } - public List invoke (Connection conn, DatabaseLiaison liaison) throws SQLException + public List invoke (Connection conn, DatabaseLiaison liaison) + throws SQLException { List result = new ArrayList(); PreparedStatement stmt = _builder.prepare(conn); @@ -230,7 +230,7 @@ public abstract class FindAllQuery } public FindAllQuery (PersistenceContext ctx, Class type) - throws PersistenceException + throws DatabaseException { _ctx = ctx; _type = type; diff --git a/src/java/com/samskivert/jdbc/depot/FindOneQuery.java b/src/java/com/samskivert/jdbc/depot/FindOneQuery.java index 7bf34fc..a9b82f9 100644 --- a/src/java/com/samskivert/jdbc/depot/FindOneQuery.java +++ b/src/java/com/samskivert/jdbc/depot/FindOneQuery.java @@ -25,8 +25,6 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import com.samskivert.io.PersistenceException; - import com.samskivert.jdbc.DatabaseLiaison; import com.samskivert.jdbc.JDBCUtil; import com.samskivert.jdbc.depot.clause.QueryClause; @@ -39,7 +37,7 @@ public class FindOneQuery implements Query { public FindOneQuery (PersistenceContext ctx, Class type, QueryClause[] clauses) - throws PersistenceException + throws DatabaseException { _marsh = ctx.getMarshaller(type); _select = new SelectClause(type, _marsh.getFieldNames(), clauses); diff --git a/src/java/com/samskivert/jdbc/depot/PersistenceContext.java b/src/java/com/samskivert/jdbc/depot/PersistenceContext.java index 0e376a0..7964237 100644 --- a/src/java/com/samskivert/jdbc/depot/PersistenceContext.java +++ b/src/java/com/samskivert/jdbc/depot/PersistenceContext.java @@ -34,7 +34,6 @@ import com.samskivert.util.StringUtil; import com.samskivert.jdbc.ConnectionProvider; import com.samskivert.jdbc.DatabaseLiaison; -import com.samskivert.jdbc.DuplicateKeyException; import com.samskivert.jdbc.LiaisonRegistry; import com.samskivert.jdbc.MySQLLiaison; import com.samskivert.jdbc.PostgreSQLLiaison; @@ -219,7 +218,7 @@ public class PersistenceContext * it if necessary. */ public DepotMarshaller getMarshaller (Class type) - throws PersistenceException + throws DatabaseException { DepotMarshaller marshaller = getRawMarshaller(type); try { @@ -231,8 +230,8 @@ public class PersistenceContext log.warning("Record initialized lazily [type=" + type.getName() + "]."); } } - } catch (PersistenceException pe) { - throw (PersistenceException)new PersistenceException( + } catch (DatabaseException pe) { + throw (DatabaseException)new DatabaseException( "Failed to initialize marshaller [type=" + type + "].").initCause(pe); } return marshaller; @@ -242,7 +241,7 @@ public class PersistenceContext * Invokes a non-modifying query and returns its result. */ public T invoke (Query query) - throws PersistenceException + throws DatabaseException { CacheKey key = query.getCacheKey(); // if there is a cache key, check the cache @@ -270,7 +269,7 @@ public class PersistenceContext * Invokes a modifying query and returns the number of rows modified. */ public int invoke (Modifier modifier) - throws PersistenceException + throws DatabaseException { modifier.cacheInvalidation(this); int rows = (Integer) invoke(null, modifier, true); @@ -456,7 +455,7 @@ public class PersistenceContext * to ensure that those records are properly registered prior to this call. */ public void initializeManagedRecords (boolean warnOnLazyInit) - throws PersistenceException + throws DatabaseException { for (Class rclass : _managedRecords) { getMarshaller(rclass); @@ -495,10 +494,16 @@ public class PersistenceContext */ protected Object invoke ( Query query, Modifier modifier, boolean retryOnTransientFailure) - throws PersistenceException + throws DatabaseException { boolean isReadOnlyQuery = (query != null); - Connection conn = _conprov.getConnection(_ident, isReadOnlyQuery); + Connection conn; + try { + conn = _conprov.getConnection(_ident, isReadOnlyQuery); + } catch (PersistenceException pe) { + throw new DatabaseException(pe.getMessage(), pe.getCause()); + } + // TEMP: we synchronize on the connection to cooperate with SimpleRepository when used in // conjunction with a StaticConnectionProvider; at some point we'll switch to standard JDBC // connection pooling which will block in getConnection() instead of returning a connection @@ -538,7 +543,7 @@ public class PersistenceContext } else { String msg = isReadOnlyQuery ? "Query failure " + query : "Modifier failure " + modifier; - throw new PersistenceException(msg, sqe); + throw new DatabaseException(msg, sqe); } } finally {