[#910] Add ExecuteListener extension to allow for overriding exception
translator to handle vendor-specific error codes
This commit is contained in:
parent
eaf66c19d2
commit
97e8fbc9f0
@ -53,7 +53,6 @@ import java.util.List;
|
||||
import java.util.Queue;
|
||||
|
||||
import org.jooq.ExecuteContext;
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.ExecuteType;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Result;
|
||||
@ -61,6 +60,7 @@ import org.jooq.TableRecord;
|
||||
import org.jooq.UpdatableRecord;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.conf.SettingsTools;
|
||||
import org.jooq.impl.DefaultExecuteListener;
|
||||
import org.jooq.impl.Factory;
|
||||
import org.jooq.test.BaseTest;
|
||||
import org.jooq.test.jOOQAbstractTest;
|
||||
@ -92,6 +92,26 @@ extends BaseTest<A, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T658, T725
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteListenerCustomException() throws Exception {
|
||||
Factory create = create(new Settings()
|
||||
.withExecuteListeners(CustomExceptionListener.class.getName()));
|
||||
|
||||
try {
|
||||
create.fetch("invalid sql");
|
||||
}
|
||||
catch (E e) {
|
||||
assertEquals("ERROR", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static class CustomExceptionListener extends DefaultExecuteListener {
|
||||
@Override
|
||||
public void exception(ExecuteContext ctx) {
|
||||
ctx.exception(new E("ERROR"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteListenerOnResultQuery() throws Exception {
|
||||
Factory create = create(new Settings()
|
||||
@ -129,7 +149,7 @@ extends BaseTest<A, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T658, T725
|
||||
assertEquals(2, result.size());
|
||||
}
|
||||
|
||||
public static class ResultQueryListener implements ExecuteListener {
|
||||
public static class ResultQueryListener extends DefaultExecuteListener {
|
||||
|
||||
// A counter that is incremented in callback methods
|
||||
private static int callbackCount = 0;
|
||||
@ -412,6 +432,18 @@ extends BaseTest<A, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T658, T725
|
||||
}
|
||||
}
|
||||
|
||||
static class E extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
*/
|
||||
private static final long serialVersionUID = 594781555404278995L;
|
||||
|
||||
public E(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteListenerOnBatchSingle() {
|
||||
if (!executePreparedStatements(create().getSettings())) {
|
||||
@ -450,7 +482,7 @@ extends BaseTest<A, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T658, T725
|
||||
assertEquals(14, BatchSingleListener.end);
|
||||
}
|
||||
|
||||
public static class BatchSingleListener implements ExecuteListener {
|
||||
public static class BatchSingleListener extends DefaultExecuteListener {
|
||||
|
||||
// A counter that is incremented in callback methods
|
||||
private static int callbackCount = 0;
|
||||
@ -672,7 +704,7 @@ extends BaseTest<A, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T658, T725
|
||||
assertEquals(20, BatchMultipleListener.end);
|
||||
}
|
||||
|
||||
public static class BatchMultipleListener implements ExecuteListener {
|
||||
public static class BatchMultipleListener extends DefaultExecuteListener {
|
||||
|
||||
// A counter that is incremented in callback methods
|
||||
private static int callbackCount = 0;
|
||||
|
||||
@ -413,7 +413,7 @@ extends BaseTest<A, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T658, T725
|
||||
context.statement().setInt(context.nextIndex(), 2);
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw translate("CustomCondition.bind", getSQL(), e);
|
||||
throw translate(getSQL(), e);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -443,7 +443,7 @@ extends BaseTest<A, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T658, T725
|
||||
context.statement().setInt(context.nextIndex(), 3);
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw translate("CustomCondition.bind", getSQL(), e);
|
||||
throw translate(getSQL(), e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1487,6 +1487,11 @@ public abstract class jOOQAbstractTest<
|
||||
new ExecuteListenerTests(this).testExecuteListenerOnResultQuery();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteListenerCustomException() throws Exception {
|
||||
new ExecuteListenerTests(this).testExecuteListenerCustomException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteListenerOnBatchSingle() throws Exception {
|
||||
new ExecuteListenerTests(this).testExecuteListenerOnBatchSingle();
|
||||
|
||||
@ -38,8 +38,10 @@ package org.jooq;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.jooq.conf.StatementType;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
|
||||
/**
|
||||
* A context object for {@link Query} execution passed to registered
|
||||
@ -104,8 +106,9 @@ public interface ExecuteContext extends Configuration {
|
||||
String sql();
|
||||
|
||||
/**
|
||||
* Override the SQL statement that is being executed. This may have no
|
||||
* effect, if called at the wrong moment.
|
||||
* Override the SQL statement that is being executed.
|
||||
* <p>
|
||||
* This may have no effect, if called at the wrong moment.
|
||||
*
|
||||
* @see ExecuteListener#renderEnd(ExecuteContext)
|
||||
* @see ExecuteListener#prepareStart(ExecuteContext)
|
||||
@ -133,8 +136,9 @@ public interface ExecuteContext extends Configuration {
|
||||
Connection getConnection();
|
||||
|
||||
/**
|
||||
* Override the {@link Connection} that is being used for execution. This
|
||||
* may have no effect, if called at the wrong moment.
|
||||
* Override the {@link Connection} that is being used for execution.
|
||||
* <p>
|
||||
* This may have no effect, if called at the wrong moment.
|
||||
*
|
||||
* @see ExecuteListener#start(ExecuteContext)
|
||||
*/
|
||||
@ -161,8 +165,9 @@ public interface ExecuteContext extends Configuration {
|
||||
PreparedStatement statement();
|
||||
|
||||
/**
|
||||
* Override the {@link PreparedStatement} that is being executed. This may
|
||||
* have no effect, if called at the wrong moment.
|
||||
* Override the {@link PreparedStatement} that is being executed.
|
||||
* <p>
|
||||
* This may have no effect, if called at the wrong moment.
|
||||
*
|
||||
* @see ExecuteListener#prepareEnd(ExecuteContext)
|
||||
* @see ExecuteListener#bindStart(ExecuteContext)
|
||||
@ -176,8 +181,9 @@ public interface ExecuteContext extends Configuration {
|
||||
ResultSet resultSet();
|
||||
|
||||
/**
|
||||
* Override the {@link ResultSet} that is being fetched. This may have no
|
||||
* effect, if called at the wrong moment.
|
||||
* Override the {@link ResultSet} that is being fetched.
|
||||
* <p>
|
||||
* This may have no effect, if called at the wrong moment.
|
||||
*
|
||||
* @see ExecuteListener#executeEnd(ExecuteContext)
|
||||
* @see ExecuteListener#fetchStart(ExecuteContext)
|
||||
@ -205,4 +211,31 @@ public interface ExecuteContext extends Configuration {
|
||||
* Calling this has no effect. It is being used by jOOQ internally.
|
||||
*/
|
||||
void result(Result<?> result);
|
||||
|
||||
/**
|
||||
* The {@link RuntimeException} being thrown.
|
||||
*/
|
||||
RuntimeException exception();
|
||||
|
||||
/**
|
||||
* Override the {@link RuntimeException} being thrown.
|
||||
* <p>
|
||||
* This may have no effect, if called at the wrong moment.
|
||||
*/
|
||||
void exception(RuntimeException e);
|
||||
|
||||
/**
|
||||
* The {@link SQLException} that was thrown by the database.
|
||||
*/
|
||||
SQLException sqlException();
|
||||
|
||||
/**
|
||||
* Override the {@link SQLException} being thrown.
|
||||
* <p>
|
||||
* Any <code>SQLException</code> will be wrapped by jOOQ using an unchecked
|
||||
* {@link DataAccessException}. To have jOOQ throw your own custom
|
||||
* {@link RuntimeException}, use {@link #exception(RuntimeException)}
|
||||
* instead. This may have no effect, if called at the wrong moment.
|
||||
*/
|
||||
void sqlException(SQLException e);
|
||||
}
|
||||
|
||||
@ -38,6 +38,7 @@ package org.jooq;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.conf.StatementType;
|
||||
@ -56,11 +57,11 @@ import org.jooq.tools.StopWatchListener;
|
||||
* <code>Settings</code> to
|
||||
* {@link Factory#Factory(java.sql.Connection, SQLDialect, Settings)}. Advanced
|
||||
* <code>ExecuteListeners</code> can also provide custom implementations of
|
||||
* {@link Connection}, {@link PreparedStatement} and {@link ResultSet} to jOOQ
|
||||
* in apropriate methods. For convenience, consider extending
|
||||
* {@link DefaultExecuteListener} instead of implementing this interface. This
|
||||
* will prevent compilation errors in future versions of jOOQ, when this
|
||||
* interface might get new methods.
|
||||
* {@link Connection}, {@link PreparedStatement}, {@link ResultSet},
|
||||
* {@link SQLException} or {@link RuntimeException} to jOOQ in apropriate
|
||||
* methods. For convenience, consider extending {@link DefaultExecuteListener}
|
||||
* instead of implementing this interface. This will prevent compilation errors
|
||||
* in future versions of jOOQ, when this interface might get new methods.
|
||||
* <p>
|
||||
* The following table explains how every type of statement / operation invokes
|
||||
* callback methods in the correct order for all registered
|
||||
@ -220,6 +221,15 @@ import org.jooq.tools.StopWatchListener;
|
||||
* <td>Yes, 1x</td>
|
||||
* <td>Yes, 1x</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link #exception(ExecuteContext)}</td>
|
||||
* <td>Maybe, 1x</td>
|
||||
* <td>Maybe, 1x</td>
|
||||
* <td>Maybe, 1x</td>
|
||||
* <td>Maybe, 1x</td>
|
||||
* <td>Maybe, 1x</td>
|
||||
* <td>Maybe, 1x</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* <br/>
|
||||
* <h3>Legend:</h3>
|
||||
@ -236,7 +246,8 @@ import org.jooq.tools.StopWatchListener;
|
||||
* </ol>
|
||||
* <p>
|
||||
* If nothing is specified, the default is to use {@link LoggerListener} and
|
||||
* {@link StopWatchListener} as the only event listeners.
|
||||
* {@link StopWatchListener} as the only event listeners, as configured in
|
||||
* {@link Settings#isExecuteLogging()}
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
@ -808,7 +819,7 @@ public interface ExecuteListener {
|
||||
void fetchEnd(ExecuteContext ctx);
|
||||
|
||||
/**
|
||||
* Called at the end of the execution lifecycle..
|
||||
* Called at the end of the execution lifecycle.
|
||||
* <p>
|
||||
* Available attributes from <code>ExecuteContext</code>:
|
||||
* <ul>
|
||||
@ -840,7 +851,7 @@ public interface ExecuteListener {
|
||||
* Note that the <code>Statement</code> is already closed!</li>
|
||||
* <li> {@link ExecuteContext#resultSet()}: The <code>ResultSet</code> that
|
||||
* was fetched or <code>null</code>, if no result set was fetched. Note that
|
||||
* if any <code>ResultSet</code> is already closed!</li>
|
||||
* the <code>ResultSet</code> may already be closed!</li>
|
||||
* <li> {@link ExecuteContext#record()}: The last <code>Record</code> that
|
||||
* was fetched or null if no records were fetched.</li>
|
||||
* <li> {@link ExecuteContext#result()}: The last set of records that were
|
||||
@ -848,4 +859,50 @@ public interface ExecuteListener {
|
||||
* </ul>
|
||||
*/
|
||||
void end(ExecuteContext ctx);
|
||||
|
||||
/**
|
||||
* Called in the event of an exception at any moment of the execution
|
||||
* lifecycle.
|
||||
* <p>
|
||||
* Available attributes from <code>ExecuteContext</code>:
|
||||
* <ul>
|
||||
* <li> {@link ExecuteContext#getConnection()}: The connection used for
|
||||
* execution</li>
|
||||
* <li> {@link ExecuteContext#configuration()}: The execution configuration</li>
|
||||
* <li> {@link ExecuteContext#query()}: The <code>Query</code> object, if a
|
||||
* jOOQ query is being executed or <code>null</code> otherwise</li>
|
||||
* <li> {@link ExecuteContext#routine()}: The <code>Routine</code> object, if
|
||||
* a jOOQ routine is being executed or <code>null</code> otherwise</li>
|
||||
* <li> {@link ExecuteContext#sql()}: The rendered <code>SQL</code> statement
|
||||
* that is about to be executed, or <code>null</code> if the
|
||||
* <code>SQL</code> statement is unknown..</li>
|
||||
* <li> {@link ExecuteContext#statement()}: The
|
||||
* <code>PreparedStatement</code> that is about to be executed, or
|
||||
* <code>null</code> if no statement is known to jOOQ. This can be any of
|
||||
* the following: <br/>
|
||||
* <br/>
|
||||
* <ul>
|
||||
* <li>A <code>java.sql.PreparedStatement</code> from your JDBC driver when
|
||||
* a jOOQ <code>Query</code> is being executed as
|
||||
* {@link StatementType#PREPARED_STATEMENT}</li>
|
||||
* <li>A <code>java.sql.Statement</code> from your JDBC driver wrapped in a
|
||||
* <code>java.sql.PreparedStatement</code> when your jOOQ <code>Query</code>
|
||||
* is being executed as {@link StatementType#STATIC_STATEMENT}</li>
|
||||
* <li>A <code>java.sql.CallableStatement</code> when you are executing a
|
||||
* jOOQ <code>Routine</code></li>
|
||||
* </ul>
|
||||
* Note that the <code>Statement</code> may be closed!</li>
|
||||
* <li> {@link ExecuteContext#resultSet()}: The <code>ResultSet</code> that
|
||||
* was fetched or <code>null</code>, if no result set was fetched. Note that
|
||||
* the <code>ResultSet</code> may already be closed!</li>
|
||||
* <li> {@link ExecuteContext#record()}: The last <code>Record</code> that
|
||||
* was fetched or null if no records were fetched.</li>
|
||||
* <li> {@link ExecuteContext#result()}: The last set of records that were
|
||||
* fetched or null if no records were fetched.</li>
|
||||
* <li> {@link ExecuteContext#exception()}: The {@link RuntimeException} that
|
||||
* is about to be thrown</li>
|
||||
* <li> {@link ExecuteContext#sqlException()}: The {@link SQLException} that
|
||||
* was thrown by the database</li> </ul>
|
||||
*/
|
||||
void exception(ExecuteContext ctx);
|
||||
}
|
||||
|
||||
@ -146,7 +146,7 @@ abstract class AbstractBindContext extends AbstractContext<BindContext> implemen
|
||||
return bindValue0(value, type);
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw Util.translate("DefaultBindContext.bindValue", null, e);
|
||||
throw Util.translate(null, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -147,7 +147,9 @@ abstract class AbstractQuery extends AbstractQueryPart implements Query {
|
||||
return result;
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw Util.translate("AbstractQuery.execute", ctx.sql(), e);
|
||||
ctx.sqlException(e);
|
||||
listener.exception(ctx);
|
||||
throw ctx.exception();
|
||||
}
|
||||
finally {
|
||||
if (!keepStatementOpen()) {
|
||||
|
||||
@ -281,8 +281,19 @@ abstract class AbstractQueryPart implements QueryPartInternal, AttachableInterna
|
||||
|
||||
/**
|
||||
* Internal convenience method
|
||||
*
|
||||
* @deprecated - 2.3.0 - Do not reuse
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@Deprecated
|
||||
protected final DataAccessException translate(String task, String sql, SQLException e) {
|
||||
return Util.translate(task, sql, e);
|
||||
return translate(sql, e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal convenience method
|
||||
*/
|
||||
protected final DataAccessException translate(String sql, SQLException e) {
|
||||
return Util.translate(sql, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,7 +329,9 @@ public abstract class AbstractRoutine<T> extends AbstractSchemaProviderQueryPart
|
||||
return 0;
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw translate("AbstractRoutine.executeCallableStatement", ctx.sql(), e);
|
||||
ctx.sqlException(e);
|
||||
listener.exception(ctx);
|
||||
throw ctx.exception();
|
||||
}
|
||||
finally {
|
||||
Util.safeClose(listener, ctx);
|
||||
|
||||
@ -93,7 +93,9 @@ class BatchMultiple implements Batch {
|
||||
return result;
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw Util.translate("BatchMultiple.execute", ctx.sql(), e);
|
||||
ctx.sqlException(e);
|
||||
listener.exception(ctx);
|
||||
throw ctx.exception();
|
||||
}
|
||||
finally {
|
||||
Util.safeClose(listener, ctx);
|
||||
|
||||
@ -131,7 +131,9 @@ class BatchSingle implements BatchBindStep {
|
||||
return result;
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw Util.translate("BatchSingle.execute", ctx.sql(), e);
|
||||
ctx.sqlException(e);
|
||||
listener.exception(ctx);
|
||||
throw ctx.exception();
|
||||
}
|
||||
finally {
|
||||
Util.safeClose(listener, ctx);
|
||||
|
||||
@ -1267,7 +1267,9 @@ class CursorImpl<R extends Record> implements Cursor<R> {
|
||||
}
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw Util.translate("Cursor.fetch", ctx.sql(), e);
|
||||
ctx.sqlException(e);
|
||||
listener.exception(ctx);
|
||||
throw ctx.exception();
|
||||
}
|
||||
|
||||
// Conveniently close cursors and underlying objects after the last
|
||||
|
||||
@ -39,6 +39,7 @@ import java.sql.Blob;
|
||||
import java.sql.Clob;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -68,7 +69,7 @@ class DefaultExecuteContext extends AbstractConfiguration implements ExecuteCont
|
||||
*/
|
||||
private static final long serialVersionUID = -6653474082935089963L;
|
||||
|
||||
// Persistent attributes
|
||||
// Persistent attributes (repeatable)
|
||||
private final Query query;
|
||||
private final Routine<?> routine;
|
||||
private String sql;
|
||||
@ -76,16 +77,18 @@ class DefaultExecuteContext extends AbstractConfiguration implements ExecuteCont
|
||||
private final Query[] batchQueries;
|
||||
private final String[] batchSQL;
|
||||
|
||||
// Transient attributes
|
||||
// Transient attributes (created afresh per execution)
|
||||
private transient PreparedStatement statement;
|
||||
private transient ResultSet resultSet;
|
||||
private transient Record record;
|
||||
private transient Result<?> result;
|
||||
private transient SQLException sqlException;
|
||||
private transient RuntimeException exception;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// XXX: Static utility methods for handling blob / clob lifecycle
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
||||
private static final ThreadLocal<List<Blob>> BLOBS = new ThreadLocal<List<Blob>>();
|
||||
private static final ThreadLocal<List<Clob>> CLOBS = new ThreadLocal<List<Clob>>();
|
||||
|
||||
@ -335,4 +338,25 @@ class DefaultExecuteContext extends AbstractConfiguration implements ExecuteCont
|
||||
public final Result<?> result() {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final RuntimeException exception() {
|
||||
return exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void exception(RuntimeException e) {
|
||||
this.exception = e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final SQLException sqlException() {
|
||||
return sqlException;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void sqlException(SQLException e) {
|
||||
this.sqlException = e;
|
||||
exception(Util.translate(sql(), e));
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,4 +96,7 @@ public class DefaultExecuteListener implements ExecuteListener {
|
||||
@Override
|
||||
public void end(ExecuteContext ctx) {}
|
||||
|
||||
@Override
|
||||
public void exception(ExecuteContext ctx) {}
|
||||
|
||||
}
|
||||
|
||||
@ -187,4 +187,11 @@ class ExecuteListeners implements ExecuteListener {
|
||||
listener.end(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void exception(ExecuteContext ctx) {
|
||||
for (ExecuteListener listener : listeners) {
|
||||
listener.exception(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1238,7 +1238,9 @@ public class Factory implements FactoryOperations {
|
||||
return new CursorImpl<Record>(ctx, listener, fields).fetch();
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw Util.translate("Factory.fetch", ctx.sql(), e);
|
||||
ctx.sqlException(e);
|
||||
listener.exception(ctx);
|
||||
throw ctx.exception();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -434,7 +434,7 @@ class LoaderImpl<R extends TableRecord<R>> implements
|
||||
// SQLExceptions originating from rollbacks or commits are always fatal
|
||||
// They are propagated, and not swallowed
|
||||
catch (SQLException e) {
|
||||
throw Util.translate("LoaderImpl.executeCSV", null, e);
|
||||
throw Util.translate(null, e);
|
||||
}
|
||||
finally {
|
||||
reader.close();
|
||||
|
||||
@ -119,7 +119,7 @@ class MetaDataFieldProvider implements FieldProvider, Serializable {
|
||||
}
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw Util.translate("MetaFieldProvider.init", null, e);
|
||||
throw Util.translate(null, e);
|
||||
}
|
||||
|
||||
meta = null;
|
||||
|
||||
@ -491,8 +491,8 @@ final class Util {
|
||||
/**
|
||||
* Translate a {@link SQLException} to a {@link DataAccessException}
|
||||
*/
|
||||
static final DataAccessException translate(String task, String sql, SQLException e) {
|
||||
String message = task + "; SQL [" + sql + "]; " + e.getMessage();
|
||||
static final DataAccessException translate(String sql, SQLException e) {
|
||||
String message = "SQL [" + sql + "]; " + e.getMessage();
|
||||
return new DataAccessException(message, e);
|
||||
}
|
||||
|
||||
|
||||
@ -127,4 +127,9 @@ public class StopWatchListener implements ExecuteListener {
|
||||
public void end(ExecuteContext ctx) {
|
||||
watch.splitDebug("Finishing");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exception(ExecuteContext ctx) {
|
||||
watch.splitDebug("Exception");
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user