public SQLExceptionSubclassTranslator() { setFallbackTranslator(new SQLStateSQLExceptionTranslator()); }
protected DataAccessException doTranslate(String task, @Nullable String sql, SQLException ex) { String sqlState = getSqlState(ex); if (sqlState != null && sqlState.length() >= 2) { String classCode = sqlState.substring(0, 2); return new DataIntegrityViolationException(buildMessage(task, sql, ex), ex); return new DataAccessResourceFailureException(buildMessage(task, sql, ex), ex); return new TransientDataAccessResourceException(buildMessage(task, sql, ex), ex); return new ConcurrencyFailureException(buildMessage(task, sql, ex), ex); return new QueryTimeoutException(buildMessage(task, sql, ex), ex);
@Test(expected = IllegalArgumentException.class) public void testTranslateNullException() throws Exception { new SQLStateSQLExceptionTranslator().translate("", "", null); }
private void testMalformedSqlStateCode(SQLException sex) { try { throw this.trans.translate("task", sql, sex); } catch (UncategorizedSQLException ex) { // OK assertTrue("SQL is correct", sql.equals(ex.getSql())); assertTrue("Exception matches", sex.equals(ex.getSQLException())); } }
@Test public void badSqlGrammar() { SQLException sex = new SQLException("Message", "42001", 1); try { throw this.trans.translate("task", sql, sex); } catch (BadSqlGrammarException ex) { // OK assertTrue("SQL is correct", sql.equals(ex.getSql())); assertTrue("Exception matches", sex.equals(ex.getSQLException())); } }
/** * Return the exception translator for this instance. * <p>Creates a default {@link SQLErrorCodeSQLExceptionTranslator} * for the specified DataSource if none set, or a * {@link SQLStateSQLExceptionTranslator} in case of no DataSource. * @see #getDataSource() */ public SQLExceptionTranslator getExceptionTranslator() { SQLExceptionTranslator exceptionTranslator = this.exceptionTranslator; if (exceptionTranslator != null) { return exceptionTranslator; } synchronized (this) { exceptionTranslator = this.exceptionTranslator; if (exceptionTranslator == null) { DataSource dataSource = getDataSource(); if (dataSource != null) { exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(dataSource); } else { exceptionTranslator = new SQLStateSQLExceptionTranslator(); } this.exceptionTranslator = exceptionTranslator; } return exceptionTranslator; } }
@Override protected DataAccessException doTranslate(String task, String sql, SQLException ex) { String sqlState = getSqlState(ex); if (sqlState != null && sqlState.length() >= 2) { String classCode = sqlState.substring(0, 2); if (logger.isDebugEnabled()) { logger.debug("Extracted SQL state class '" + classCode + "' from value '" + sqlState + "'"); } if (BAD_SQL_GRAMMAR_CODES.contains(classCode)) { return new BadSqlGrammarException(task, sql, ex); } else if (DATA_INTEGRITY_VIOLATION_CODES.contains(classCode)) { return new DataIntegrityViolationException(buildMessage(task, sql, ex), ex); } else if (DATA_ACCESS_RESOURCE_FAILURE_CODES.contains(classCode)) { return new DataAccessResourceFailureException(buildMessage(task, sql, ex), ex); } else if (TRANSIENT_DATA_ACCESS_RESOURCE_CODES.contains(classCode)) { return new TransientDataAccessResourceException(buildMessage(task, sql, ex), ex); } else if (CONCURRENCY_FAILURE_CODES.contains(classCode)) { return new ConcurrencyFailureException(buildMessage(task, sql, ex), ex); } } return null; }
@Test public void invalidSqlStateCode() { SQLException sex = new SQLException("Message", "NO SUCH CODE", 1); try { throw this.trans.translate("task", sql, sex); } catch (UncategorizedSQLException ex) { // OK assertTrue("SQL is correct", sql.equals(ex.getSql())); assertTrue("Exception matches", sex.equals(ex.getSQLException())); } }
/** * Creates a default SQLErrorCodeSQLExceptionTranslator for the specified * DataSource if none is set. * * @return the exception translator for this instance. */ protected SQLExceptionTranslator getExceptionTranslator() { synchronized(this) { if (exceptionTranslator == null) { if (dataSource != null) { exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(dataSource); } else { exceptionTranslator = new SQLStateSQLExceptionTranslator(); } } } return exceptionTranslator; }
protected DataAccessException doTranslate(String task, @Nullable String sql, SQLException ex) { String sqlState = getSqlState(ex); if (sqlState != null && sqlState.length() >= 2) { String classCode = sqlState.substring(0, 2); return new DataIntegrityViolationException(buildMessage(task, sql, ex), ex); return new DataAccessResourceFailureException(buildMessage(task, sql, ex), ex); return new TransientDataAccessResourceException(buildMessage(task, sql, ex), ex); return new ConcurrencyFailureException(buildMessage(task, sql, ex), ex); return new QueryTimeoutException(buildMessage(task, sql, ex), ex);
private static DataAccessException searchAndTranslateSqlException(final RuntimeException ex) { final SQLException sqlException = findSqlException(ex); if (sqlException == null) { return null; } return SQLSTATE_EXCEPTION_TRANSLATOR.translate(null, null, sqlException); }
private void doTest(String sqlState, Class<?> dataAccessExceptionType) { SQLException ex = new SQLException(REASON, sqlState); SQLExceptionTranslator translator = new SQLStateSQLExceptionTranslator(); DataAccessException dax = translator.translate(TASK, SQL, ex); assertNotNull("Translation must *never* result in a null DataAccessException being returned.", dax); assertEquals("Wrong DataAccessException type returned as the result of the translation", dataAccessExceptionType, dax.getClass()); assertNotNull("The original SQLException must be preserved in the translated DataAccessException", dax.getCause()); assertSame("The exact same original SQLException must be preserved in the translated DataAccessException", ex, dax.getCause()); }
private static DataAccessException searchAndTranslateSqlException(final RuntimeException ex) { final SQLException sqlException = findSqlException(ex); if (sqlException == null) { return null; } return SQLSTATE_EXCEPTION_TRANSLATOR.translate(null, null, sqlException); }
@Before public void setUp() throws SQLException { given(connection.createStatement()).willReturn(statement); given(connection.prepareStatement(anyString())).willReturn(preparedStatement); given(statement.executeQuery(anyString())).willReturn(resultSet); given(preparedStatement.executeQuery()).willReturn(resultSet); given(resultSet.next()).willReturn(true, true, false); given(resultSet.getString(1)).willReturn("tb1", "tb2"); given(resultSet.getInt(2)).willReturn(1, 2); template.setDataSource(new SingleConnectionDataSource(connection, false)); template.setExceptionTranslator(new SQLStateSQLExceptionTranslator()); template.afterPropertiesSet(); }
public Object invoke(MethodInvocation invocation) throws Throwable { if (!StringUtils.equalsIgnoreCase(invocation.getMethod().getName(), "getConnection")) { return invocation.proceed(); } try { return invocation.proceed(); // need to check with detecting sql? } catch (Throwable t) { if (t instanceof SQLException) { // we use SQLStateSQLExceptionTranslator to translate SQLExceptions , but it doesn't mean it will work as we expected, // so maybe more scope should be covered. we will check out later with runtime data statistics. DataAccessException dae = sqlExTranslator.translate( "translate to check whether it's a resource failure exception", null, (SQLException) t); if (dae instanceof DataAccessResourceFailureException) { logger.warn("failed to get Connection from data source with exception:\n{}", t); doSwap(); return invocation.getMethod().invoke(targetSource.getTarget(), invocation.getArguments()); } } // other exception conditions should be handled by application, // 'cause we don't have enough context information to decide what to do here. throw t; } }
/** * Test that we see an SQLException translated using Error Code. * If we provide the SQLExceptionTranslator, we shouldn't use a connection * to get the metadata */ @Test public void testUseCustomSQLErrorCodeTranslator() throws Exception { // Bad SQL state final SQLException sqlException = new SQLException("I have a known problem", "07000", 1054); final String sql = "SELECT ID FROM CUSTOMER"; given(this.resultSet.next()).willReturn(true); given(this.connection.createStatement()).willReturn(this.preparedStatement); JdbcTemplate template = new JdbcTemplate(); template.setDataSource(this.dataSource); // Set custom exception translator template.setExceptionTranslator(new SQLStateSQLExceptionTranslator()); template.afterPropertiesSet(); this.thrown.expect(BadSqlGrammarException.class); this.thrown.expect(exceptionCause(sameInstance(sqlException))); try { template.query(sql, (RowCallbackHandler) rs -> { throw sqlException; }); } finally { verify(this.resultSet).close(); verify(this.preparedStatement).close(); verify(this.connection).close(); } }
@SuppressWarnings("unchecked") public Mock(MockType type) throws Exception { connection = mock(Connection.class); statement = mock(Statement.class); resultSet = mock(ResultSet.class); resultSetMetaData = mock(ResultSetMetaData.class); given(connection.createStatement()).willReturn(statement); given(statement.executeQuery(anyString())).willReturn(resultSet); given(resultSet.getMetaData()).willReturn(resultSetMetaData); given(resultSet.next()).willReturn(true, false); given(resultSet.getString(1)).willReturn("Bubba"); given(resultSet.getLong(2)).willReturn(22L); given(resultSet.getTimestamp(3)).willReturn(new Timestamp(1221222L)); given(resultSet.getObject(anyInt(), any(Class.class))).willThrow(new SQLFeatureNotSupportedException()); given(resultSet.getDate(3)).willReturn(new java.sql.Date(1221222L)); given(resultSet.getBigDecimal(4)).willReturn(new BigDecimal("1234.56")); given(resultSet.wasNull()).willReturn(type == MockType.TWO); given(resultSetMetaData.getColumnCount()).willReturn(4); given(resultSetMetaData.getColumnLabel(1)).willReturn( type == MockType.THREE ? "Last Name" : "name"); given(resultSetMetaData.getColumnLabel(2)).willReturn("age"); given(resultSetMetaData.getColumnLabel(3)).willReturn("birth_date"); given(resultSetMetaData.getColumnLabel(4)).willReturn("balance"); jdbcTemplate = new JdbcTemplate(); jdbcTemplate.setDataSource(new SingleConnectionDataSource(connection, false)); jdbcTemplate.setExceptionTranslator(new SQLStateSQLExceptionTranslator()); jdbcTemplate.afterPropertiesSet(); }
t.setExceptionTranslator(new SQLStateSQLExceptionTranslator()); StoredProcedureConfiguredViaJdbcTemplate sp = new StoredProcedureConfiguredViaJdbcTemplate(t);
/** * Return the JDBC exception translator for this instance. * <p>Creates a default SQLStateSQLExceptionTranslator, * if no exception translator explicitly specified. */ public SQLExceptionTranslator getJdbcExceptionTranslator() { if (this.jdbcExceptionTranslator == null) { this.jdbcExceptionTranslator = new SQLStateSQLExceptionTranslator(); } return this.jdbcExceptionTranslator; }
/** * Create an appropriate SQLExceptionTranslator for the given TransactionManager. * If a DataSource is found, a SQLErrorCodeSQLExceptionTranslator for the DataSource * is created; else, a SQLStateSQLExceptionTranslator as fallback. * @param transactionManager the TransactionManager to create the translator for * @return the SQLExceptionTranslator * @see #getDataSource * @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator * @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator */ public static SQLExceptionTranslator newJdbcExceptionTranslator() { return new SQLStateSQLExceptionTranslator(); }