diff options
author | Emmanuel Bourg <ebourg@apache.org> | 2015-07-15 23:21:27 +0200 |
---|---|---|
committer | Emmanuel Bourg <ebourg@apache.org> | 2015-07-15 23:21:27 +0200 |
commit | da46d30e80e4c59a41cf52055d06faa1dbb7e383 (patch) | |
tree | 52b707fbbccd5b6100088913f32c1cbd00568790 /spring-jdbc | |
parent | c03c348db4e91c613982cbe6c99d0cf04ea14fe3 (diff) |
Imported Upstream version 4.0.9
Diffstat (limited to 'spring-jdbc')
164 files changed, 2990 insertions, 1132 deletions
diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/CannotGetJdbcConnectionException.java b/spring-jdbc/src/main/java/org/springframework/jdbc/CannotGetJdbcConnectionException.java index a50f9b83..96fb8d86 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/CannotGetJdbcConnectionException.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/CannotGetJdbcConnectionException.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,16 +37,4 @@ public class CannotGetJdbcConnectionException extends DataAccessResourceFailureE super(msg, ex); } - /** - * Constructor for CannotGetJdbcConnectionException. - * @param msg the detail message - * @param ex ClassNotFoundException root cause - * @deprecated since Spring 2.5, in favor of throwing an - * IllegalStateException in case of the driver not being found - */ - @Deprecated - public CannotGetJdbcConnectionException(String msg, ClassNotFoundException ex) { - super(msg, ex); - } - } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/config/JdbcNamespaceHandler.java b/spring-jdbc/src/main/java/org/springframework/jdbc/config/JdbcNamespaceHandler.java index 3674dfba..e5567d1c 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/config/JdbcNamespaceHandler.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/config/JdbcNamespaceHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport; */ public class JdbcNamespaceHandler extends NamespaceHandlerSupport { + @Override public void init() { registerBeanDefinitionParser("embedded-database", new EmbeddedDatabaseBeanDefinitionParser()); registerBeanDefinitionParser("initialize-database", new InitializeDatabaseBeanDefinitionParser()); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/config/SortedResourcesFactoryBean.java b/spring-jdbc/src/main/java/org/springframework/jdbc/config/SortedResourcesFactoryBean.java index 6569ba89..6f20b20a 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/config/SortedResourcesFactoryBean.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/config/SortedResourcesFactoryBean.java @@ -59,6 +59,7 @@ public class SortedResourcesFactoryBean extends AbstractFactoryBean<Resource[]> } + @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader); } @@ -76,6 +77,7 @@ public class SortedResourcesFactoryBean extends AbstractFactoryBean<Resource[]> List<Resource> resources = new ArrayList<Resource>( Arrays.asList(this.resourcePatternResolver.getResources(location))); Collections.sort(resources, new Comparator<Resource>() { + @Override public int compare(Resource r1, Resource r2) { try { return r1.getURL().toString().compareTo(r2.getURL().toString()); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/ArgumentPreparedStatementSetter.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/ArgumentPreparedStatementSetter.java index 24bc6870..75ca1930 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/ArgumentPreparedStatementSetter.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/ArgumentPreparedStatementSetter.java @@ -39,6 +39,7 @@ public class ArgumentPreparedStatementSetter implements PreparedStatementSetter, } + @Override public void setValues(PreparedStatement ps) throws SQLException { if (this.args != null) { for (int i = 0; i < this.args.length; i++) { @@ -66,6 +67,7 @@ public class ArgumentPreparedStatementSetter implements PreparedStatementSetter, } } + @Override public void cleanupParameters() { StatementCreatorUtils.cleanupParameters(this.args); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/ArgumentTypePreparedStatementSetter.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/ArgumentTypePreparedStatementSetter.java index ceb3d785..9db420e0 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/ArgumentTypePreparedStatementSetter.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/ArgumentTypePreparedStatementSetter.java @@ -52,13 +52,14 @@ public class ArgumentTypePreparedStatementSetter implements PreparedStatementSet } + @Override public void setValues(PreparedStatement ps) throws SQLException { int parameterPosition = 1; if (this.args != null) { for (int i = 0; i < this.args.length; i++) { Object arg = this.args[i]; if (arg instanceof Collection && this.argTypes[i] != Types.ARRAY) { - Collection entries = (Collection) arg; + Collection<?> entries = (Collection<?>) arg; for (Object entry : entries) { if (entry instanceof Object[]) { Object[] valueArray = ((Object[]) entry); @@ -96,6 +97,7 @@ public class ArgumentTypePreparedStatementSetter implements PreparedStatementSet StatementCreatorUtils.setParameterValue(ps, parameterPosition, argType, argValue); } + @Override public void cleanupParameters() { StatementCreatorUtils.cleanupParameters(this.args); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/BatchUpdateUtils.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/BatchUpdateUtils.java index 2785e6a1..c888b47e 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/BatchUpdateUtils.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/BatchUpdateUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,11 +33,13 @@ public abstract class BatchUpdateUtils { sql, new BatchPreparedStatementSetter() { + @Override public void setValues(PreparedStatement ps, int i) throws SQLException { Object[] values = batchValues.get(i); setStatementParameters(values, ps, columnTypes); } + @Override public int getBatchSize() { return batchValues.size(); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/BeanPropertyRowMapper.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/BeanPropertyRowMapper.java index 69b9ee71..c65ac159 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/BeanPropertyRowMapper.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/BeanPropertyRowMapper.java @@ -230,6 +230,7 @@ public class BeanPropertyRowMapper<T> implements RowMapper<T> { * <p>Utilizes public setters and result set metadata. * @see java.sql.ResultSetMetaData */ + @Override public T mapRow(ResultSet rs, int rowNumber) throws SQLException { Assert.state(this.mappedClass != null, "Mapped class was not specified"); T mappedObject = BeanUtils.instantiate(this.mappedClass); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/CallableStatementCreatorFactory.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/CallableStatementCreatorFactory.java index 279ab5a5..c4cdb8ab 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/CallableStatementCreatorFactory.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/CallableStatementCreatorFactory.java @@ -150,6 +150,7 @@ public class CallableStatementCreatorFactory { this.inParameters = inParams; } + @Override public CallableStatement createCallableStatement(Connection con) throws SQLException { // If we were given a ParameterMapper, we must let the mapper do its thing to create the Map. if (this.inParameterMapper != null) { @@ -218,10 +219,12 @@ public class CallableStatementCreatorFactory { return cs; } + @Override public String getSql() { return callString; } + @Override public void cleanupParameters() { if (this.inParameters != null) { StatementCreatorUtils.cleanupParameters(this.inParameters.values()); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/ColumnMapRowMapper.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/ColumnMapRowMapper.java index 103333fe..1a0ac827 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/ColumnMapRowMapper.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/ColumnMapRowMapper.java @@ -47,6 +47,7 @@ import org.springframework.util.LinkedCaseInsensitiveMap; */ public class ColumnMapRowMapper implements RowMapper<Map<String, Object>> { + @Override public Map<String, Object> mapRow(ResultSet rs, int rowNum) throws SQLException { ResultSetMetaData rsmd = rs.getMetaData(); int columnCount = rsmd.getColumnCount(); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java index b98adcdb..d1cfd94c 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java @@ -20,6 +20,7 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import java.sql.BatchUpdateException; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; @@ -49,6 +50,7 @@ import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor; import org.springframework.jdbc.support.rowset.SqlRowSet; import org.springframework.util.Assert; import org.springframework.util.LinkedCaseInsensitiveMap; +import org.springframework.util.StringUtils; /** * <b>This is the central class in the JDBC core package.</b> @@ -79,6 +81,8 @@ import org.springframework.util.LinkedCaseInsensitiveMap; * <p>All SQL operations performed by this class are logged at debug level, * using "org.springframework.jdbc.core.JdbcTemplate" as log category. * + * <p><b>NOTE: An instance of this class is thread-safe once configured.</b> + * * @author Rod Johnson * @author Juergen Hoeller * @author Thomas Risberg @@ -325,6 +329,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { // Methods dealing with a plain java.sql.Connection //------------------------------------------------------------------------- + @Override public <T> T execute(ConnectionCallback<T> action) throws DataAccessException { Assert.notNull(action, "Callback object must not be null"); @@ -376,6 +381,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { // Methods dealing with static SQL (java.sql.Statement) //------------------------------------------------------------------------- + @Override public <T> T execute(StatementCallback<T> action) throws DataAccessException { Assert.notNull(action, "Callback object must not be null"); @@ -412,15 +418,18 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { } } + @Override public void execute(final String sql) throws DataAccessException { if (logger.isDebugEnabled()) { logger.debug("Executing SQL statement [" + sql + "]"); } class ExecuteStatementCallback implements StatementCallback<Object>, SqlProvider { + @Override public Object doInStatement(Statement stmt) throws SQLException { stmt.execute(sql); return null; } + @Override public String getSql() { return sql; } @@ -428,6 +437,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { execute(new ExecuteStatementCallback()); } + @Override public <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException { Assert.notNull(sql, "SQL must not be null"); Assert.notNull(rse, "ResultSetExtractor must not be null"); @@ -435,6 +445,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { logger.debug("Executing SQL query [" + sql + "]"); } class QueryStatementCallback implements StatementCallback<T>, SqlProvider { + @Override public T doInStatement(Statement stmt) throws SQLException { ResultSet rs = null; try { @@ -449,6 +460,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { JdbcUtils.closeResultSet(rs); } } + @Override public String getSql() { return sql; } @@ -456,57 +468,69 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { return execute(new QueryStatementCallback()); } + @Override public void query(String sql, RowCallbackHandler rch) throws DataAccessException { query(sql, new RowCallbackHandlerResultSetExtractor(rch)); } + @Override public <T> List<T> query(String sql, RowMapper<T> rowMapper) throws DataAccessException { return query(sql, new RowMapperResultSetExtractor<T>(rowMapper)); } + @Override public Map<String, Object> queryForMap(String sql) throws DataAccessException { return queryForObject(sql, getColumnMapRowMapper()); } + @Override public <T> T queryForObject(String sql, RowMapper<T> rowMapper) throws DataAccessException { List<T> results = query(sql, rowMapper); return DataAccessUtils.requiredSingleResult(results); } + @Override public <T> T queryForObject(String sql, Class<T> requiredType) throws DataAccessException { return queryForObject(sql, getSingleColumnRowMapper(requiredType)); } + @Override @Deprecated public long queryForLong(String sql) throws DataAccessException { Number number = queryForObject(sql, Long.class); return (number != null ? number.longValue() : 0); } + @Override @Deprecated public int queryForInt(String sql) throws DataAccessException { Number number = queryForObject(sql, Integer.class); return (number != null ? number.intValue() : 0); } + @Override public <T> List<T> queryForList(String sql, Class<T> elementType) throws DataAccessException { return query(sql, getSingleColumnRowMapper(elementType)); } + @Override public List<Map<String, Object>> queryForList(String sql) throws DataAccessException { return query(sql, getColumnMapRowMapper()); } + @Override public SqlRowSet queryForRowSet(String sql) throws DataAccessException { return query(sql, new SqlRowSetResultSetExtractor()); } + @Override public int update(final String sql) throws DataAccessException { Assert.notNull(sql, "SQL must not be null"); if (logger.isDebugEnabled()) { logger.debug("Executing SQL update [" + sql + "]"); } class UpdateStatementCallback implements StatementCallback<Integer>, SqlProvider { + @Override public Integer doInStatement(Statement stmt) throws SQLException { int rows = stmt.executeUpdate(sql); if (logger.isDebugEnabled()) { @@ -514,6 +538,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { } return rows; } + @Override public String getSql() { return sql; } @@ -521,21 +546,44 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { return execute(new UpdateStatementCallback()); } + @Override public int[] batchUpdate(final String[] sql) throws DataAccessException { + Assert.notEmpty(sql, "SQL array must not be empty"); + if (logger.isDebugEnabled()) { logger.debug("Executing SQL batch update of " + sql.length + " statements"); } + class BatchUpdateStatementCallback implements StatementCallback<int[]>, SqlProvider { + private String currSql; + + @Override public int[] doInStatement(Statement stmt) throws SQLException, DataAccessException { + int[] rowsAffected = new int[sql.length]; + if (JdbcUtils.supportsBatchUpdates(stmt.getConnection())) { for (String sqlStmt : sql) { - this.currSql = sqlStmt; + this.currSql = appendSql(this.currSql, sqlStmt); stmt.addBatch(sqlStmt); } - rowsAffected = stmt.executeBatch(); + try { + rowsAffected = stmt.executeBatch(); + } + catch (BatchUpdateException ex) { + String batchExceptionSql = null; + for (int i = 0; i < ex.getUpdateCounts().length; i++) { + if (ex.getUpdateCounts()[i] == Statement.EXECUTE_FAILED) { + batchExceptionSql = appendSql(batchExceptionSql, sql[i]); + } + } + if (StringUtils.hasLength(batchExceptionSql)) { + this.currSql = batchExceptionSql; + } + throw ex; + } } else { for (int i = 0; i < sql.length; i++) { @@ -550,6 +598,12 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { } return rowsAffected; } + + private String appendSql(String sql, String statement) { + return (StringUtils.isEmpty(sql) ? statement : sql + "; " + statement); + } + + @Override public String getSql() { return this.currSql; } @@ -562,6 +616,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { // Methods dealing with prepared statements //------------------------------------------------------------------------- + @Override public <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action) throws DataAccessException { @@ -613,6 +668,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { } } + @Override public <T> T execute(String sql, PreparedStatementCallback<T> action) throws DataAccessException { return execute(new SimplePreparedStatementCreator(sql), action); } @@ -637,6 +693,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { logger.debug("Executing prepared SQL query"); return execute(psc, new PreparedStatementCallback<T>() { + @Override public T doInPreparedStatement(PreparedStatement ps) throws SQLException { ResultSet rs = null; try { @@ -660,66 +717,82 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { }); } + @Override public <T> T query(PreparedStatementCreator psc, ResultSetExtractor<T> rse) throws DataAccessException { return query(psc, null, rse); } + @Override public <T> T query(String sql, PreparedStatementSetter pss, ResultSetExtractor<T> rse) throws DataAccessException { return query(new SimplePreparedStatementCreator(sql), pss, rse); } + @Override public <T> T query(String sql, Object[] args, int[] argTypes, ResultSetExtractor<T> rse) throws DataAccessException { return query(sql, newArgTypePreparedStatementSetter(args, argTypes), rse); } + @Override public <T> T query(String sql, Object[] args, ResultSetExtractor<T> rse) throws DataAccessException { return query(sql, newArgPreparedStatementSetter(args), rse); } + @Override public <T> T query(String sql, ResultSetExtractor<T> rse, Object... args) throws DataAccessException { return query(sql, newArgPreparedStatementSetter(args), rse); } + @Override public void query(PreparedStatementCreator psc, RowCallbackHandler rch) throws DataAccessException { query(psc, new RowCallbackHandlerResultSetExtractor(rch)); } + @Override public void query(String sql, PreparedStatementSetter pss, RowCallbackHandler rch) throws DataAccessException { query(sql, pss, new RowCallbackHandlerResultSetExtractor(rch)); } + @Override public void query(String sql, Object[] args, int[] argTypes, RowCallbackHandler rch) throws DataAccessException { query(sql, newArgTypePreparedStatementSetter(args, argTypes), rch); } + @Override public void query(String sql, Object[] args, RowCallbackHandler rch) throws DataAccessException { query(sql, newArgPreparedStatementSetter(args), rch); } + @Override public void query(String sql, RowCallbackHandler rch, Object... args) throws DataAccessException { query(sql, newArgPreparedStatementSetter(args), rch); } + @Override public <T> List<T> query(PreparedStatementCreator psc, RowMapper<T> rowMapper) throws DataAccessException { return query(psc, new RowMapperResultSetExtractor<T>(rowMapper)); } + @Override public <T> List<T> query(String sql, PreparedStatementSetter pss, RowMapper<T> rowMapper) throws DataAccessException { return query(sql, pss, new RowMapperResultSetExtractor<T>(rowMapper)); } + @Override public <T> List<T> query(String sql, Object[] args, int[] argTypes, RowMapper<T> rowMapper) throws DataAccessException { return query(sql, args, argTypes, new RowMapperResultSetExtractor<T>(rowMapper)); } + @Override public <T> List<T> query(String sql, Object[] args, RowMapper<T> rowMapper) throws DataAccessException { return query(sql, args, new RowMapperResultSetExtractor<T>(rowMapper)); } + @Override public <T> List<T> query(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException { return query(sql, args, new RowMapperResultSetExtractor<T>(rowMapper)); } + @Override public <T> T queryForObject(String sql, Object[] args, int[] argTypes, RowMapper<T> rowMapper) throws DataAccessException { @@ -727,86 +800,104 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { return DataAccessUtils.requiredSingleResult(results); } + @Override public <T> T queryForObject(String sql, Object[] args, RowMapper<T> rowMapper) throws DataAccessException { List<T> results = query(sql, args, new RowMapperResultSetExtractor<T>(rowMapper, 1)); return DataAccessUtils.requiredSingleResult(results); } + @Override public <T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException { List<T> results = query(sql, args, new RowMapperResultSetExtractor<T>(rowMapper, 1)); return DataAccessUtils.requiredSingleResult(results); } + @Override public <T> T queryForObject(String sql, Object[] args, int[] argTypes, Class<T> requiredType) throws DataAccessException { return queryForObject(sql, args, argTypes, getSingleColumnRowMapper(requiredType)); } + @Override public <T> T queryForObject(String sql, Object[] args, Class<T> requiredType) throws DataAccessException { return queryForObject(sql, args, getSingleColumnRowMapper(requiredType)); } + @Override public <T> T queryForObject(String sql, Class<T> requiredType, Object... args) throws DataAccessException { return queryForObject(sql, args, getSingleColumnRowMapper(requiredType)); } + @Override public Map<String, Object> queryForMap(String sql, Object[] args, int[] argTypes) throws DataAccessException { return queryForObject(sql, args, argTypes, getColumnMapRowMapper()); } + @Override public Map<String, Object> queryForMap(String sql, Object... args) throws DataAccessException { return queryForObject(sql, args, getColumnMapRowMapper()); } + @Override @Deprecated public long queryForLong(String sql, Object[] args, int[] argTypes) throws DataAccessException { Number number = queryForObject(sql, args, argTypes, Long.class); return (number != null ? number.longValue() : 0); } + @Override @Deprecated public long queryForLong(String sql, Object... args) throws DataAccessException { Number number = queryForObject(sql, args, Long.class); return (number != null ? number.longValue() : 0); } + @Override @Deprecated public int queryForInt(String sql, Object[] args, int[] argTypes) throws DataAccessException { Number number = queryForObject(sql, args, argTypes, Integer.class); return (number != null ? number.intValue() : 0); } + @Override @Deprecated public int queryForInt(String sql, Object... args) throws DataAccessException { Number number = queryForObject(sql, args, Integer.class); return (number != null ? number.intValue() : 0); } + @Override public <T> List<T> queryForList(String sql, Object[] args, int[] argTypes, Class<T> elementType) throws DataAccessException { return query(sql, args, argTypes, getSingleColumnRowMapper(elementType)); } + @Override public <T> List<T> queryForList(String sql, Object[] args, Class<T> elementType) throws DataAccessException { return query(sql, args, getSingleColumnRowMapper(elementType)); } + @Override public <T> List<T> queryForList(String sql, Class<T> elementType, Object... args) throws DataAccessException { return query(sql, args, getSingleColumnRowMapper(elementType)); } + @Override public List<Map<String, Object>> queryForList(String sql, Object[] args, int[] argTypes) throws DataAccessException { return query(sql, args, argTypes, getColumnMapRowMapper()); } + @Override public List<Map<String, Object>> queryForList(String sql, Object... args) throws DataAccessException { return query(sql, args, getColumnMapRowMapper()); } + @Override public SqlRowSet queryForRowSet(String sql, Object[] args, int[] argTypes) throws DataAccessException { return query(sql, args, argTypes, new SqlRowSetResultSetExtractor()); } + @Override public SqlRowSet queryForRowSet(String sql, Object... args) throws DataAccessException { return query(sql, args, new SqlRowSetResultSetExtractor()); } @@ -816,6 +907,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { logger.debug("Executing prepared SQL update"); return execute(psc, new PreparedStatementCallback<Integer>() { + @Override public Integer doInPreparedStatement(PreparedStatement ps) throws SQLException { try { if (pss != null) { @@ -836,10 +928,12 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { }); } + @Override public int update(PreparedStatementCreator psc) throws DataAccessException { return update(psc, (PreparedStatementSetter) null); } + @Override public int update(final PreparedStatementCreator psc, final KeyHolder generatedKeyHolder) throws DataAccessException { @@ -847,6 +941,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { logger.debug("Executing SQL update and returning generated keys"); return execute(psc, new PreparedStatementCallback<Integer>() { + @Override public Integer doInPreparedStatement(PreparedStatement ps) throws SQLException { int rows = ps.executeUpdate(); List<Map<String, Object>> generatedKeys = generatedKeyHolder.getKeyList(); @@ -870,24 +965,29 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { }); } + @Override public int update(String sql, PreparedStatementSetter pss) throws DataAccessException { return update(new SimplePreparedStatementCreator(sql), pss); } + @Override public int update(String sql, Object[] args, int[] argTypes) throws DataAccessException { return update(sql, newArgTypePreparedStatementSetter(args, argTypes)); } + @Override public int update(String sql, Object... args) throws DataAccessException { return update(sql, newArgPreparedStatementSetter(args)); } + @Override public int[] batchUpdate(String sql, final BatchPreparedStatementSetter pss) throws DataAccessException { if (logger.isDebugEnabled()) { logger.debug("Executing SQL batch update [" + sql + "]"); } return execute(sql, new PreparedStatementCallback<int[]>() { + @Override public int[] doInPreparedStatement(PreparedStatement ps) throws SQLException { try { int batchSize = pss.getBatchSize(); @@ -929,14 +1029,17 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { }); } + @Override public int[] batchUpdate(String sql, List<Object[]> batchArgs) throws DataAccessException { return batchUpdate(sql, batchArgs, new int[0]); } + @Override public int[] batchUpdate(String sql, List<Object[]> batchArgs, int[] argTypes) throws DataAccessException { return BatchUpdateUtils.executeBatchUpdate(sql, batchArgs, argTypes, this); } + @Override public <T> int[][] batchUpdate(String sql, final Collection<T> batchArgs, final int batchSize, final ParameterizedPreparedStatementSetter<T> pss) throws DataAccessException { @@ -944,6 +1047,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { logger.debug("Executing SQL batch update [" + sql + "] with a batch size of " + batchSize); } return execute(sql, new PreparedStatementCallback<int[][]>() { + @Override public int[][] doInPreparedStatement(PreparedStatement ps) throws SQLException { List<int[]> rowsAffected = new ArrayList<int[]>(); try { @@ -990,6 +1094,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { // Methods dealing with callable statements //------------------------------------------------------------------------- + @Override public <T> T execute(CallableStatementCreator csc, CallableStatementCallback<T> action) throws DataAccessException { @@ -1040,10 +1145,12 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { } } + @Override public <T> T execute(String callString, CallableStatementCallback<T> action) throws DataAccessException { return execute(new SimpleCallableStatementCreator(callString), action); } + @Override public Map<String, Object> call(CallableStatementCreator csc, List<SqlParameter> declaredParameters) throws DataAccessException { @@ -1064,6 +1171,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { } } return execute(csc, new CallableStatementCallback<Map<String, Object>>() { + @Override public Map<String, Object> doInCallableStatement(CallableStatement cs) throws SQLException { boolean retVal = cs.execute(); int updateCount = cs.getUpdateCount(); @@ -1378,6 +1486,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { this.target = target; } + @Override @SuppressWarnings("rawtypes") public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // Invocation on ConnectionProxy interface coming in... @@ -1443,10 +1552,12 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { this.sql = sql; } + @Override public PreparedStatement createPreparedStatement(Connection con) throws SQLException { return con.prepareStatement(this.sql); } + @Override public String getSql() { return this.sql; } @@ -1465,10 +1576,12 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { this.callString = callString; } + @Override public CallableStatement createCallableStatement(Connection con) throws SQLException { return con.prepareCall(this.callString); } + @Override public String getSql() { return this.callString; } @@ -1488,6 +1601,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { this.rch = rch; } + @Override public Object extractData(ResultSet rs) throws SQLException { while (rs.next()) { this.rch.processRow(rs); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/PreparedStatementCreatorFactory.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/PreparedStatementCreatorFactory.java index daa9e5c7..1625c4c1 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/PreparedStatementCreatorFactory.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/PreparedStatementCreatorFactory.java @@ -224,6 +224,7 @@ public class PreparedStatementCreatorFactory { } } + @Override public PreparedStatement createPreparedStatement(Connection con) throws SQLException { PreparedStatement ps; if (generatedKeysColumnNames != null || returnGeneratedKeys) { @@ -252,6 +253,7 @@ public class PreparedStatementCreatorFactory { return ps; } + @Override public void setValues(PreparedStatement ps) throws SQLException { // Determine PreparedStatement to pass to custom types. PreparedStatement psToUse = ps; @@ -300,10 +302,12 @@ public class PreparedStatementCreatorFactory { } } + @Override public String getSql() { return sql; } + @Override public void cleanupParameters() { StatementCreatorUtils.cleanupParameters(this.parameters); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/ResultSetSupportingSqlParameter.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/ResultSetSupportingSqlParameter.java index 7c171637..ca515b5b 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/ResultSetSupportingSqlParameter.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/ResultSetSupportingSqlParameter.java @@ -25,11 +25,11 @@ package org.springframework.jdbc.core; */ public class ResultSetSupportingSqlParameter extends SqlParameter { - private ResultSetExtractor resultSetExtractor; + private ResultSetExtractor<?> resultSetExtractor; private RowCallbackHandler rowCallbackHandler; - private RowMapper rowMapper; + private RowMapper<?> rowMapper; /** @@ -68,7 +68,7 @@ public class ResultSetSupportingSqlParameter extends SqlParameter { * @param sqlType SQL type of the parameter according to java.sql.Types * @param rse ResultSetExtractor to use for parsing the ResultSet */ - public ResultSetSupportingSqlParameter(String name, int sqlType, ResultSetExtractor rse) { + public ResultSetSupportingSqlParameter(String name, int sqlType, ResultSetExtractor<?> rse) { super(name, sqlType); this.resultSetExtractor = rse; } @@ -90,7 +90,7 @@ public class ResultSetSupportingSqlParameter extends SqlParameter { * @param sqlType SQL type of the parameter according to java.sql.Types * @param rm RowMapper to use for parsing the ResultSet */ - public ResultSetSupportingSqlParameter(String name, int sqlType, RowMapper rm) { + public ResultSetSupportingSqlParameter(String name, int sqlType, RowMapper<?> rm) { super(name, sqlType); this.rowMapper = rm; } @@ -107,7 +107,7 @@ public class ResultSetSupportingSqlParameter extends SqlParameter { /** * Return the ResultSetExtractor held by this parameter, if any. */ - public ResultSetExtractor getResultSetExtractor() { + public ResultSetExtractor<?> getResultSetExtractor() { return this.resultSetExtractor; } @@ -121,7 +121,7 @@ public class ResultSetSupportingSqlParameter extends SqlParameter { /** * Return the RowMapper held by this parameter, if any. */ - public RowMapper getRowMapper() { + public RowMapper<?> getRowMapper() { return this.rowMapper; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/RowCountCallbackHandler.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/RowCountCallbackHandler.java index 7aeb9ee3..376810bf 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/RowCountCallbackHandler.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/RowCountCallbackHandler.java @@ -69,6 +69,7 @@ public class RowCountCallbackHandler implements RowCallbackHandler { * by overriding the {@code processRow(ResultSet, int)} method. * @see #processRow(java.sql.ResultSet, int) */ + @Override public final void processRow(ResultSet rs) throws SQLException { if (this.rowCount == 0) { ResultSetMetaData rsmd = rs.getMetaData(); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/RowMapperResultSetExtractor.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/RowMapperResultSetExtractor.java index 8ce94536..98043f57 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/RowMapperResultSetExtractor.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/RowMapperResultSetExtractor.java @@ -85,6 +85,7 @@ public class RowMapperResultSetExtractor<T> implements ResultSetExtractor<List<T } + @Override public List<T> extractData(ResultSet rs) throws SQLException { List<T> results = (this.rowsExpected > 0 ? new ArrayList<T>(this.rowsExpected) : new ArrayList<T>()); int rowNum = 0; diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/SingleColumnRowMapper.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/SingleColumnRowMapper.java index 9583ec75..17493853 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/SingleColumnRowMapper.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/SingleColumnRowMapper.java @@ -78,6 +78,7 @@ public class SingleColumnRowMapper<T> implements RowMapper<T> { * @see #getColumnValue(java.sql.ResultSet, int, Class) * @see #convertValueToRequiredType(Object, Class) */ + @Override @SuppressWarnings("unchecked") public T mapRow(ResultSet rs, int rowNum) throws SQLException { // Validate column count. @@ -120,7 +121,7 @@ public class SingleColumnRowMapper<T> implements RowMapper<T> { * @see org.springframework.jdbc.support.JdbcUtils#getResultSetValue(java.sql.ResultSet, int, Class) * @see #getColumnValue(java.sql.ResultSet, int) */ - protected Object getColumnValue(ResultSet rs, int index, Class requiredType) throws SQLException { + protected Object getColumnValue(ResultSet rs, int index, Class<?> requiredType) throws SQLException { if (requiredType != null) { return JdbcUtils.getResultSetValue(rs, index, requiredType); } @@ -163,18 +164,18 @@ public class SingleColumnRowMapper<T> implements RowMapper<T> { * @see #getColumnValue(java.sql.ResultSet, int, Class) */ @SuppressWarnings("unchecked") - protected Object convertValueToRequiredType(Object value, Class requiredType) { + protected Object convertValueToRequiredType(Object value, Class<?> requiredType) { if (String.class.equals(requiredType)) { return value.toString(); } else if (Number.class.isAssignableFrom(requiredType)) { if (value instanceof Number) { // Convert original Number to target Number class. - return NumberUtils.convertNumberToTargetClass(((Number) value), requiredType); + return NumberUtils.convertNumberToTargetClass(((Number) value), (Class<Number>) requiredType); } else { // Convert stringified value to target Number class. - return NumberUtils.parseNumber(value.toString(), requiredType); + return NumberUtils.parseNumber(value.toString(),(Class<Number>) requiredType); } } else { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlInOutParameter.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlInOutParameter.java index 9bdb7f0a..1c25a16b 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlInOutParameter.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlInOutParameter.java @@ -77,7 +77,7 @@ public class SqlInOutParameter extends SqlOutParameter { * @param sqlType SQL type of the parameter according to java.sql.Types * @param rse ResultSetExtractor to use for parsing the ResultSet */ - public SqlInOutParameter(String name, int sqlType, ResultSetExtractor rse) { + public SqlInOutParameter(String name, int sqlType, ResultSetExtractor<?> rse) { super(name, sqlType, rse); } @@ -97,7 +97,7 @@ public class SqlInOutParameter extends SqlOutParameter { * @param sqlType SQL type of the parameter according to java.sql.Types * @param rm RowMapper to use for parsing the ResultSet */ - public SqlInOutParameter(String name, int sqlType, RowMapper rm) { + public SqlInOutParameter(String name, int sqlType, RowMapper<?> rm) { super(name, sqlType, rm); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlOutParameter.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlOutParameter.java index 9454e2bd..0baba25d 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlOutParameter.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlOutParameter.java @@ -83,7 +83,7 @@ public class SqlOutParameter extends ResultSetSupportingSqlParameter { * @param sqlType SQL type of the parameter according to java.sql.Types * @param rse ResultSetExtractor to use for parsing the ResultSet */ - public SqlOutParameter(String name, int sqlType, ResultSetExtractor rse) { + public SqlOutParameter(String name, int sqlType, ResultSetExtractor<?> rse) { super(name, sqlType, rse); } @@ -103,7 +103,7 @@ public class SqlOutParameter extends ResultSetSupportingSqlParameter { * @param sqlType SQL type of the parameter according to java.sql.Types * @param rm RowMapper to use for parsing the ResultSet */ - public SqlOutParameter(String name, int sqlType, RowMapper rm) { + public SqlOutParameter(String name, int sqlType, RowMapper<?> rm) { super(name, sqlType, rm); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlReturnResultSet.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlReturnResultSet.java index 1120d8f8..02e956c2 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlReturnResultSet.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlReturnResultSet.java @@ -35,7 +35,7 @@ public class SqlReturnResultSet extends ResultSetSupportingSqlParameter { * @param name name of the parameter, as used in input and output maps * @param extractor ResultSetExtractor to use for parsing the {@link java.sql.ResultSet} */ - public SqlReturnResultSet(String name, ResultSetExtractor extractor) { + public SqlReturnResultSet(String name, ResultSetExtractor<?> extractor) { super(name, 0, extractor); } @@ -53,7 +53,7 @@ public class SqlReturnResultSet extends ResultSetSupportingSqlParameter { * @param name name of the parameter, as used in input and output maps * @param mapper RowMapper to use for parsing the {@link java.sql.ResultSet} */ - public SqlReturnResultSet(String name, RowMapper mapper) { + public SqlReturnResultSet(String name, RowMapper<?> mapper) { super(name, 0, mapper); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlRowSetResultSetExtractor.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlRowSetResultSetExtractor.java index 38efce95..7a69f2c4 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlRowSetResultSetExtractor.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/SqlRowSetResultSetExtractor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import javax.sql.rowset.RowSetProvider; import org.springframework.core.JdkVersion; import org.springframework.jdbc.support.rowset.ResultSetWrappingSqlRowSet; import org.springframework.jdbc.support.rowset.SqlRowSet; +import org.springframework.util.ClassUtils; /** * {@link ResultSetExtractor} implementation that returns a Spring {@link SqlRowSet} @@ -58,6 +59,7 @@ public class SqlRowSetResultSetExtractor implements ResultSetExtractor<SqlRowSet } + @Override public SqlRowSet extractData(ResultSet rs) throws SQLException { return createSqlRowSet(rs); } @@ -120,6 +122,7 @@ public class SqlRowSetResultSetExtractor implements ResultSetExtractor<SqlRowSet } } + @Override public CachedRowSet createCachedRowSet() throws SQLException { return this.rowSetFactory.createCachedRowSet(); } @@ -131,8 +134,26 @@ public class SqlRowSetResultSetExtractor implements ResultSetExtractor<SqlRowSet */ private static class SunCachedRowSetFactory implements CachedRowSetFactory { + private static final Class<?> implementationClass; + + static { + try { + implementationClass = ClassUtils.forName("com.sun.rowset.CachedRowSetImpl", + SqlRowSetResultSetExtractor.class.getClassLoader()); + } + catch (Throwable ex) { + throw new IllegalStateException(ex); + } + } + + @Override public CachedRowSet createCachedRowSet() throws SQLException { - return new com.sun.rowset.CachedRowSetImpl(); + try { + return (CachedRowSet) implementationClass.newInstance(); + } + catch (Throwable ex) { + throw new IllegalStateException(ex); + } } } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/StatementCreatorUtils.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/StatementCreatorUtils.java index b805724d..1c3ada01 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/StatementCreatorUtils.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/StatementCreatorUtils.java @@ -28,8 +28,10 @@ import java.sql.Types; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.logging.Log; @@ -77,9 +79,8 @@ public abstract class StatementCreatorUtils { static final boolean shouldIgnoreGetParameterType = SpringProperties.getFlag(IGNORE_GETPARAMETERTYPE_PROPERTY_NAME); - // Using a ConcurrentHashMap as a Set (for Java 5 compatibility) - static final Map<String, Boolean> driversWithNoSupportForGetParameterType = - new ConcurrentHashMap<String, Boolean>(1); + static final Set<String> driversWithNoSupportForGetParameterType = + Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(1)); private static final Log logger = LogFactory.getLog(StatementCreatorUtils.class); @@ -250,7 +251,7 @@ public abstract class StatementCreatorUtils { try { dbmd = ps.getConnection().getMetaData(); jdbcDriverName = dbmd.getDriverName(); - checkGetParameterType = !driversWithNoSupportForGetParameterType.containsKey(jdbcDriverName); + checkGetParameterType = !driversWithNoSupportForGetParameterType.contains(jdbcDriverName); } catch (Throwable ex) { logger.debug("Could not check connection metadata", ex); @@ -277,7 +278,7 @@ public abstract class StatementCreatorUtils { jdbcDriverName = dbmd.getDriverName(); } if (checkGetParameterType) { - driversWithNoSupportForGetParameterType.put(jdbcDriverName, Boolean.TRUE); + driversWithNoSupportForGetParameterType.add(jdbcDriverName); } String databaseProductName = dbmd.getDatabaseProductName(); if (databaseProductName.startsWith("Informix") || diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataProvider.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataProvider.java index 7640c9d2..e8ca5fc5 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataProvider.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataProvider.java @@ -42,7 +42,7 @@ public interface CallMetaDataProvider { /** * Initialize the database specific management of procedure column meta data. - * This is only called for databases that are supported. This initalization + * This is only called for databases that are supported. This initialization * can be turned off by specifying that column meta data should not be used. * @param databaseMetaData used to retrieve database specific information * @param catalogName name of catalog to use or null diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataProviderFactory.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataProviderFactory.java index 33087c44..62d56910 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataProviderFactory.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataProviderFactory.java @@ -61,14 +61,15 @@ public class CallMetaDataProviderFactory { ); /** - * Create a CallMetaDataProvider based on the database metedata - * @param dataSource used to retrieve metedata - * @param context the class that holds configuration and metedata + * Create a CallMetaDataProvider based on the database metadata + * @param dataSource used to retrieve metadata + * @param context the class that holds configuration and metadata * @return instance of the CallMetaDataProvider implementation to be used */ static public CallMetaDataProvider createMetaDataProvider(DataSource dataSource, final CallMetaDataContext context) { try { return (CallMetaDataProvider) JdbcUtils.extractDatabaseMetaData(dataSource, new DatabaseMetaDataCallback() { + @Override public Object processMetaData(DatabaseMetaData databaseMetaData) throws SQLException, MetaDataAccessException { String databaseProductName = JdbcUtils.commonDatabaseName(databaseMetaData.getDatabaseProductName()); boolean accessProcedureColumnMetaData = context.isAccessCallParameterMetaData(); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/GenericCallMetaDataProvider.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/GenericCallMetaDataProvider.java index 22e19d6e..2f4821a7 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/GenericCallMetaDataProvider.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/GenericCallMetaDataProvider.java @@ -68,6 +68,7 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider { } + @Override public void initializeWithMetaData(DatabaseMetaData databaseMetaData) throws SQLException { try { setSupportsCatalogsInProcedureCalls(databaseMetaData.supportsCatalogsInProcedureCalls()); @@ -103,6 +104,7 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider { } } + @Override public void initializeWithProcedureColumnMetaData(DatabaseMetaData databaseMetaData, String catalogName, String schemaName, String procedureName) throws SQLException { @@ -110,10 +112,12 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider { processProcedureColumns(databaseMetaData, catalogName, schemaName, procedureName); } + @Override public List<CallParameterMetaData> getCallParameterMetaData() { return this.callParameterMetaData; } + @Override public String procedureNameToUse(String procedureName) { if (procedureName == null) { return null; @@ -129,6 +133,7 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider { } } + @Override public String catalogNameToUse(String catalogName) { if (catalogName == null) { return null; @@ -144,6 +149,7 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider { } } + @Override public String schemaNameToUse(String schemaName) { if (schemaName == null) { return null; @@ -159,6 +165,7 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider { } } + @Override public String metaDataCatalogNameToUse(String catalogName) { if (isSupportsCatalogsInProcedureCalls()) { return catalogNameToUse(catalogName); @@ -168,6 +175,7 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider { } } + @Override public String metaDataSchemaNameToUse(String schemaName) { if (isSupportsSchemasInProcedureCalls()) { return schemaNameToUse(schemaName); @@ -177,6 +185,7 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider { } } + @Override public String parameterNameToUse(String parameterName) { if (parameterName == null) { return null; @@ -192,38 +201,47 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider { } } + @Override public boolean byPassReturnParameter(String parameterName) { return false; } + @Override public SqlParameter createDefaultOutParameter(String parameterName, CallParameterMetaData meta) { return new SqlOutParameter(parameterName, meta.getSqlType()); } + @Override public SqlParameter createDefaultInOutParameter(String parameterName, CallParameterMetaData meta) { return new SqlInOutParameter(parameterName, meta.getSqlType()); } + @Override public SqlParameter createDefaultInParameter(String parameterName, CallParameterMetaData meta) { return new SqlParameter(parameterName, meta.getSqlType()); } + @Override public String getUserName() { return this.userName; } + @Override public boolean isReturnResultSetSupported() { return true; } + @Override public boolean isRefCursorSupported() { return false; } + @Override public int getRefCursorSqlType() { return Types.OTHER; } + @Override public boolean isProcedureColumnMetaDataUsed() { return this.procedureColumnMetaDataUsed; } @@ -239,6 +257,7 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider { /** * Does the database support the use of catalog name in procedure calls */ + @Override public boolean isSupportsCatalogsInProcedureCalls() { return this.supportsCatalogsInProcedureCalls; } @@ -253,6 +272,7 @@ public class GenericCallMetaDataProvider implements CallMetaDataProvider { /** * Does the database support the use of schema name in procedure calls */ + @Override public boolean isSupportsSchemasInProcedureCalls() { return this.supportsSchemasInProcedureCalls; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/GenericTableMetaDataProvider.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/GenericTableMetaDataProvider.java index fcf2c6fe..24e66c42 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/GenericTableMetaDataProvider.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/GenericTableMetaDataProvider.java @@ -102,22 +102,27 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider { } + @Override public boolean isTableColumnMetaDataUsed() { return this.tableColumnMetaDataUsed; } + @Override public List<TableParameterMetaData> getTableParameterMetaData() { return this.insertParameterMetaData; } + @Override public boolean isGetGeneratedKeysSupported() { return this.getGeneratedKeysSupported; } + @Override public boolean isGetGeneratedKeysSimulated(){ return false; } + @Override public String getSimpleQueryForGetGeneratedKey(String tableName, String keyColumnName) { return null; } @@ -130,10 +135,12 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider { this.generatedKeysColumnNameArraySupported = generatedKeysColumnNameArraySupported; } + @Override public boolean isGeneratedKeysColumnNameArraySupported() { return this.generatedKeysColumnNameArraySupported; } + @Override public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) { this.nativeJdbcExtractor = nativeJdbcExtractor; } @@ -143,6 +150,7 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider { } + @Override public void initializeWithMetaData(DatabaseMetaData databaseMetaData) throws SQLException { try { if (databaseMetaData.supportsGetGeneratedKeys()) { @@ -197,6 +205,7 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider { } + @Override public void initializeWithTableColumnMetaData(DatabaseMetaData databaseMetaData, String catalogName, String schemaName, String tableName) throws SQLException { @@ -204,6 +213,7 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider { locateTableAndProcessMetaData(databaseMetaData, catalogName, schemaName, tableName); } + @Override public String tableNameToUse(String tableName) { if (tableName == null) { return null; @@ -219,6 +229,7 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider { } } + @Override public String catalogNameToUse(String catalogName) { if (catalogName == null) { return null; @@ -234,6 +245,7 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider { } } + @Override public String schemaNameToUse(String schemaName) { if (schemaName == null) { return null; @@ -249,10 +261,12 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider { } } + @Override public String metaDataCatalogNameToUse(String catalogName) { return catalogNameToUse(catalogName); } + @Override public String metaDataSchemaNameToUse(String schemaName) { if (schemaName == null) { return schemaNameToUse(getDefaultSchema()); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataProviderFactory.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataProviderFactory.java index 15421a99..36bc50ed 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataProviderFactory.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataProviderFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -62,6 +62,7 @@ public class TableMetaDataProviderFactory { try { return (TableMetaDataProvider) JdbcUtils.extractDatabaseMetaData(dataSource, new DatabaseMetaDataCallback() { + @Override public Object processMetaData(DatabaseMetaData databaseMetaData) throws SQLException { String databaseProductName = JdbcUtils.commonDatabaseName(databaseMetaData.getDatabaseProductName()); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/AbstractSqlParameterSource.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/AbstractSqlParameterSource.java index f8ff89e4..79526492 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/AbstractSqlParameterSource.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/AbstractSqlParameterSource.java @@ -61,6 +61,7 @@ public abstract class AbstractSqlParameterSource implements SqlParameterSource { * @return the SQL type of the parameter, * or {@code TYPE_UNKNOWN} if not registered */ + @Override public int getSqlType(String paramName) { Assert.notNull(paramName, "Parameter name must not be null"); Integer sqlType = this.sqlTypes.get(paramName); @@ -76,6 +77,7 @@ public abstract class AbstractSqlParameterSource implements SqlParameterSource { * @return the type name of the parameter, * or {@code null} if not registered */ + @Override public String getTypeName(String paramName) { Assert.notNull(paramName, "Parameter name must not be null"); return this.typeNames.get(paramName); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/BeanPropertySqlParameterSource.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/BeanPropertySqlParameterSource.java index 76062a8c..1726eabf 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/BeanPropertySqlParameterSource.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/BeanPropertySqlParameterSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -55,10 +55,12 @@ public class BeanPropertySqlParameterSource extends AbstractSqlParameterSource { } + @Override public boolean hasValue(String paramName) { return this.beanWrapper.isReadableProperty(paramName); } + @Override public Object getValue(String paramName) throws IllegalArgumentException { try { return this.beanWrapper.getPropertyValue(paramName); @@ -97,7 +99,7 @@ public class BeanPropertySqlParameterSource extends AbstractSqlParameterSource { if (sqlType != TYPE_UNKNOWN) { return sqlType; } - Class propType = this.beanWrapper.getPropertyType(paramName); + Class<?> propType = this.beanWrapper.getPropertyType(paramName); return StatementCreatorUtils.javaTypeToSqlParameterType(propType); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/EmptySqlParameterSource.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/EmptySqlParameterSource.java index a0b525f0..e90d4085 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/EmptySqlParameterSource.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/EmptySqlParameterSource.java @@ -30,18 +30,22 @@ public class EmptySqlParameterSource implements SqlParameterSource { public static final EmptySqlParameterSource INSTANCE = new EmptySqlParameterSource(); + @Override public boolean hasValue(String paramName) { return false; } + @Override public Object getValue(String paramName) throws IllegalArgumentException { throw new IllegalArgumentException("This SqlParameterSource is empty"); } + @Override public int getSqlType(String paramName) { return TYPE_UNKNOWN; } + @Override public String getTypeName(String paramName) { return null; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/MapSqlParameterSource.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/MapSqlParameterSource.java index fc7b32f4..1212c42c 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/MapSqlParameterSource.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/MapSqlParameterSource.java @@ -149,10 +149,12 @@ public class MapSqlParameterSource extends AbstractSqlParameterSource { } + @Override public boolean hasValue(String paramName) { return this.values.containsKey(paramName); } + @Override public Object getValue(String paramName) { if (!hasValue(paramName)) { throw new IllegalArgumentException("No value registered for key '" + paramName + "'"); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterBatchUpdateUtils.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterBatchUpdateUtils.java index 8f43da6b..fd711b43 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterBatchUpdateUtils.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterBatchUpdateUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,12 +41,14 @@ public class NamedParameterBatchUpdateUtils extends BatchUpdateUtils { sqlToUse, new BatchPreparedStatementSetter() { + @Override public void setValues(PreparedStatement ps, int i) throws SQLException { Object[] values = NamedParameterUtils.buildValueArray(parsedSql, batchArgs[i], null); int[] columnTypes = NamedParameterUtils.buildSqlTypeArray(parsedSql, batchArgs[i]); setStatementParameters(values, ps, columnTypes); } + @Override public int getBatchSize() { return batchArgs.length; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java index f1aea7da..0baf5cab 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java @@ -107,6 +107,7 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations * Expose the classic Spring JdbcTemplate to allow invocation of * less commonly used methods. */ + @Override public JdbcOperations getJdbcOperations() { return this.classicJdbcTemplate; } @@ -127,70 +128,83 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations } + @Override public <T> T execute(String sql, SqlParameterSource paramSource, PreparedStatementCallback<T> action) throws DataAccessException { return getJdbcOperations().execute(getPreparedStatementCreator(sql, paramSource), action); } + @Override public <T> T execute(String sql, Map<String, ?> paramMap, PreparedStatementCallback<T> action) throws DataAccessException { return execute(sql, new MapSqlParameterSource(paramMap), action); } + @Override public <T> T execute(String sql, PreparedStatementCallback<T> action) throws DataAccessException { return execute(sql, EmptySqlParameterSource.INSTANCE, action); } + @Override public <T> T query(String sql, SqlParameterSource paramSource, ResultSetExtractor<T> rse) throws DataAccessException { return getJdbcOperations().query(getPreparedStatementCreator(sql, paramSource), rse); } + @Override public <T> T query(String sql, Map<String, ?> paramMap, ResultSetExtractor<T> rse) throws DataAccessException { return query(sql, new MapSqlParameterSource(paramMap), rse); } + @Override public <T> T query(String sql, ResultSetExtractor<T> rse) throws DataAccessException { return query(sql, EmptySqlParameterSource.INSTANCE, rse); } + @Override public void query(String sql, SqlParameterSource paramSource, RowCallbackHandler rch) throws DataAccessException { getJdbcOperations().query(getPreparedStatementCreator(sql, paramSource), rch); } + @Override public void query(String sql, Map<String, ?> paramMap, RowCallbackHandler rch) throws DataAccessException { query(sql, new MapSqlParameterSource(paramMap), rch); } + @Override public void query(String sql, RowCallbackHandler rch) throws DataAccessException { query(sql, EmptySqlParameterSource.INSTANCE, rch); } + @Override public <T> List<T> query(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper) throws DataAccessException { return getJdbcOperations().query(getPreparedStatementCreator(sql, paramSource), rowMapper); } + @Override public <T> List<T> query(String sql, Map<String, ?> paramMap, RowMapper<T> rowMapper) throws DataAccessException { return query(sql, new MapSqlParameterSource(paramMap), rowMapper); } + @Override public <T> List<T> query(String sql, RowMapper<T> rowMapper) throws DataAccessException { return query(sql, EmptySqlParameterSource.INSTANCE, rowMapper); } + @Override public <T> T queryForObject(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper) throws DataAccessException { @@ -198,101 +212,120 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations return DataAccessUtils.requiredSingleResult(results); } + @Override public <T> T queryForObject(String sql, Map<String, ?> paramMap, RowMapper<T>rowMapper) throws DataAccessException { return queryForObject(sql, new MapSqlParameterSource(paramMap), rowMapper); } + @Override public <T> T queryForObject(String sql, SqlParameterSource paramSource, Class<T> requiredType) throws DataAccessException { return queryForObject(sql, paramSource, new SingleColumnRowMapper<T>(requiredType)); } + @Override public <T> T queryForObject(String sql, Map<String, ?> paramMap, Class<T> requiredType) throws DataAccessException { return queryForObject(sql, paramMap, new SingleColumnRowMapper<T>(requiredType)); } + @Override public Map<String, Object> queryForMap(String sql, SqlParameterSource paramSource) throws DataAccessException { return queryForObject(sql, paramSource, new ColumnMapRowMapper()); } + @Override public Map<String, Object> queryForMap(String sql, Map<String, ?> paramMap) throws DataAccessException { return queryForObject(sql, paramMap, new ColumnMapRowMapper()); } + @Override @Deprecated public long queryForLong(String sql, SqlParameterSource paramSource) throws DataAccessException { Number number = queryForObject(sql, paramSource, Long.class); return (number != null ? number.longValue() : 0); } + @Override @Deprecated public long queryForLong(String sql, Map<String, ?> paramMap) throws DataAccessException { return queryForLong(sql, new MapSqlParameterSource(paramMap)); } + @Override @Deprecated public int queryForInt(String sql, SqlParameterSource paramSource) throws DataAccessException { Number number = queryForObject(sql, paramSource, Integer.class); return (number != null ? number.intValue() : 0); } + @Override @Deprecated public int queryForInt(String sql, Map<String, ?> paramMap) throws DataAccessException { return queryForInt(sql, new MapSqlParameterSource(paramMap)); } + @Override public <T> List<T> queryForList(String sql, SqlParameterSource paramSource, Class<T> elementType) throws DataAccessException { return query(sql, paramSource, new SingleColumnRowMapper<T>(elementType)); } + @Override public <T> List<T> queryForList(String sql, Map<String, ?> paramMap, Class<T> elementType) throws DataAccessException { return queryForList(sql, new MapSqlParameterSource(paramMap), elementType); } + @Override public List<Map<String, Object>> queryForList(String sql, SqlParameterSource paramSource) throws DataAccessException { return query(sql, paramSource, new ColumnMapRowMapper()); } + @Override public List<Map<String, Object>> queryForList(String sql, Map<String, ?> paramMap) throws DataAccessException { return queryForList(sql, new MapSqlParameterSource(paramMap)); } + @Override public SqlRowSet queryForRowSet(String sql, SqlParameterSource paramSource) throws DataAccessException { return getJdbcOperations().query( getPreparedStatementCreator(sql, paramSource), new SqlRowSetResultSetExtractor()); } + @Override public SqlRowSet queryForRowSet(String sql, Map<String, ?> paramMap) throws DataAccessException { return queryForRowSet(sql, new MapSqlParameterSource(paramMap)); } + @Override public int update(String sql, SqlParameterSource paramSource) throws DataAccessException { return getJdbcOperations().update(getPreparedStatementCreator(sql, paramSource)); } + @Override public int update(String sql, Map<String, ?> paramMap) throws DataAccessException { return update(sql, new MapSqlParameterSource(paramMap)); } + @Override public int update(String sql, SqlParameterSource paramSource, KeyHolder generatedKeyHolder) throws DataAccessException { return update(sql, paramSource, generatedKeyHolder, null); } + @Override public int update( String sql, SqlParameterSource paramSource, KeyHolder generatedKeyHolder, String[] keyColumnNames) throws DataAccessException { @@ -311,6 +344,7 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations return getJdbcOperations().update(pscf.newPreparedStatementCreator(params), generatedKeyHolder); } + @Override public int[] batchUpdate(String sql, Map<String, ?>[] batchValues) { SqlParameterSource[] batchArgs = new SqlParameterSource[batchValues.length]; int i = 0; @@ -321,6 +355,7 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations return batchUpdate(sql, batchArgs); } + @Override public int[] batchUpdate(String sql, SqlParameterSource[] batchArgs) { ParsedSql parsedSql = getParsedSql(sql); return NamedParameterBatchUpdateUtils.executeBatchUpdateWithNamedParameters(parsedSql, batchArgs, getJdbcOperations()); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterUtils.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterUtils.java index 31f84b50..6ddba8f2 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterUtils.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterUtils.java @@ -252,10 +252,10 @@ public abstract class NamedParameterUtils { public static String substituteNamedParameters(ParsedSql parsedSql, SqlParameterSource paramSource) { String originalSql = parsedSql.getOriginalSql(); StringBuilder actualSql = new StringBuilder(); - List paramNames = parsedSql.getParameterNames(); + List<String> paramNames = parsedSql.getParameterNames(); int lastIndex = 0; for (int i = 0; i < paramNames.size(); i++) { - String paramName = (String) paramNames.get(i); + String paramName = paramNames.get(i); int[] indexes = parsedSql.getParameterIndexes(i); int startIndex = indexes[0]; int endIndex = indexes[1]; @@ -266,7 +266,7 @@ public abstract class NamedParameterUtils { value = ((SqlParameterValue) value).getValue(); } if (value instanceof Collection) { - Iterator entryIter = ((Collection) value).iterator(); + Iterator<?> entryIter = ((Collection<?>) value).iterator(); int k = 0; while (entryIter.hasNext()) { if (k > 0) { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/ParsedSql.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/ParsedSql.java index f498e6b3..c60164af 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/ParsedSql.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/ParsedSql.java @@ -70,7 +70,7 @@ public class ParsedSql { /** * Return all of the parameters (bind variables) in the parsed SQL statement. - * Repeated occurences of the same parameter name are included here. + * Repeated occurrences of the same parameter name are included here. */ List<String> getParameterNames() { return this.parameterNames; @@ -89,7 +89,7 @@ public class ParsedSql { /** * Set the count of named parameters in the SQL statement. - * Each parameter name counts once; repeated occurences do not count here. + * Each parameter name counts once; repeated occurrences do not count here. */ void setNamedParameterCount(int namedParameterCount) { this.namedParameterCount = namedParameterCount; @@ -97,7 +97,7 @@ public class ParsedSql { /** * Return the count of named parameters in the SQL statement. - * Each parameter name counts once; repeated occurences do not count here. + * Each parameter name counts once; repeated occurrences do not count here. */ int getNamedParameterCount() { return this.namedParameterCount; @@ -119,7 +119,7 @@ public class ParsedSql { /** * Set the total count of all of the parameters in the SQL statement. - * Repeated occurences of the same parameter name do count here. + * Repeated occurrences of the same parameter name do count here. */ void setTotalParameterCount(int totalParameterCount) { this.totalParameterCount = totalParameterCount; @@ -127,7 +127,7 @@ public class ParsedSql { /** * Return the total count of all of the parameters in the SQL statement. - * Repeated occurences of the same parameter name do count here. + * Repeated occurrences of the same parameter name do count here. */ int getTotalParameterCount() { return this.totalParameterCount; diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/SqlParameterSourceUtils.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/SqlParameterSourceUtils.java index b23eb8ca..e9f3f04e 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/SqlParameterSourceUtils.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/SqlParameterSourceUtils.java @@ -35,10 +35,10 @@ public class SqlParameterSourceUtils { * @param valueMaps array of Maps containing the values to be used * @return an array of SqlParameterSource */ - public static SqlParameterSource[] createBatch(Map[] valueMaps) { + public static SqlParameterSource[] createBatch(Map<String, ?>[] valueMaps) { MapSqlParameterSource[] batch = new MapSqlParameterSource[valueMaps.length]; for (int i = 0; i < valueMaps.length; i++) { - Map valueMap = valueMaps[i]; + Map<String, ?> valueMap = valueMaps[i]; batch[i] = new MapSqlParameterSource(valueMap); } return batch; @@ -80,13 +80,13 @@ public class SqlParameterSourceUtils { } } -/** - * Create a Map of case insensitive parameter names together with the original name. - * @param parameterSource the source of paramer names - * @return the Map that can be used for case insensitive matching of parameter names - */ - public static Map extractCaseInsensitiveParameterNames(SqlParameterSource parameterSource) { - Map caseInsensitiveParameterNames = new HashMap(); + /** + * Create a Map of case insensitive parameter names together with the original name. + * @param parameterSource the source of paramer names + * @return the Map that can be used for case insensitive matching of parameter names + */ + public static Map<String, String> extractCaseInsensitiveParameterNames(SqlParameterSource parameterSource) { + Map<String, String> caseInsensitiveParameterNames = new HashMap<String, String>(); if (parameterSource instanceof BeanPropertySqlParameterSource) { String[] propertyNames = ((BeanPropertySqlParameterSource)parameterSource).getReadablePropertyNames(); for (int i = 0; i < propertyNames.length; i++) { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/AbstractJdbcCall.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/AbstractJdbcCall.java index 992c19c9..56cf2084 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/AbstractJdbcCall.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/AbstractJdbcCall.java @@ -61,7 +61,7 @@ public abstract class AbstractJdbcCall { private final List<SqlParameter> declaredParameters = new ArrayList<SqlParameter>(); /** List of RefCursor/ResultSet RowMapper objects */ - private final Map<String, RowMapper> declaredRowMappers = new LinkedHashMap<String, RowMapper>(); + private final Map<String, RowMapper<?>> declaredRowMappers = new LinkedHashMap<String, RowMapper<?>>(); /** * Has this operation been compiled? Compilation means at least checking @@ -238,22 +238,13 @@ public abstract class AbstractJdbcCall { * @param parameterName name of parameter or column * @param rowMapper the RowMapper implementation to use */ - public void addDeclaredRowMapper(String parameterName, RowMapper rowMapper) { + public void addDeclaredRowMapper(String parameterName, RowMapper<?> rowMapper) { this.declaredRowMappers.put(parameterName, rowMapper); if (logger.isDebugEnabled()) { logger.debug("Added row mapper for [" + getProcedureName() + "]: " + parameterName); } } - /** - * Add a {@link org.springframework.jdbc.core.RowMapper} for the specified parameter or column. - * @deprecated in favor of {@link #addDeclaredRowMapper(String, org.springframework.jdbc.core.RowMapper)} - */ - @Deprecated - public void addDeclaredRowMapper(String parameterName, ParameterizedRowMapper rowMapper) { - addDeclaredRowMapper(parameterName, (RowMapper) rowMapper); - } - //------------------------------------------------------------------------- // Methods handling compilation issues @@ -295,7 +286,7 @@ public abstract class AbstractJdbcCall { this.callMetaDataContext.initializeMetaData(getJdbcTemplate().getDataSource()); // Iterate over the declared RowMappers and register the corresponding SqlParameter - for (Map.Entry<String, RowMapper> entry : this.declaredRowMappers.entrySet()) { + for (Map.Entry<String, RowMapper<?>> entry : this.declaredRowMappers.entrySet()) { SqlParameter resultSetParameter = this.callMetaDataContext.createReturnResultSetParameter(entry.getKey(), entry.getValue()); this.declaredParameters.add(resultSetParameter); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/AbstractJdbcInsert.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/AbstractJdbcInsert.java index e71129b1..0f9b8fb3 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/AbstractJdbcInsert.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/AbstractJdbcInsert.java @@ -435,6 +435,7 @@ public abstract class AbstractJdbcInsert { if (this.tableMetaDataContext.isGetGeneratedKeysSupported()) { getJdbcTemplate().update( new PreparedStatementCreator() { + @Override public PreparedStatement createPreparedStatement(Connection con) throws SQLException { PreparedStatement ps = prepareStatementForGeneratedKeys(con); setParameterValues(ps, values, getInsertTypes()); @@ -472,6 +473,7 @@ public abstract class AbstractJdbcInsert { } else { getJdbcTemplate().execute(new ConnectionCallback<Object>() { + @Override public Object doInConnection(Connection con) throws SQLException, DataAccessException { // Do the insert PreparedStatement ps = null; @@ -578,10 +580,12 @@ public abstract class AbstractJdbcInsert { } return getJdbcTemplate().batchUpdate(getInsertString(), new BatchPreparedStatementSetter() { + @Override public void setValues(PreparedStatement ps, int i) throws SQLException { List<Object> values = batchValues[i]; setParameterValues(ps, values, getInsertTypes()); } + @Override public int getBatchSize() { return batchValues.length; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcCall.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcCall.java index 64368f4a..df58d5d0 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcCall.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcCall.java @@ -79,33 +79,39 @@ public class SimpleJdbcCall extends AbstractJdbcCall implements SimpleJdbcCallOp } + @Override public SimpleJdbcCall withProcedureName(String procedureName) { setProcedureName(procedureName); setFunction(false); return this; } + @Override public SimpleJdbcCall withFunctionName(String functionName) { setProcedureName(functionName); setFunction(true); return this; } + @Override public SimpleJdbcCall withSchemaName(String schemaName) { setSchemaName(schemaName); return this; } + @Override public SimpleJdbcCall withCatalogName(String catalogName) { setCatalogName(catalogName); return this; } + @Override public SimpleJdbcCall withReturnValue() { setReturnValueRequired(true); return this; } + @Override public SimpleJdbcCall declareParameters(SqlParameter... sqlParameters) { for (SqlParameter sqlParameter : sqlParameters) { if (sqlParameter != null) { @@ -115,68 +121,71 @@ public class SimpleJdbcCall extends AbstractJdbcCall implements SimpleJdbcCallOp return this; } + @Override public SimpleJdbcCall useInParameterNames(String... inParameterNames) { setInParameterNames(new LinkedHashSet<String>(Arrays.asList(inParameterNames))); return this; } - public SimpleJdbcCall returningResultSet(String parameterName, RowMapper rowMapper) { - addDeclaredRowMapper(parameterName, rowMapper); - return this; - } - - /** - * @deprecated in favor of {@link #returningResultSet(String, org.springframework.jdbc.core.RowMapper)} - */ - @Deprecated - public SimpleJdbcCall returningResultSet(String parameterName, ParameterizedRowMapper rowMapper) { + @Override + public SimpleJdbcCall returningResultSet(String parameterName, RowMapper<?> rowMapper) { addDeclaredRowMapper(parameterName, rowMapper); return this; } + @Override public SimpleJdbcCall withoutProcedureColumnMetaDataAccess() { setAccessCallParameterMetaData(false); return this; } + @Override @SuppressWarnings("unchecked") public <T> T executeFunction(Class<T> returnType, Object... args) { return (T) doExecute(args).get(getScalarOutParameterName()); } + @Override @SuppressWarnings("unchecked") public <T> T executeFunction(Class<T> returnType, Map<String, ?> args) { return (T) doExecute(args).get(getScalarOutParameterName()); } + @Override @SuppressWarnings("unchecked") public <T> T executeFunction(Class<T> returnType, SqlParameterSource args) { return (T) doExecute(args).get(getScalarOutParameterName()); } + @Override @SuppressWarnings("unchecked") public <T> T executeObject(Class<T> returnType, Object... args) { return (T) doExecute(args).get(getScalarOutParameterName()); } + @Override @SuppressWarnings("unchecked") public <T> T executeObject(Class<T> returnType, Map<String, ?> args) { return (T) doExecute(args).get(getScalarOutParameterName()); } + @Override @SuppressWarnings("unchecked") public <T> T executeObject(Class<T> returnType, SqlParameterSource args) { return (T) doExecute(args).get(getScalarOutParameterName()); } + @Override public Map<String, Object> execute(Object... args) { return doExecute(args); } + @Override public Map<String, Object> execute(Map<String, ?> args) { return doExecute(args); } + @Override public Map<String, Object> execute(SqlParameterSource parameterSource) { return doExecute(parameterSource); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcCallOperations.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcCallOperations.java index 0cd4307d..fcdca17f 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcCallOperations.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcCallOperations.java @@ -92,18 +92,7 @@ public interface SimpleJdbcCallOperations { * @param parameterName the name of the returned results and/or the name of the ref cursor parameter * @param rowMapper the RowMapper implementation that will map the data returned for each row * */ - SimpleJdbcCallOperations returningResultSet(String parameterName, RowMapper rowMapper); - - /** - * Used to specify when a ResultSet is returned by the stored procedure and you want it mapped - * by a RowMapper. The results will be returned using the parameter name specified. Multiple - * ResultSets must be declared in the correct order. If the database you are using uses ref cursors - * then the name specified must match the name of the parameter declared for the procedure in the - * database. - * @deprecated in favor of {@link #returningResultSet(String, org.springframework.jdbc.core.RowMapper)} - */ - @Deprecated - SimpleJdbcCallOperations returningResultSet(String parameterName, ParameterizedRowMapper rowMapper); + SimpleJdbcCallOperations returningResultSet(String parameterName, RowMapper<?> rowMapper); /** * Turn off any processing of parameter meta data information obtained via JDBC. diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcInsert.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcInsert.java index ba6d109a..2bae7ec4 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcInsert.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcInsert.java @@ -69,74 +69,90 @@ public class SimpleJdbcInsert extends AbstractJdbcInsert implements SimpleJdbcIn } + @Override public SimpleJdbcInsert withTableName(String tableName) { setTableName(tableName); return this; } + @Override public SimpleJdbcInsert withSchemaName(String schemaName) { setSchemaName(schemaName); return this; } + @Override public SimpleJdbcInsert withCatalogName(String catalogName) { setCatalogName(catalogName); return this; } + @Override public SimpleJdbcInsert usingColumns(String... columnNames) { setColumnNames(Arrays.asList(columnNames)); return this; } + @Override public SimpleJdbcInsert usingGeneratedKeyColumns(String... columnNames) { setGeneratedKeyNames(columnNames); return this; } + @Override public SimpleJdbcInsertOperations withoutTableColumnMetaDataAccess() { setAccessTableColumnMetaData(false); return this; } + @Override public SimpleJdbcInsertOperations includeSynonymsForTableColumnMetaData() { setOverrideIncludeSynonymsDefault(true); return this; } + @Override public SimpleJdbcInsertOperations useNativeJdbcExtractorForMetaData(NativeJdbcExtractor nativeJdbcExtractor) { setNativeJdbcExtractor(nativeJdbcExtractor); return this; } + @Override public int execute(Map<String, Object> args) { return doExecute(args); } + @Override public int execute(SqlParameterSource parameterSource) { return doExecute(parameterSource); } + @Override public Number executeAndReturnKey(Map<String, Object> args) { return doExecuteAndReturnKey(args); } + @Override public Number executeAndReturnKey(SqlParameterSource parameterSource) { return doExecuteAndReturnKey(parameterSource); } + @Override public KeyHolder executeAndReturnKeyHolder(Map<String, Object> args) { return doExecuteAndReturnKeyHolder(args); } + @Override public KeyHolder executeAndReturnKeyHolder(SqlParameterSource parameterSource) { return doExecuteAndReturnKeyHolder(parameterSource); } + @Override public int[] executeBatch(Map<String, Object>[] batch) { return doExecuteBatch(batch); } + @Override public int[] executeBatch(SqlParameterSource[] batch) { return doExecuteBatch(batch); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcTemplate.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcTemplate.java index a4ec41fc..f947df58 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcTemplate.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,13 +18,12 @@ package org.springframework.jdbc.core.simple; import java.util.List; import java.util.Map; - import javax.sql.DataSource; import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.BatchUpdateUtils; import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.BatchUpdateUtils; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.SqlParameterSource; @@ -42,6 +41,8 @@ import org.springframework.util.ObjectUtils; * such as RowCallbackHandler, updates with PreparedStatementSetters rather than * argument arrays, and stored procedures as well as batch operations. * + * <p><b>NOTE: An instance of this class is thread-safe once configured.</b> + * * @author Rod Johnson * @author Rob Harrop * @author Juergen Hoeller @@ -91,6 +92,7 @@ public class SimpleJdbcTemplate implements SimpleJdbcOperations { * Expose the classic Spring JdbcTemplate to allow invocation of * less commonly used methods. */ + @Override public JdbcOperations getJdbcOperations() { return this.namedParameterJdbcOperations.getJdbcOperations(); } @@ -99,172 +101,207 @@ public class SimpleJdbcTemplate implements SimpleJdbcOperations { * Expose the Spring NamedParameterJdbcTemplate to allow invocation of * less commonly used methods. */ + @Override public NamedParameterJdbcOperations getNamedParameterJdbcOperations() { return this.namedParameterJdbcOperations; } + @Override public int queryForInt(String sql, Map<String, ?> args) throws DataAccessException { return getNamedParameterJdbcOperations().queryForInt(sql, args); } + @Override public int queryForInt(String sql, SqlParameterSource args) throws DataAccessException { return getNamedParameterJdbcOperations().queryForInt(sql, args); } + @Override public int queryForInt(String sql, Object... args) throws DataAccessException { return (ObjectUtils.isEmpty(args) ? getJdbcOperations().queryForInt(sql) : getJdbcOperations().queryForInt(sql, getArguments(args))); } + @Override public long queryForLong(String sql, Map<String, ?> args) throws DataAccessException { return getNamedParameterJdbcOperations().queryForLong(sql, args); } + @Override public long queryForLong(String sql, SqlParameterSource args) throws DataAccessException { return getNamedParameterJdbcOperations().queryForLong(sql, args); } + @Override public long queryForLong(String sql, Object... args) throws DataAccessException { return (ObjectUtils.isEmpty(args) ? getJdbcOperations().queryForLong(sql) : getJdbcOperations().queryForLong(sql, getArguments(args))); } + @Override public <T> T queryForObject(String sql, Class<T> requiredType, Map<String, ?> args) throws DataAccessException { return getNamedParameterJdbcOperations().queryForObject(sql, args, requiredType); } + @Override public <T> T queryForObject(String sql, Class<T> requiredType, SqlParameterSource args) throws DataAccessException { return getNamedParameterJdbcOperations().queryForObject(sql, args, requiredType); } + @Override public <T> T queryForObject(String sql, Class<T> requiredType, Object... args) throws DataAccessException { return (ObjectUtils.isEmpty(args) ? getJdbcOperations().queryForObject(sql, requiredType) : getJdbcOperations().queryForObject(sql, getArguments(args), requiredType)); } + @Override public <T> T queryForObject(String sql, RowMapper<T> rm, Map<String, ?> args) throws DataAccessException { return getNamedParameterJdbcOperations().queryForObject(sql, args, rm); } + @Override @Deprecated public <T> T queryForObject(String sql, ParameterizedRowMapper<T> rm, Map<String, ?> args) throws DataAccessException { return queryForObject(sql, (RowMapper<T>) rm, args); } + @Override public <T> T queryForObject(String sql, RowMapper<T> rm, SqlParameterSource args) throws DataAccessException { return getNamedParameterJdbcOperations().queryForObject(sql, args, rm); } + @Override @Deprecated public <T> T queryForObject(String sql, ParameterizedRowMapper<T> rm, SqlParameterSource args) throws DataAccessException { return queryForObject(sql, (RowMapper<T>) rm, args); } + @Override public <T> T queryForObject(String sql, RowMapper<T> rm, Object... args) throws DataAccessException { return (ObjectUtils.isEmpty(args) ? getJdbcOperations().queryForObject(sql, rm): getJdbcOperations().queryForObject(sql, getArguments(args), rm)); } + @Override @Deprecated public <T> T queryForObject(String sql, ParameterizedRowMapper<T> rm, Object... args) throws DataAccessException { return queryForObject(sql, (RowMapper<T>) rm, args); } + @Override public <T> List<T> query(String sql, RowMapper<T> rm, Map<String, ?> args) throws DataAccessException { return getNamedParameterJdbcOperations().query(sql, args, rm); } + @Override @Deprecated public <T> List<T> query(String sql, ParameterizedRowMapper<T> rm, Map<String, ?> args) throws DataAccessException { return query(sql, (RowMapper<T>) rm, args); } + @Override public <T> List<T> query(String sql, RowMapper<T> rm, SqlParameterSource args) throws DataAccessException { return getNamedParameterJdbcOperations().query(sql, args, rm); } + @Override @Deprecated public <T> List<T> query(String sql, ParameterizedRowMapper<T> rm, SqlParameterSource args) throws DataAccessException { return query(sql, (RowMapper<T>) rm, args); } + @Override public <T> List<T> query(String sql, RowMapper<T> rm, Object... args) throws DataAccessException { return (ObjectUtils.isEmpty(args) ? getJdbcOperations().query(sql, rm) : getJdbcOperations().query(sql, getArguments(args), rm)); } + @Override @Deprecated public <T> List<T> query(String sql, ParameterizedRowMapper<T> rm, Object... args) throws DataAccessException { return query(sql, (RowMapper<T>) rm, args); } + @Override public Map<String, Object> queryForMap(String sql, Map<String, ?> args) throws DataAccessException { return getNamedParameterJdbcOperations().queryForMap(sql, args); } + @Override public Map<String, Object> queryForMap(String sql, SqlParameterSource args) throws DataAccessException { return getNamedParameterJdbcOperations().queryForMap(sql, args); } + @Override public Map<String, Object> queryForMap(String sql, Object... args) throws DataAccessException { return (ObjectUtils.isEmpty(args) ? getJdbcOperations().queryForMap(sql) : getJdbcOperations().queryForMap(sql, getArguments(args))); } + @Override public List<Map<String, Object>> queryForList(String sql, Map<String, ?> args) throws DataAccessException { return getNamedParameterJdbcOperations().queryForList(sql, args); } + @Override public List<Map<String, Object>> queryForList(String sql, SqlParameterSource args) throws DataAccessException { return getNamedParameterJdbcOperations().queryForList(sql, args); } + @Override public List<Map<String, Object>> queryForList(String sql, Object... args) throws DataAccessException { return (ObjectUtils.isEmpty(args) ? getJdbcOperations().queryForList(sql) : getJdbcOperations().queryForList(sql, getArguments(args))); } + @Override public int update(String sql, Map<String, ?> args) throws DataAccessException { return getNamedParameterJdbcOperations().update(sql, args); } + @Override public int update(String sql, SqlParameterSource args) throws DataAccessException { return getNamedParameterJdbcOperations().update(sql, args); } + @Override public int update(String sql, Object ... args) throws DataAccessException { return (ObjectUtils.isEmpty(args) ? getJdbcOperations().update(sql) : getJdbcOperations().update(sql, getArguments(args))); } + @Override public int[] batchUpdate(String sql, List<Object[]> batchArgs) { return batchUpdate(sql, batchArgs, new int[0]); } + @Override public int[] batchUpdate(String sql, List<Object[]> batchArgs, int[] argTypes) { return BatchUpdateUtils.executeBatchUpdate(sql, batchArgs, argTypes, getJdbcOperations()); } + @Override public int[] batchUpdate(String sql, Map<String, ?>[] batchValues) { return getNamedParameterJdbcOperations().batchUpdate(sql, batchValues); } + @Override public int[] batchUpdate(String sql, SqlParameterSource[] batchArgs) { return getNamedParameterJdbcOperations().batchUpdate(sql, batchArgs); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/AbstractInterruptibleBatchPreparedStatementSetter.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/AbstractInterruptibleBatchPreparedStatementSetter.java index 83d37435..7fb5e6d1 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/AbstractInterruptibleBatchPreparedStatementSetter.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/AbstractInterruptibleBatchPreparedStatementSetter.java @@ -40,6 +40,7 @@ public abstract class AbstractInterruptibleBatchPreparedStatementSetter * This implementation calls {@link #setValuesIfAvailable} * and sets this instance's exhaustion flag accordingly. */ + @Override public final void setValues(PreparedStatement ps, int i) throws SQLException { this.exhausted = !setValuesIfAvailable(ps, i); } @@ -47,6 +48,7 @@ public abstract class AbstractInterruptibleBatchPreparedStatementSetter /** * This implementation return this instance's current exhaustion flag. */ + @Override public final boolean isBatchExhausted(int i) { return this.exhausted; } @@ -55,6 +57,7 @@ public abstract class AbstractInterruptibleBatchPreparedStatementSetter * This implementation returns {@code Integer.MAX_VALUE}. * Can be overridden in subclasses to lower the maximum batch size. */ + @Override public int getBatchSize() { return Integer.MAX_VALUE; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/AbstractLobCreatingPreparedStatementCallback.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/AbstractLobCreatingPreparedStatementCallback.java index c106ad57..ee4633d5 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/AbstractLobCreatingPreparedStatementCallback.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/AbstractLobCreatingPreparedStatementCallback.java @@ -68,6 +68,7 @@ public abstract class AbstractLobCreatingPreparedStatementCallback implements Pr } + @Override public final Integer doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException { LobCreator lobCreator = this.lobHandler.getLobCreator(); try { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/AbstractLobStreamingResultSetExtractor.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/AbstractLobStreamingResultSetExtractor.java index 83a9aedf..496bbdbf 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/AbstractLobStreamingResultSetExtractor.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/AbstractLobStreamingResultSetExtractor.java @@ -53,7 +53,7 @@ import org.springframework.jdbc.core.ResultSetExtractor; * @see org.springframework.jdbc.support.lob.LobHandler * @see org.springframework.jdbc.LobRetrievalFailureException */ -public abstract class AbstractLobStreamingResultSetExtractor implements ResultSetExtractor { +public abstract class AbstractLobStreamingResultSetExtractor<T> implements ResultSetExtractor<T> { /** * Delegates to handleNoRowFound, handleMultipleRowsFound and streamData, @@ -64,7 +64,8 @@ public abstract class AbstractLobStreamingResultSetExtractor implements ResultSe * @see #streamData * @see org.springframework.jdbc.LobRetrievalFailureException */ - public final Object extractData(ResultSet rs) throws SQLException, DataAccessException { + @Override + public final T extractData(ResultSet rs) throws SQLException, DataAccessException { if (!rs.next()) { handleNoRowFound(); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/AbstractSqlTypeValue.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/AbstractSqlTypeValue.java index d7519339..67f325c8 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/AbstractSqlTypeValue.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/AbstractSqlTypeValue.java @@ -52,6 +52,7 @@ import org.springframework.jdbc.core.SqlTypeValue; */ public abstract class AbstractSqlTypeValue implements SqlTypeValue { + @Override public final void setTypeValue(PreparedStatement ps, int paramIndex, int sqlType, String typeName) throws SQLException { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/JdbcBeanDefinitionReader.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/JdbcBeanDefinitionReader.java index 7039eeac..bdcd1c30 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/JdbcBeanDefinitionReader.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/JdbcBeanDefinitionReader.java @@ -107,6 +107,7 @@ public class JdbcBeanDefinitionReader { Assert.notNull(this.jdbcTemplate, "Not fully configured - specify DataSource or JdbcTemplate"); final Properties props = new Properties(); this.jdbcTemplate.query(sql, new RowCallbackHandler() { + @Override public void processRow(ResultSet rs) throws SQLException { String beanName = rs.getString(1); String property = rs.getString(2); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/SqlLobValue.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/SqlLobValue.java index 2cc5f9f9..8e46d42b 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/SqlLobValue.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/support/SqlLobValue.java @@ -168,6 +168,7 @@ public class SqlLobValue implements DisposableSqlTypeValue { /** * Set the specified content via the LobCreator. */ + @Override public void setTypeValue(PreparedStatement ps, int paramIndex, int sqlType, String typeName) throws SQLException { if (sqlType == Types.BLOB) { @@ -208,6 +209,7 @@ public class SqlLobValue implements DisposableSqlTypeValue { /** * Close the LobCreator, if any. */ + @Override public void cleanup() { this.lobCreator.close(); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/AbstractDataSource.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/AbstractDataSource.java index 0674c79b..63d9ddff 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/AbstractDataSource.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/AbstractDataSource.java @@ -45,6 +45,7 @@ public abstract class AbstractDataSource implements DataSource { /** * Returns 0, indicating the default system timeout is to be used. */ + @Override public int getLoginTimeout() throws SQLException { return 0; } @@ -52,6 +53,7 @@ public abstract class AbstractDataSource implements DataSource { /** * Setting a login timeout is not supported. */ + @Override public void setLoginTimeout(int timeout) throws SQLException { throw new UnsupportedOperationException("setLoginTimeout"); } @@ -59,6 +61,7 @@ public abstract class AbstractDataSource implements DataSource { /** * LogWriter methods are not supported. */ + @Override public PrintWriter getLogWriter() { throw new UnsupportedOperationException("getLogWriter"); } @@ -66,6 +69,7 @@ public abstract class AbstractDataSource implements DataSource { /** * LogWriter methods are not supported. */ + @Override public void setLogWriter(PrintWriter pw) throws SQLException { throw new UnsupportedOperationException("setLogWriter"); } @@ -75,6 +79,7 @@ public abstract class AbstractDataSource implements DataSource { // Implementation of JDBC 4.0's Wrapper interface //--------------------------------------------------------------------- + @Override @SuppressWarnings("unchecked") public <T> T unwrap(Class<T> iface) throws SQLException { if (iface.isInstance(this)) { @@ -84,6 +89,7 @@ public abstract class AbstractDataSource implements DataSource { "] cannot be unwrapped as [" + iface.getName() + "]"); } + @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { return iface.isInstance(this); } @@ -93,6 +99,7 @@ public abstract class AbstractDataSource implements DataSource { // Implementation of JDBC 4.1's getParentLogger method //--------------------------------------------------------------------- + @Override public Logger getParentLogger() { return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/AbstractDriverBasedDataSource.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/AbstractDriverBasedDataSource.java index c7e7e199..0a2808fe 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/AbstractDriverBasedDataSource.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/AbstractDriverBasedDataSource.java @@ -115,6 +115,7 @@ public abstract class AbstractDriverBasedDataSource extends AbstractDataSource { * @see #setUsername * @see #setPassword */ + @Override public Connection getConnection() throws SQLException { return getConnectionFromDriver(getUsername(), getPassword()); } @@ -124,6 +125,7 @@ public abstract class AbstractDriverBasedDataSource extends AbstractDataSource { * using the given username and password. * @see #getConnectionFromDriver(String, String) */ + @Override public Connection getConnection(String username, String password) throws SQLException { return getConnectionFromDriver(username, password); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/ConnectionHandle.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/ConnectionHandle.java index 4223dfed..2343aef4 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/ConnectionHandle.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/ConnectionHandle.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2005 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,12 +20,13 @@ import java.sql.Connection; /** * Simple interface to be implemented by handles for a JDBC Connection. - * Used by JdoDialect, for example. + * Used by JpaDialect and JdoDialect, for example. * * @author Juergen Hoeller * @since 1.1 * @see SimpleConnectionHandle * @see ConnectionHolder + * @see org.springframework.orm.jdo.JpaDialect#getJdbcConnection * @see org.springframework.orm.jdo.JdoDialect#getJdbcConnection */ public interface ConnectionHandle { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceTransactionManager.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceTransactionManager.java index 3acd7749..421ecb78 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceTransactionManager.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceTransactionManager.java @@ -161,6 +161,7 @@ public class DataSourceTransactionManager extends AbstractPlatformTransactionMan return this.dataSource; } + @Override public void afterPropertiesSet() { if (getDataSource() == null) { throw new IllegalArgumentException("Property 'dataSource' is required"); @@ -168,6 +169,7 @@ public class DataSourceTransactionManager extends AbstractPlatformTransactionMan } + @Override public Object getResourceFactory() { return getDataSource(); } @@ -362,6 +364,7 @@ public class DataSourceTransactionManager extends AbstractPlatformTransactionMan getConnectionHolder().setRollbackOnly(); } + @Override public boolean isRollbackOnly() { return getConnectionHolder().isRollbackOnly(); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DelegatingDataSource.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DelegatingDataSource.java index a4c162dd..3adef83c 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DelegatingDataSource.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DelegatingDataSource.java @@ -73,6 +73,7 @@ public class DelegatingDataSource implements DataSource, InitializingBean { return this.targetDataSource; } + @Override public void afterPropertiesSet() { if (getTargetDataSource() == null) { throw new IllegalArgumentException("Property 'targetDataSource' is required"); @@ -80,26 +81,32 @@ public class DelegatingDataSource implements DataSource, InitializingBean { } + @Override public Connection getConnection() throws SQLException { return getTargetDataSource().getConnection(); } + @Override public Connection getConnection(String username, String password) throws SQLException { return getTargetDataSource().getConnection(username, password); } + @Override public PrintWriter getLogWriter() throws SQLException { return getTargetDataSource().getLogWriter(); } + @Override public void setLogWriter(PrintWriter out) throws SQLException { getTargetDataSource().setLogWriter(out); } + @Override public int getLoginTimeout() throws SQLException { return getTargetDataSource().getLoginTimeout(); } + @Override public void setLoginTimeout(int seconds) throws SQLException { getTargetDataSource().setLoginTimeout(seconds); } @@ -109,6 +116,7 @@ public class DelegatingDataSource implements DataSource, InitializingBean { // Implementation of JDBC 4.0's Wrapper interface //--------------------------------------------------------------------- + @Override @SuppressWarnings("unchecked") public <T> T unwrap(Class<T> iface) throws SQLException { if (iface.isInstance(this)) { @@ -117,6 +125,7 @@ public class DelegatingDataSource implements DataSource, InitializingBean { return getTargetDataSource().unwrap(iface); } + @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { return (iface.isInstance(this) || getTargetDataSource().isWrapperFor(iface)); } @@ -126,6 +135,7 @@ public class DelegatingDataSource implements DataSource, InitializingBean { // Implementation of JDBC 4.1's getParentLogger method //--------------------------------------------------------------------- + @Override public Logger getParentLogger() { return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DriverManagerDataSource.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DriverManagerDataSource.java index 5aaf586b..b272b572 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DriverManagerDataSource.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DriverManagerDataSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -107,26 +107,6 @@ public class DriverManagerDataSource extends AbstractDriverBasedDataSource { setConnectionProperties(conProps); } - /** - * Create a new DriverManagerDataSource with the given standard - * DriverManager parameters. - * @param driverClassName the JDBC driver class name - * @param url the JDBC URL to use for accessing the DriverManager - * @param username the JDBC username to use for accessing the DriverManager - * @param password the JDBC password to use for accessing the DriverManager - * @deprecated since Spring 2.5. DriverManagerDataSource is primarily - * intended for accessing <i>pre-registered</i> JDBC drivers. - * If you need to register a new driver, consider using - * {@link SimpleDriverDataSource} instead. - */ - @Deprecated - public DriverManagerDataSource(String driverClassName, String url, String username, String password) { - setDriverClassName(driverClassName); - setUrl(url); - setUsername(username); - setPassword(password); - } - /** * Set the JDBC driver class name. This driver will get initialized diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/JdbcTransactionObjectSupport.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/JdbcTransactionObjectSupport.java index 57cd9416..18c65728 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/JdbcTransactionObjectSupport.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/JdbcTransactionObjectSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -87,6 +87,7 @@ public abstract class JdbcTransactionObjectSupport implements SavepointManager, return this.savepointAllowed; } + @Override public void flush() { // no-op } @@ -100,6 +101,7 @@ public abstract class JdbcTransactionObjectSupport implements SavepointManager, * This implementation creates a JDBC 3.0 Savepoint and returns it. * @see java.sql.Connection#setSavepoint */ + @Override public Object createSavepoint() throws TransactionException { ConnectionHolder conHolder = getConnectionHolderForSavepoint(); try { @@ -124,6 +126,7 @@ public abstract class JdbcTransactionObjectSupport implements SavepointManager, * This implementation rolls back to the given JDBC 3.0 Savepoint. * @see java.sql.Connection#rollback(java.sql.Savepoint) */ + @Override public void rollbackToSavepoint(Object savepoint) throws TransactionException { try { getConnectionHolderForSavepoint().getConnection().rollback((Savepoint) savepoint); @@ -137,6 +140,7 @@ public abstract class JdbcTransactionObjectSupport implements SavepointManager, * This implementation releases the given JDBC 3.0 Savepoint. * @see java.sql.Connection#releaseSavepoint */ + @Override public void releaseSavepoint(Object savepoint) throws TransactionException { try { getConnectionHolderForSavepoint().getConnection().releaseSavepoint((Savepoint) savepoint); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/LazyConnectionDataSourceProxy.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/LazyConnectionDataSourceProxy.java index 5495aa68..9df9e096 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/LazyConnectionDataSourceProxy.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/LazyConnectionDataSourceProxy.java @@ -219,7 +219,7 @@ public class LazyConnectionDataSourceProxy extends DelegatingDataSource { public Connection getConnection() throws SQLException { return (Connection) Proxy.newProxyInstance( ConnectionProxy.class.getClassLoader(), - new Class[] {ConnectionProxy.class}, + new Class<?>[] {ConnectionProxy.class}, new LazyConnectionInvocationHandler()); } @@ -237,7 +237,7 @@ public class LazyConnectionDataSourceProxy extends DelegatingDataSource { public Connection getConnection(String username, String password) throws SQLException { return (Connection) Proxy.newProxyInstance( ConnectionProxy.class.getClassLoader(), - new Class[] {ConnectionProxy.class}, + new Class<?>[] {ConnectionProxy.class}, new LazyConnectionInvocationHandler(username, password)); } @@ -273,6 +273,7 @@ public class LazyConnectionDataSourceProxy extends DelegatingDataSource { this.password = password; } + @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // Invocation on ConnectionProxy interface coming in... @@ -288,12 +289,12 @@ public class LazyConnectionDataSourceProxy extends DelegatingDataSource { return System.identityHashCode(proxy); } else if (method.getName().equals("unwrap")) { - if (((Class) args[0]).isInstance(proxy)) { + if (((Class<?>) args[0]).isInstance(proxy)) { return proxy; } } else if (method.getName().equals("isWrapperFor")) { - if (((Class) args[0]).isInstance(proxy)) { + if (((Class<?>) args[0]).isInstance(proxy)) { return true; } } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/SimpleConnectionHandle.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/SimpleConnectionHandle.java index ed37136a..6140a51f 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/SimpleConnectionHandle.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/SimpleConnectionHandle.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,6 +44,7 @@ public class SimpleConnectionHandle implements ConnectionHandle { /** * Return the specified Connection as-is. */ + @Override public Connection getConnection() { return this.connection; } @@ -52,6 +53,7 @@ public class SimpleConnectionHandle implements ConnectionHandle { * This implementation is empty, as we're using a standard * Connection handle that does not have to be released. */ + @Override public void releaseConnection(Connection con) { } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/SingleConnectionDataSource.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/SingleConnectionDataSource.java index 9d2b41f5..9d1411e9 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/SingleConnectionDataSource.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/SingleConnectionDataSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -83,28 +83,6 @@ public class SingleConnectionDataSource extends DriverManagerDataSource /** * Create a new SingleConnectionDataSource with the given standard * DriverManager parameters. - * @param driverClassName the JDBC driver class name - * @param url the JDBC URL to use for accessing the DriverManager - * @param username the JDBC username to use for accessing the DriverManager - * @param password the JDBC password to use for accessing the DriverManager - * @param suppressClose if the returned Connection should be a - * close-suppressing proxy or the physical Connection - * @deprecated since Spring 2.5. Driver parameter usage is generally not recommended - * for a SingleConnectionDataSource. If you insist on using driver parameters - * directly, set up the Driver class manually before invoking this DataSource. - * @see java.sql.DriverManager#getConnection(String, String, String) - */ - @Deprecated - public SingleConnectionDataSource( - String driverClassName, String url, String username, String password, boolean suppressClose) { - - super(driverClassName, url, username, password); - this.suppressClose = suppressClose; - } - - /** - * Create a new SingleConnectionDataSource with the given standard - * DriverManager parameters. * @param url the JDBC URL to use for accessing the DriverManager * @param username the JDBC username to use for accessing the DriverManager * @param password the JDBC password to use for accessing the DriverManager @@ -213,6 +191,7 @@ public class SingleConnectionDataSource extends DriverManagerDataSource /** * This is a single Connection: Do not close it when returning to the "pool". */ + @Override public boolean shouldClose(Connection con) { synchronized (this.connectionMonitor) { return (con != this.connection && con != this.target); @@ -225,6 +204,7 @@ public class SingleConnectionDataSource extends DriverManagerDataSource * <p>As this bean implements DisposableBean, a bean factory will * automatically invoke this on destruction of its cached singletons. */ + @Override public void destroy() { synchronized (this.connectionMonitor) { closeConnection(); @@ -298,7 +278,7 @@ public class SingleConnectionDataSource extends DriverManagerDataSource protected Connection getCloseSuppressingConnectionProxy(Connection target) { return (Connection) Proxy.newProxyInstance( ConnectionProxy.class.getClassLoader(), - new Class[] {ConnectionProxy.class}, + new Class<?>[] {ConnectionProxy.class}, new CloseSuppressingInvocationHandler(target)); } @@ -314,6 +294,7 @@ public class SingleConnectionDataSource extends DriverManagerDataSource this.target = target; } + @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // Invocation on ConnectionProxy interface coming in... @@ -326,12 +307,12 @@ public class SingleConnectionDataSource extends DriverManagerDataSource return System.identityHashCode(proxy); } else if (method.getName().equals("unwrap")) { - if (((Class) args[0]).isInstance(proxy)) { + if (((Class<?>) args[0]).isInstance(proxy)) { return proxy; } } else if (method.getName().equals("isWrapperFor")) { - if (((Class) args[0]).isInstance(proxy)) { + if (((Class<?>) args[0]).isInstance(proxy)) { return true; } } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/TransactionAwareDataSourceProxy.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/TransactionAwareDataSourceProxy.java index 3bde7776..81f94b62 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/TransactionAwareDataSourceProxy.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/TransactionAwareDataSourceProxy.java @@ -138,7 +138,7 @@ public class TransactionAwareDataSourceProxy extends DelegatingDataSource { protected Connection getTransactionAwareConnectionProxy(DataSource targetDataSource) { return (Connection) Proxy.newProxyInstance( ConnectionProxy.class.getClassLoader(), - new Class[] {ConnectionProxy.class}, + new Class<?>[] {ConnectionProxy.class}, new TransactionAwareInvocationHandler(targetDataSource)); } @@ -174,6 +174,7 @@ public class TransactionAwareDataSourceProxy extends DelegatingDataSource { this.targetDataSource = targetDataSource; } + @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // Invocation on ConnectionProxy interface coming in... @@ -197,12 +198,12 @@ public class TransactionAwareDataSourceProxy extends DelegatingDataSource { return sb.toString(); } else if (method.getName().equals("unwrap")) { - if (((Class) args[0]).isInstance(proxy)) { + if (((Class<?>) args[0]).isInstance(proxy)) { return proxy; } } else if (method.getName().equals("isWrapperFor")) { - if (((Class) args[0]).isInstance(proxy)) { + if (((Class<?>) args[0]).isInstance(proxy)) { return true; } } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/WebSphereDataSourceAdapter.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/WebSphereDataSourceAdapter.java index 6a3c6c53..ec29246b 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/WebSphereDataSourceAdapter.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/WebSphereDataSourceAdapter.java @@ -69,7 +69,7 @@ public class WebSphereDataSourceAdapter extends IsolationLevelDataSourceAdapter protected final Log logger = LogFactory.getLog(getClass()); - private Class wsDataSourceClass; + private Class<?> wsDataSourceClass; private Method newJdbcConnSpecMethod; @@ -91,16 +91,16 @@ public class WebSphereDataSourceAdapter extends IsolationLevelDataSourceAdapter public WebSphereDataSourceAdapter() { try { this.wsDataSourceClass = getClass().getClassLoader().loadClass("com.ibm.websphere.rsadapter.WSDataSource"); - Class jdbcConnSpecClass = getClass().getClassLoader().loadClass("com.ibm.websphere.rsadapter.JDBCConnectionSpec"); - Class wsrraFactoryClass = getClass().getClassLoader().loadClass("com.ibm.websphere.rsadapter.WSRRAFactory"); - this.newJdbcConnSpecMethod = wsrraFactoryClass.getMethod("createJDBCConnectionSpec", (Class[]) null); + Class<?> jdbcConnSpecClass = getClass().getClassLoader().loadClass("com.ibm.websphere.rsadapter.JDBCConnectionSpec"); + Class<?> wsrraFactoryClass = getClass().getClassLoader().loadClass("com.ibm.websphere.rsadapter.WSRRAFactory"); + this.newJdbcConnSpecMethod = wsrraFactoryClass.getMethod("createJDBCConnectionSpec", (Class<?>[]) null); this.wsDataSourceGetConnectionMethod = - this.wsDataSourceClass.getMethod("getConnection", new Class[] {jdbcConnSpecClass}); + this.wsDataSourceClass.getMethod("getConnection", new Class<?>[] {jdbcConnSpecClass}); this.setTransactionIsolationMethod = - jdbcConnSpecClass.getMethod("setTransactionIsolation", new Class[] {int.class}); - this.setReadOnlyMethod = jdbcConnSpecClass.getMethod("setReadOnly", new Class[] {Boolean.class}); - this.setUserNameMethod = jdbcConnSpecClass.getMethod("setUserName", new Class[] {String.class}); - this.setPasswordMethod = jdbcConnSpecClass.getMethod("setPassword", new Class[] {String.class}); + jdbcConnSpecClass.getMethod("setTransactionIsolation", new Class<?>[] {int.class}); + this.setReadOnlyMethod = jdbcConnSpecClass.getMethod("setReadOnly", new Class<?>[] {Boolean.class}); + this.setUserNameMethod = jdbcConnSpecClass.getMethod("setUserName", new Class<?>[] {String.class}); + this.setPasswordMethod = jdbcConnSpecClass.getMethod("setPassword", new Class<?>[] {String.class}); } catch (Exception ex) { throw new IllegalStateException( diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/AbstractEmbeddedDatabaseConfigurer.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/AbstractEmbeddedDatabaseConfigurer.java index 634eb57c..2497a6cc 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/AbstractEmbeddedDatabaseConfigurer.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/AbstractEmbeddedDatabaseConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,6 +35,7 @@ abstract class AbstractEmbeddedDatabaseConfigurer implements EmbeddedDatabaseCon protected final Log logger = LogFactory.getLog(getClass()); + @Override public void shutdown(DataSource dataSource, String databaseName) { try { Connection connection = dataSource.getConnection(); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/ConnectionProperties.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/ConnectionProperties.java index b97bec09..83cad4c7 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/ConnectionProperties.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/ConnectionProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,37 +18,39 @@ package org.springframework.jdbc.datasource.embedded; import java.sql.Driver; - /** - * DataSourceFactory helper that allows essential JDBC connection properties to be configured consistently, - * independent of the actual DataSource implementation. + * {@code ConnectionProperties} serves as a simple data container that allows + * essential JDBC connection properties to be configured consistently, + * independent of the actual {@link javax.sql.DataSource DataSource} + * implementation. * * @author Keith Donald + * @author Sam Brannen * @since 3.0 * @see DataSourceFactory */ public interface ConnectionProperties { /** - * Set the JDBC driver to use to connect to the database. + * Set the JDBC driver class to use to connect to the database. * @param driverClass the jdbc driver class */ void setDriverClass(Class<? extends Driver> driverClass); /** - * Sets the JDBC connection URL of the database. + * Set the JDBC connection URL for the database. * @param url the connection url */ void setUrl(String url); /** - * Sets the username to use to connect to the database. + * Set the username to use to connect to the database. * @param username the username */ void setUsername(String username); /** - * Sets the password to use to connect to the database. + * Set the password to use to connect to the database. * @param password the password */ void setPassword(String password); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DataSourceFactory.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DataSourceFactory.java index 9df27cf6..720296ec 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DataSourceFactory.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DataSourceFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,27 +18,31 @@ package org.springframework.jdbc.datasource.embedded; import javax.sql.DataSource; -import org.springframework.jdbc.datasource.SimpleDriverDataSource; - /** - * Encapsulates the creation of a particular DataSource implementation, such as a - * {@link SimpleDriverDataSource} or connection pool such as Apache DBCP or C3P0. + * {@code DataSourceFactory} encapsulates the creation of a particular + * {@link DataSource} implementation such as a + * {@link org.springframework.jdbc.datasource.SimpleDriverDataSource + * SimpleDriverDataSource} or a connection pool such as Apache DBCP or C3P0. * - * <p>Call {@link #getConnectionProperties()} to configure normalized DataSource properties - * before calling {@link #getDataSource()} to actually get the configured DataSource instance. + * <p>Call {@link #getConnectionProperties()} to configure normalized + * {@code DataSource} properties before calling {@link #getDataSource()} to + * actually get the configured {@code DataSource} instance. * * @author Keith Donald + * @author Sam Brannen * @since 3.0 */ public interface DataSourceFactory { /** - * Allows properties of the DataSource to be configured. + * Get the {@linkplain ConnectionProperties connection properties} of the + * {@link #getDataSource DataSource} to be configured. */ ConnectionProperties getConnectionProperties(); /** - * Returns the DataSource with the connection properties applied. + * Get the {@link DataSource} with the {@linkplain #getConnectionProperties + * connection properties} applied. */ DataSource getDataSource(); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DerbyEmbeddedDatabaseConfigurer.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DerbyEmbeddedDatabaseConfigurer.java index bb745d11..85ea5df6 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DerbyEmbeddedDatabaseConfigurer.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DerbyEmbeddedDatabaseConfigurer.java @@ -16,19 +16,16 @@ package org.springframework.jdbc.datasource.embedded; -import java.io.File; -import java.io.IOException; import java.sql.SQLException; import java.util.Properties; import javax.sql.DataSource; -import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.derby.impl.io.VFMemoryStorageFactory; import org.apache.derby.jdbc.EmbeddedDriver; /** - * {@link EmbeddedDatabaseConfigurer} for the Apache Derby database. + * {@link EmbeddedDatabaseConfigurer} for the Apache Derby database 10.6+. + * <p>Call {@link #getInstance()} to get the singleton instance of this class. * * @author Oliver Gierke * @author Juergen Hoeller @@ -36,14 +33,9 @@ import org.apache.derby.jdbc.EmbeddedDriver; */ final class DerbyEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigurer { - private static final Log logger = LogFactory.getLog(DerbyEmbeddedDatabaseConfigurer.class); - private static final String URL_TEMPLATE = "jdbc:derby:memory:%s;%s"; - // Error code that indicates successful shutdown - private static final String SHUTDOWN_CODE = "08006"; - - private static DerbyEmbeddedDatabaseConfigurer INSTANCE; + private static DerbyEmbeddedDatabaseConfigurer instance; /** @@ -52,18 +44,20 @@ final class DerbyEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigure * @throws ClassNotFoundException if Derby is not on the classpath */ public static synchronized DerbyEmbeddedDatabaseConfigurer getInstance() throws ClassNotFoundException { - if (INSTANCE == null) { + if (instance == null) { // disable log file System.setProperty("derby.stream.error.method", OutputStreamFactory.class.getName() + ".getNoopOutputStream"); - INSTANCE = new DerbyEmbeddedDatabaseConfigurer(); + instance = new DerbyEmbeddedDatabaseConfigurer(); } - return INSTANCE; + return instance; } + private DerbyEmbeddedDatabaseConfigurer() { } + @Override public void configureConnectionProperties(ConnectionProperties properties, String databaseName) { properties.setDriverClass(EmbeddedDriver.class); properties.setUrl(String.format(URL_TEMPLATE, databaseName, "create=true")); @@ -71,28 +65,16 @@ final class DerbyEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigure properties.setPassword(""); } + @Override public void shutdown(DataSource dataSource, String databaseName) { - EmbeddedDriver embeddedDriver = new EmbeddedDriver(); - boolean isAtLeastDotSix = (embeddedDriver.getMinorVersion() >= 6); - String shutdownCommand = String.format("%s=true", isAtLeastDotSix ? "drop" : "shutdown"); try { - embeddedDriver.connect( - String.format(URL_TEMPLATE, databaseName, shutdownCommand), new Properties()); + new EmbeddedDriver().connect( + String.format(URL_TEMPLATE, databaseName, "drop=true"), new Properties()); } catch (SQLException ex) { - if (!SHUTDOWN_CODE.equals(ex.getSQLState())) { - logger.warn("Could not shutdown in-memory Derby database", ex); - return; - } - if (!isAtLeastDotSix) { - // Explicitly purge the in-memory database, to prevent it - // from hanging around after being shut down. - try { - VFMemoryStorageFactory.purgeDatabase(new File(databaseName).getCanonicalPath()); - } - catch (IOException ex2) { - logger.warn("Could not purge in-memory Derby database", ex2); - } + // Error code that indicates successful shutdown + if (!"08006".equals(ex.getSQLState())) { + LogFactory.getLog(getClass()).warn("Could not shutdown in-memory Derby database", ex); } } } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabase.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabase.java index 634fa5c8..6c5ad88f 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabase.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabase.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,11 +19,14 @@ package org.springframework.jdbc.datasource.embedded; import javax.sql.DataSource; /** - * A handle to an EmbeddedDatabase instance. - * Is a {@link DataSource}. - * Adds a shutdown operation so the embedded database instance can be shutdown. + * {@code EmbeddedDatabase} serves as a handle to an embedded database instance. + * + * <p>An {@code EmbeddedDatabase} is also a {@link DataSource} and adds a + * {@link #shutdown} operation so that the embedded database instance can be + * shutdown. * * @author Keith Donald + * @author Sam Brannen * @since 3.0 */ public interface EmbeddedDatabase extends DataSource { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilder.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilder.java index 7d78a51b..08ee1687 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilder.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilder.java @@ -16,17 +16,29 @@ package org.springframework.jdbc.datasource.embedded; +import javax.sql.DataSource; + import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.ResourceLoader; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; +import org.springframework.jdbc.datasource.init.ScriptUtils; +import org.springframework.util.Assert; /** * A builder that provides a convenient API for constructing an embedded database. * - * <p>Usage example: + * <h3>Usage Example</h3> * <pre class="code"> - * EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); - * EmbeddedDatabase db = builder.setType(H2).addScript("schema.sql").addScript("data.sql").build(); + * EmbeddedDatabase db = new EmbeddedDatabaseBuilder() + * .setType(H2) + * .setScriptEncoding("UTF-8") + * .ignoreFailedDrops(true) + * .addScript("schema.sql") + * .addScripts("user_data.sql", "country_data.sql") + * .build(); + * + * // ... + * * db.shutdown(); * </pre> * @@ -35,6 +47,9 @@ import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; * @author Dave Syer * @author Sam Brannen * @since 3.0 + * @see org.springframework.jdbc.datasource.init.ScriptUtils + * @see org.springframework.jdbc.datasource.init.ResourceDatabasePopulator + * @see org.springframework.jdbc.datasource.init.DatabasePopulatorUtils */ public class EmbeddedDatabaseBuilder { @@ -46,15 +61,15 @@ public class EmbeddedDatabaseBuilder { /** - * Create a new embedded database builder. + * Create a new embedded database builder with a {@link DefaultResourceLoader}. */ public EmbeddedDatabaseBuilder() { this(new DefaultResourceLoader()); } /** - * Create a new embedded database builder with the given ResourceLoader. - * @param resourceLoader the ResourceLoader to delegate to + * Create a new embedded database builder with the given {@link ResourceLoader}. + * @param resourceLoader the {@code ResourceLoader} to delegate to */ public EmbeddedDatabaseBuilder(ResourceLoader resourceLoader) { this.databaseFactory = new EmbeddedDatabaseFactory(); @@ -63,12 +78,12 @@ public class EmbeddedDatabaseBuilder { this.resourceLoader = resourceLoader; } - /** * Set the name of the embedded database. - * <p>Defaults to "testdb" if not called. - * @param databaseName the database name - * @return this, to facilitate method chaining + * <p>Defaults to {@link EmbeddedDatabaseFactory#DEFAULT_DATABASE_NAME} if + * not called. + * @param databaseName the name of the embedded database to build + * @return {@code this}, to facilitate method chaining */ public EmbeddedDatabaseBuilder setName(String databaseName) { this.databaseFactory.setDatabaseName(databaseName); @@ -78,8 +93,8 @@ public class EmbeddedDatabaseBuilder { /** * Set the type of embedded database. * <p>Defaults to HSQL if not called. - * @param databaseType the database type - * @return this, to facilitate method chaining + * @param databaseType the type of embedded database to build + * @return {@code this}, to facilitate method chaining */ public EmbeddedDatabaseBuilder setType(EmbeddedDatabaseType databaseType) { this.databaseFactory.setDatabaseType(databaseType); @@ -87,24 +102,144 @@ public class EmbeddedDatabaseBuilder { } /** - * Add a SQL script to execute to populate the database. - * @param sqlResource the sql resource location - * @return this, to facilitate method chaining + * Set the factory to use to create the {@link DataSource} instance that + * connects to the embedded database. + * <p>Defaults to {@link SimpleDriverDataSourceFactory} but can be overridden, + * for example to introduce connection pooling. + * @return {@code this}, to facilitate method chaining + * @since 4.0.3 */ - public EmbeddedDatabaseBuilder addScript(String sqlResource) { - this.databasePopulator.addScript(this.resourceLoader.getResource(sqlResource)); + public EmbeddedDatabaseBuilder setDataSourceFactory(DataSourceFactory dataSourceFactory) { + Assert.notNull(dataSourceFactory, "DataSourceFactory is required"); + this.databaseFactory.setDataSourceFactory(dataSourceFactory); return this; } /** - * Add default scripts to execute to populate the database. - * <p>The default scripts are {@code schema.sql} to create the db - * schema and {@code data.sql} to populate the db with data. - * @return this, to facilitate method chaining + * Add default SQL scripts to execute to populate the database. + * <p>The default scripts are {@code "schema.sql"} to create the database + * schema and {@code "data.sql"} to populate the database with data. + * @return {@code this}, to facilitate method chaining */ public EmbeddedDatabaseBuilder addDefaultScripts() { - addScript("schema.sql"); - addScript("data.sql"); + return addScripts("schema.sql", "data.sql"); + } + + /** + * Add an SQL script to execute to initialize or populate the database. + * @param script the script to execute + * @return {@code this}, to facilitate method chaining + */ + public EmbeddedDatabaseBuilder addScript(String script) { + this.databasePopulator.addScript(this.resourceLoader.getResource(script)); + return this; + } + + /** + * Add multiple SQL scripts to execute to initialize or populate the database. + * @param scripts the scripts to execute + * @return {@code this}, to facilitate method chaining + * @since 4.0.3 + */ + public EmbeddedDatabaseBuilder addScripts(String... scripts) { + for (String script : scripts) { + addScript(script); + } + return this; + } + + /** + * Specify the character encoding used in all SQL scripts, if different from + * the platform encoding. + * @param scriptEncoding the encoding used in scripts + * @return {@code this}, to facilitate method chaining + * @since 4.0.3 + */ + public EmbeddedDatabaseBuilder setScriptEncoding(String scriptEncoding) { + this.databasePopulator.setSqlScriptEncoding(scriptEncoding); + return this; + } + + /** + * Specify the statement separator used in all SQL scripts, if a custom one. + * <p>Defaults to {@code ";"} if not specified and falls back to {@code "\n"} + * as a last resort; may be set to {@link ScriptUtils#EOF_STATEMENT_SEPARATOR} + * to signal that each script contains a single statement without a separator. + * @param separator the statement separator + * @return {@code this}, to facilitate method chaining + * @since 4.0.3 + */ + public EmbeddedDatabaseBuilder setSeparator(String separator) { + this.databasePopulator.setSeparator(separator); + return this; + } + + /** + * Specify the single-line comment prefix used in all SQL scripts. + * <p>Defaults to {@code "--"}. + * @param commentPrefix the prefix for single-line comments + * @return {@code this}, to facilitate method chaining + * @since 4.0.3 + */ + public EmbeddedDatabaseBuilder setCommentPrefix(String commentPrefix) { + this.databasePopulator.setCommentPrefix(commentPrefix); + return this; + } + + /** + * Specify the start delimiter for block comments in all SQL scripts. + * <p>Defaults to {@code "/*"}. + * @param blockCommentStartDelimiter the start delimiter for block comments + * @return {@code this}, to facilitate method chaining + * @since 4.0.3 + * @see #setBlockCommentEndDelimiter + * @since 4.0.3 + */ + public EmbeddedDatabaseBuilder setBlockCommentStartDelimiter(String blockCommentStartDelimiter) { + this.databasePopulator.setBlockCommentStartDelimiter(blockCommentStartDelimiter); + return this; + } + + /** + * Specify the end delimiter for block comments in all SQL scripts. + * <p>Defaults to <code>"*/"</code>. + * @param blockCommentEndDelimiter the end delimiter for block comments + * @return {@code this}, to facilitate method chaining + * @since 4.0.3 + * @see #setBlockCommentStartDelimiter + * @since 4.0.3 + */ + public EmbeddedDatabaseBuilder setBlockCommentEndDelimiter(String blockCommentEndDelimiter) { + this.databasePopulator.setBlockCommentEndDelimiter(blockCommentEndDelimiter); + return this; + } + + /** + * Specify that all failures which occur while executing SQL scripts should + * be logged but should not cause a failure. + * <p>Defaults to {@code false}. + * @param flag {@code true} if script execution should continue on error + * @return {@code this}, to facilitate method chaining + * @since 4.0.3 + */ + public EmbeddedDatabaseBuilder continueOnError(boolean flag) { + this.databasePopulator.setContinueOnError(flag); + return this; + } + + /** + * Specify that a failed SQL {@code DROP} statement within an executed + * script can be ignored. + * <p>This is useful for a database whose SQL dialect does not support an + * {@code IF EXISTS} clause in a {@code DROP} statement. + * <p>The default is {@code false} so that {@link #build building} will fail + * fast if a script starts with a {@code DROP} statement. + * @param flag {@code true} if failed drop statements should be ignored + * @return {@code this}, to facilitate method chaining + * @since 4.0.3 + */ + public EmbeddedDatabaseBuilder ignoreFailedDrops(boolean flag) { + this.databasePopulator.setIgnoreFailedDrops(flag); return this; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseConfigurer.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseConfigurer.java index 73d54ca4..d6328ff1 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseConfigurer.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,23 +19,28 @@ package org.springframework.jdbc.datasource.embedded; import javax.sql.DataSource; /** - * Encapsulates the configuration required to create, connect to, and shutdown a specific type of embedded database such as HSQL or H2. - * Create a implementation for each database type you wish to support; for example HSQL, H2, or some other type. + * {@code EmbeddedDatabaseConfigurer} encapsulates the configuration required to + * create, connect to, and shutdown a specific type of embedded database such as + * HSQL or H2. + * <p>Create an implementation for each database type you wish to support; for + * example HSQL, H2, or some other type. * * @author Keith Donald + * @author Sam Brannen * @since 3.0 */ public interface EmbeddedDatabaseConfigurer { /** - * Configure the properties required to create and connect to the embedded database instance. + * Configure the properties required to create and connect to the embedded + * database instance. * @param properties connection properties to configure - * @param databaseName the name of the test database + * @param databaseName the name of the embedded database */ void configureConnectionProperties(ConnectionProperties properties, String databaseName); /** - * Shutdown the embedded database instance that backs dataSource. + * Shutdown the embedded database instance that backs the supplied {@link DataSource}. * @param dataSource the data source * @param databaseName the name of the database being shutdown */ diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseConfigurerFactory.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseConfigurerFactory.java index 8719cc8a..1ceda5b4 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseConfigurerFactory.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseConfigurerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,11 +19,12 @@ package org.springframework.jdbc.datasource.embedded; import org.springframework.util.Assert; /** - * Maps well-known {@link EmbeddedDatabaseType embedded database types} to + * Maps well-known {@linkplain EmbeddedDatabaseType embedded database types} to * {@link EmbeddedDatabaseConfigurer} strategies. * * @author Keith Donald * @author Oliver Gierke + * @author Sam Brannen * @since 3.0 */ final class EmbeddedDatabaseConfigurerFactory { @@ -39,7 +40,7 @@ final class EmbeddedDatabaseConfigurerFactory { case DERBY: return DerbyEmbeddedDatabaseConfigurer.getInstance(); default: - throw new UnsupportedOperationException("Other embedded database types not yet supported"); + throw new UnsupportedOperationException("Embedded database type [" + type + "] is not supported"); } } catch (ClassNotFoundException ex) { @@ -49,6 +50,7 @@ final class EmbeddedDatabaseConfigurerFactory { } private EmbeddedDatabaseConfigurerFactory() { + /* no-op */ } } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactory.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactory.java index e9b9559d..9ce946ee 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactory.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactory.java @@ -199,43 +199,53 @@ public class EmbeddedDatabaseFactory { this.dataSource = dataSource; } + @Override public Connection getConnection() throws SQLException { return this.dataSource.getConnection(); } + @Override public Connection getConnection(String username, String password) throws SQLException { return this.dataSource.getConnection(username, password); } + @Override public PrintWriter getLogWriter() throws SQLException { return this.dataSource.getLogWriter(); } + @Override public void setLogWriter(PrintWriter out) throws SQLException { this.dataSource.setLogWriter(out); } + @Override public int getLoginTimeout() throws SQLException { return this.dataSource.getLoginTimeout(); } + @Override public void setLoginTimeout(int seconds) throws SQLException { this.dataSource.setLoginTimeout(seconds); } + @Override public <T> T unwrap(Class<T> iface) throws SQLException { return this.dataSource.unwrap(iface); } + @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { return this.dataSource.isWrapperFor(iface); } // getParentLogger() is required for JDBC 4.1 compatibility + @Override public Logger getParentLogger() { return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); } + @Override public void shutdown() { shutdownDatabase(); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryBean.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryBean.java index a58d84a7..1b28b871 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryBean.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,13 +25,16 @@ import org.springframework.jdbc.datasource.init.DatabasePopulator; import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils; /** - * A subclass of {@link EmbeddedDatabaseFactory} that implements {@link FactoryBean} for registration as a Spring bean. - * Returns the actual {@link DataSource} that provides connectivity to the embedded database to Spring. + * A subclass of {@link EmbeddedDatabaseFactory} that implements {@link FactoryBean} + * for registration as a Spring bean. Returns the actual {@link DataSource} that + * provides connectivity to the embedded database to Spring. * - * <p>The target DataSource is returned instead of a {@link EmbeddedDatabase} proxy since the FactoryBean - * will manage the initialization and destruction lifecycle of the database instance. + * <p>The target {@link DataSource} is returned instead of an {@link EmbeddedDatabase} + * proxy since the {@link FactoryBean} will manage the initialization and destruction + * lifecycle of the embedded database instance. * - * <p>Implements DisposableBean to shutdown the embedded database when the managing Spring container is shutdown. + * <p>Implements {@link DisposableBean} to shutdown the embedded database when the + * managing Spring container is being closed. * * @author Keith Donald * @author Juergen Hoeller @@ -54,28 +57,34 @@ public class EmbeddedDatabaseFactoryBean extends EmbeddedDatabaseFactory this.databaseCleaner = databaseCleaner; } + @Override public void afterPropertiesSet() { initDatabase(); } - public void destroy() { - if (this.databaseCleaner != null) { - DatabasePopulatorUtils.execute(this.databaseCleaner, getDataSource()); - } - shutdownDatabase(); - } - + @Override public DataSource getObject() { return getDataSource(); } + @Override public Class<? extends DataSource> getObjectType() { return DataSource.class; } + @Override public boolean isSingleton() { return true; } + + @Override + public void destroy() { + if (this.databaseCleaner != null) { + DatabasePopulatorUtils.execute(this.databaseCleaner, getDataSource()); + } + shutdownDatabase(); + } + } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/H2EmbeddedDatabaseConfigurer.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/H2EmbeddedDatabaseConfigurer.java index d7fc50bf..57c6000a 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/H2EmbeddedDatabaseConfigurer.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/H2EmbeddedDatabaseConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,40 +21,44 @@ import java.sql.Driver; import org.springframework.util.ClassUtils; /** - * Initializes an H2 embedded database instance. - * Call {@link #getInstance()} to get the singleton instance of this class. + * {@link EmbeddedDatabaseConfigurer} for an H2 embedded database instance. + * <p>Call {@link #getInstance()} to get the singleton instance of this class. * * @author Oliver Gierke * @author Juergen Hoeller + * @author Sam Brannen * @since 3.0 */ final class H2EmbeddedDatabaseConfigurer extends AbstractEmbeddedDatabaseConfigurer { - private static H2EmbeddedDatabaseConfigurer INSTANCE; + private static H2EmbeddedDatabaseConfigurer instance; private final Class<? extends Driver> driverClass; + /** - * Get the singleton {@link H2EmbeddedDatabaseConfigurer} instance. + * Get the singleton {@code H2EmbeddedDatabaseConfigurer} instance. * @return the configurer * @throws ClassNotFoundException if H2 is not on the classpath */ @SuppressWarnings("unchecked") public static synchronized H2EmbeddedDatabaseConfigurer getInstance() throws ClassNotFoundException { - if (INSTANCE == null) { - INSTANCE = new H2EmbeddedDatabaseConfigurer( - (Class<? extends Driver>) ClassUtils.forName("org.h2.Driver", H2EmbeddedDatabaseConfigurer.class.getClassLoader())); + if (instance == null) { + instance = new H2EmbeddedDatabaseConfigurer( (Class<? extends Driver>) + ClassUtils.forName("org.h2.Driver", H2EmbeddedDatabaseConfigurer.class.getClassLoader())); } - return INSTANCE; + return instance; } + private H2EmbeddedDatabaseConfigurer(Class<? extends Driver> driverClass) { this.driverClass = driverClass; } + @Override public void configureConnectionProperties(ConnectionProperties properties, String databaseName) { properties.setDriverClass(this.driverClass); - properties.setUrl(String.format("jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1", databaseName)); + properties.setUrl(String.format("jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false", databaseName)); properties.setUsername("sa"); properties.setPassword(""); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/HsqlEmbeddedDatabaseConfigurer.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/HsqlEmbeddedDatabaseConfigurer.java index 07670934..89f37f2d 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/HsqlEmbeddedDatabaseConfigurer.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/HsqlEmbeddedDatabaseConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,8 +21,8 @@ import java.sql.Driver; import org.springframework.util.ClassUtils; /** - * Initializes an HSQL embedded database instance. - * Call {@link #getInstance()} to get the singleton instance of this class. + * {@link EmbeddedDatabaseConfigurer} for an HSQL embedded database instance. + * <p>Call {@link #getInstance()} to get the singleton instance of this class. * * @author Keith Donald * @author Oliver Gierke @@ -30,10 +30,11 @@ import org.springframework.util.ClassUtils; */ final class HsqlEmbeddedDatabaseConfigurer extends AbstractEmbeddedDatabaseConfigurer { - private static HsqlEmbeddedDatabaseConfigurer INSTANCE; + private static HsqlEmbeddedDatabaseConfigurer instance; private final Class<? extends Driver> driverClass; + /** * Get the singleton {@link HsqlEmbeddedDatabaseConfigurer} instance. * @return the configurer @@ -41,17 +42,19 @@ final class HsqlEmbeddedDatabaseConfigurer extends AbstractEmbeddedDatabaseConfi */ @SuppressWarnings("unchecked") public static synchronized HsqlEmbeddedDatabaseConfigurer getInstance() throws ClassNotFoundException { - if (INSTANCE == null) { - INSTANCE = new HsqlEmbeddedDatabaseConfigurer( - (Class<? extends Driver>) ClassUtils.forName("org.hsqldb.jdbcDriver", HsqlEmbeddedDatabaseConfigurer.class.getClassLoader())); + if (instance == null) { + instance = new HsqlEmbeddedDatabaseConfigurer( (Class<? extends Driver>) + ClassUtils.forName("org.hsqldb.jdbcDriver", HsqlEmbeddedDatabaseConfigurer.class.getClassLoader())); } - return INSTANCE; + return instance; } + private HsqlEmbeddedDatabaseConfigurer(Class<? extends Driver> driverClass) { this.driverClass = driverClass; } + @Override public void configureConnectionProperties(ConnectionProperties properties, String databaseName) { properties.setDriverClass(this.driverClass); properties.setUrl("jdbc:hsqldb:mem:" + databaseName); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/OutputStreamFactory.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/OutputStreamFactory.java index 848501e7..964c3b33 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/OutputStreamFactory.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/OutputStreamFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,6 +33,7 @@ public class OutputStreamFactory { */ public static OutputStream getNoopOutputStream() { return new OutputStream() { + @Override public void write(int b) throws IOException { // ignore the output } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/SimpleDriverDataSourceFactory.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/SimpleDriverDataSourceFactory.java index 58b17672..309d7765 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/SimpleDriverDataSourceFactory.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/SimpleDriverDataSourceFactory.java @@ -33,26 +33,32 @@ final class SimpleDriverDataSourceFactory implements DataSourceFactory { private final SimpleDriverDataSource dataSource = new SimpleDriverDataSource(); + @Override public ConnectionProperties getConnectionProperties() { return new ConnectionProperties() { + @Override public void setDriverClass(Class<? extends Driver> driverClass) { dataSource.setDriverClass(driverClass); } + @Override public void setUrl(String url) { dataSource.setUrl(url); } + @Override public void setUsername(String username) { dataSource.setUsername(username); } + @Override public void setPassword(String password) { dataSource.setPassword(password); } }; } + @Override public DataSource getDataSource() { return this.dataSource; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/CannotReadScriptException.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/CannotReadScriptException.java index 93388def..7ab5b198 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/CannotReadScriptException.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/CannotReadScriptException.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,14 +19,14 @@ package org.springframework.jdbc.datasource.init; import org.springframework.core.io.support.EncodedResource; /** - * Thrown by {@link ResourceDatabasePopulator} if one of its SQL scripts cannot - * be read during population. + * Thrown by {@link ScriptUtils} if an SQL script cannot be read. * * @author Keith Donald + * @author Sam Brannen * @since 3.0 */ @SuppressWarnings("serial") -public class CannotReadScriptException extends RuntimeException { +public class CannotReadScriptException extends ScriptException { /** * Construct a new {@code CannotReadScriptException}. diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/CompositeDatabasePopulator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/CompositeDatabasePopulator.java index 143317b6..16c7b8e0 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/CompositeDatabasePopulator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/CompositeDatabasePopulator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,20 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.jdbc.datasource.init; import java.sql.Connection; import java.sql.SQLException; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * {@link DatabasePopulator} implementation that delegates to a list of other - * DatabasePopulator implementations, executing all scripts. + * {@code DatabasePopulator} implementations, executing all scripts. * * @author Dave Syer * @author Juergen Hoeller + * @author Sam Brannen * @since 3.1 */ public class CompositeDatabasePopulator implements DatabasePopulator { @@ -43,14 +46,17 @@ public class CompositeDatabasePopulator implements DatabasePopulator { } /** - * Add a populator to the list of delegates. + * Add one or more populators to the list of delegates. */ public void addPopulators(DatabasePopulator... populators) { this.populators.addAll(Arrays.asList(populators)); } - - public void populate(Connection connection) throws SQLException { + /** + * {@inheritDoc} + */ + @Override + public void populate(Connection connection) throws SQLException, ScriptException { for (DatabasePopulator populator : this.populators) { populator.populate(connection); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DataSourceInitializer.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DataSourceInitializer.java index 96f795ca..574c1ae5 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DataSourceInitializer.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DataSourceInitializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,11 +20,15 @@ import javax.sql.DataSource; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; /** - * Used to populate a database during initialization. + * Used to {@linkplain #setDatabasePopulator set up} a database during + * initialization and {@link #setDatabaseCleaner clean up} a database during + * destruction. * * @author Dave Syer + * @author Sam Brannen * @since 3.0 * @see DatabasePopulator */ @@ -40,8 +44,9 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean { /** - * The {@link DataSource} to populate when this component is initialized. - * Mandatory with no default. + * The {@link DataSource} for the database to populate when this component + * is initialized and to clean up when this component is shut down. + * <p>This property is mandatory with no default provided. * @param dataSource the DataSource */ public void setDataSource(DataSource dataSource) { @@ -49,47 +54,58 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean { } /** - * The {@link DatabasePopulator} to use to populate the data source. - * Mandatory with no default. - * @param databasePopulator the database populator to use. + * Set the {@link DatabasePopulator} to execute during the bean initialization + * phase. + * @param databasePopulator the {@code DatabasePopulator} to use during + * initialization + * @see #setDatabaseCleaner */ public void setDatabasePopulator(DatabasePopulator databasePopulator) { this.databasePopulator = databasePopulator; } /** - * Set a script execution to be run in the bean destruction callback, - * cleaning up the database and leaving it in a known state for others. - * @param databaseCleaner the database script executor to run on destroy + * Set the {@link DatabasePopulator} to execute during the bean destruction + * phase, cleaning up the database and leaving it in a known state for others. + * @param databaseCleaner the {@code DatabasePopulator} to use during destruction + * @see #setDatabasePopulator */ public void setDatabaseCleaner(DatabasePopulator databaseCleaner) { this.databaseCleaner = databaseCleaner; } /** - * Flag to explicitly enable or disable the database populator. - * @param enabled true if the database populator will be called on startup + * Flag to explicitly enable or disable the {@linkplain #setDatabasePopulator + * database populator} and {@linkplain #setDatabaseCleaner database cleaner}. + * @param enabled {@code true} if the database populator and database cleaner + * should be called on startup and shutdown, respectively */ public void setEnabled(boolean enabled) { this.enabled = enabled; } - /** - * Use the populator to set up data in the data source. + * Use the {@linkplain #setDatabasePopulator database populator} to set up + * the database. */ + @Override public void afterPropertiesSet() { - if (this.databasePopulator != null && this.enabled) { - DatabasePopulatorUtils.execute(this.databasePopulator, this.dataSource); - } + execute(this.databasePopulator); } /** - * Use the populator to clean up data in the data source. + * Use the {@linkplain #setDatabaseCleaner database cleaner} to clean up the + * database. */ + @Override public void destroy() { - if (this.databaseCleaner != null && this.enabled) { - DatabasePopulatorUtils.execute(this.databaseCleaner, this.dataSource); + execute(this.databaseCleaner); + } + + private void execute(DatabasePopulator populator) { + Assert.state(dataSource != null, "DataSource must be set"); + if (this.enabled && populator != null) { + DatabasePopulatorUtils.execute(populator, this.dataSource); } } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulator.java index 52cdd430..b6b9f2d2 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,19 +20,32 @@ import java.sql.Connection; import java.sql.SQLException; /** - * Strategy used to populate a database during initialization. + * Strategy used to populate, initialize, or clean up a database. * * @author Keith Donald + * @author Sam Brannen * @since 3.0 * @see ResourceDatabasePopulator + * @see DatabasePopulatorUtils + * @see DataSourceInitializer */ public interface DatabasePopulator { /** - * Populate the database using the JDBC connection provided. - * @param connection the JDBC connection to use to populate the db; already configured and ready to use - * @throws SQLException if an unrecoverable data access exception occurs during database population + * Populate, initialize, or clean up the database using the provided JDBC + * connection. + * <p>Concrete implementations <em>may</em> throw an {@link SQLException} if + * an error is encountered but are <em>strongly encouraged</em> to throw a + * specific {@link ScriptException} instead. For example, Spring's + * {@link ResourceDatabasePopulator} and {@link DatabasePopulatorUtils} wrap + * all {@code SQLExceptions} in {@code ScriptExceptions}. + * @param connection the JDBC connection to use to populate the db; already + * configured and ready to use + * @throws SQLException if an unrecoverable data access exception occurs + * during database population + * @throws ScriptException in all other error cases + * @see DatabasePopulatorUtils#execute */ - void populate(Connection connection) throws SQLException; + void populate(Connection connection) throws SQLException, ScriptException; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulatorUtils.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulatorUtils.java index 1f046d07..898c6a39 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulatorUtils.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulatorUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,25 +20,27 @@ import java.sql.Connection; import javax.sql.DataSource; -import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.dao.DataAccessException; import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.util.Assert; /** - * Utility methods for executing a DatabasePopulator. + * Utility methods for executing a {@link DatabasePopulator}. * * @author Juergen Hoeller * @author Oliver Gierke + * @author Sam Brannen * @since 3.1 */ public abstract class DatabasePopulatorUtils { /** - * Execute the given DatabasePopulator against the given DataSource. - * @param populator the DatabasePopulator to execute - * @param dataSource the DataSource to execute against + * Execute the given {@link DatabasePopulator} against the given {@link DataSource}. + * @param populator the {@code DatabasePopulator} to execute + * @param dataSource the {@code DataSource} to execute against + * @throws DataAccessException if an error occurs, specifically a {@link ScriptException} */ - public static void execute(DatabasePopulator populator, DataSource dataSource) { + public static void execute(DatabasePopulator populator, DataSource dataSource) throws DataAccessException { Assert.notNull(populator, "DatabasePopulator must be provided"); Assert.notNull(dataSource, "DataSource must be provided"); try { @@ -53,7 +55,11 @@ public abstract class DatabasePopulatorUtils { } } catch (Exception ex) { - throw new DataAccessResourceFailureException("Failed to execute database script", ex); + if (ex instanceof ScriptException) { + throw (ScriptException) ex; + } + + throw new UncategorizedScriptException("Failed to execute database script", ex); } } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ResourceDatabasePopulator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ResourceDatabasePopulator.java index 1b44edf2..23082390 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ResourceDatabasePopulator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ResourceDatabasePopulator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,28 +16,22 @@ package org.springframework.jdbc.datasource.init; -import java.io.IOException; -import java.io.LineNumberReader; import java.sql.Connection; -import java.sql.SQLException; -import java.sql.Statement; import java.util.ArrayList; import java.util.Arrays; -import java.util.LinkedList; import java.util.List; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - import org.springframework.core.io.Resource; import org.springframework.core.io.support.EncodedResource; -import org.springframework.util.StringUtils; /** - * Populates a database from SQL scripts defined in external resources. + * Populates or initializes a database from SQL scripts defined in external + * resources. * - * <p>Call {@link #addScript(Resource)} to add a SQL script location. - * Call {@link #setSqlScriptEncoding(String)} to set the encoding for all added scripts. + * <p>Call {@link #addScript(Resource)} to add a single SQL script location. + * Call {@link #addScripts(Resource...)} to add multiple SQL script locations. + * Call {@link #setSqlScriptEncoding(String)} to set the encoding for all added + * scripts. * * @author Keith Donald * @author Dave Syer @@ -45,24 +39,23 @@ import org.springframework.util.StringUtils; * @author Chris Beams * @author Oliver Gierke * @author Sam Brannen + * @author Chris Baldwin * @since 3.0 + * @see DatabasePopulatorUtils */ public class ResourceDatabasePopulator implements DatabasePopulator { - private static final String DEFAULT_COMMENT_PREFIX = "--"; - - private static final String DEFAULT_STATEMENT_SEPARATOR = ";"; - - private static final Log logger = LogFactory.getLog(ResourceDatabasePopulator.class); - - private List<Resource> scripts = new ArrayList<Resource>(); private String sqlScriptEncoding; - private String separator; + private String separator = ScriptUtils.DEFAULT_STATEMENT_SEPARATOR; - private String commentPrefix = DEFAULT_COMMENT_PREFIX; + private String commentPrefix = ScriptUtils.DEFAULT_COMMENT_PREFIX; + + private String blockCommentStartDelimiter = ScriptUtils.DEFAULT_BLOCK_COMMENT_START_DELIMITER; + + private String blockCommentEndDelimiter = ScriptUtils.DEFAULT_BLOCK_COMMENT_END_DELIMITER; private boolean continueOnError = false; @@ -70,15 +63,62 @@ public class ResourceDatabasePopulator implements DatabasePopulator { /** - * Add a script to execute to populate the database. - * @param script the path to a SQL script + * Construct a new {@code ResourceDatabasePopulator} with default settings. + * @since 4.0.3 + */ + public ResourceDatabasePopulator() { + /* no-op */ + } + + /** + * Construct a new {@code ResourceDatabasePopulator} with default settings + * for the supplied scripts. + * @param scripts the scripts to execute to initialize or populate the database + * @since 4.0.3 + */ + public ResourceDatabasePopulator(Resource... scripts) { + this(); + this.scripts = Arrays.asList(scripts); + } + + /** + * Construct a new {@code ResourceDatabasePopulator} with the supplied values. + * @param continueOnError flag to indicate that all failures in SQL should be + * logged but not cause a failure + * @param ignoreFailedDrops flag to indicate that a failed SQL {@code DROP} + * statement can be ignored + * @param sqlScriptEncoding the encoding for the supplied SQL scripts, if + * different from the platform encoding; may be {@code null} + * @param scripts the scripts to execute to initialize or populate the database + * @since 4.0.3 + */ + public ResourceDatabasePopulator(boolean continueOnError, boolean ignoreFailedDrops, String sqlScriptEncoding, + Resource... scripts) { + this(scripts); + this.continueOnError = continueOnError; + this.ignoreFailedDrops = ignoreFailedDrops; + this.sqlScriptEncoding = sqlScriptEncoding; + } + + /** + * Add a script to execute to initialize or populate the database. + * @param script the path to an SQL script */ public void addScript(Resource script) { this.scripts.add(script); } /** - * Set the scripts to execute to populate the database. + * Add multiple scripts to execute to initialize or populate the database. + * @param scripts the scripts to execute + */ + public void addScripts(Resource... scripts) { + this.scripts.addAll(Arrays.asList(scripts)); + } + + /** + * Set the scripts to execute to initialize or populate the database, + * replacing any previously added scripts. * @param scripts the scripts to execute */ public void setScripts(Resource... scripts) { @@ -87,8 +127,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator { /** * Specify the encoding for SQL scripts, if different from the platform encoding. - * Note setting this property has no effect on added scripts that are already - * {@link EncodedResource encoded resources}. + * @param sqlScriptEncoding the encoding used in scripts * @see #addScript(Resource) */ public void setSqlScriptEncoding(String sqlScriptEncoding) { @@ -96,261 +135,88 @@ public class ResourceDatabasePopulator implements DatabasePopulator { } /** - * Specify the statement separator, if a custom one. Default is ";". + * Specify the statement separator, if a custom one. + * <p>Defaults to {@code ";"} if not specified and falls back to {@code "\n"} + * as a last resort; may be set to {@link ScriptUtils#EOF_STATEMENT_SEPARATOR} + * to signal that each script contains a single statement without a separator. + * @param separator the script statement separator */ public void setSeparator(String separator) { this.separator = separator; } /** - * Set the line prefix that identifies comments in the SQL script. - * Default is "--". + * Set the prefix that identifies single-line comments within the SQL scripts. + * <p>Defaults to {@code "--"}. + * @param commentPrefix the prefix for single-line comments */ public void setCommentPrefix(String commentPrefix) { this.commentPrefix = commentPrefix; } /** - * Flag to indicate that all failures in SQL should be logged but not cause a failure. - * Defaults to false. + * Set the start delimiter that identifies block comments within the SQL + * scripts. + * <p>Defaults to {@code "/*"}. + * @param blockCommentStartDelimiter the start delimiter for block comments + * @since 4.0.3 + * @see #setBlockCommentEndDelimiter */ - public void setContinueOnError(boolean continueOnError) { - this.continueOnError = continueOnError; + public void setBlockCommentStartDelimiter(String blockCommentStartDelimiter) { + this.blockCommentStartDelimiter = blockCommentStartDelimiter; } /** - * Flag to indicate that a failed SQL {@code DROP} statement can be ignored. - * <p>This is useful for non-embedded databases whose SQL dialect does not support an - * {@code IF EXISTS} clause in a {@code DROP}. The default is false so that if the - * populator runs accidentally, it will fail fast when the script starts with a {@code DROP}. + * Set the end delimiter that identifies block comments within the SQL + * scripts. + * <p>Defaults to <code>"*/"</code>. + * @param blockCommentEndDelimiter the end delimiter for block comments + * @since 4.0.3 + * @see #setBlockCommentStartDelimiter */ - public void setIgnoreFailedDrops(boolean ignoreFailedDrops) { - this.ignoreFailedDrops = ignoreFailedDrops; - } - - - public void populate(Connection connection) throws SQLException { - for (Resource script : this.scripts) { - executeSqlScript(connection, applyEncodingIfNecessary(script), this.continueOnError, this.ignoreFailedDrops); - } - } - - private EncodedResource applyEncodingIfNecessary(Resource script) { - if (script instanceof EncodedResource) { - return (EncodedResource) script; - } - else { - return new EncodedResource(script, this.sqlScriptEncoding); - } + public void setBlockCommentEndDelimiter(String blockCommentEndDelimiter) { + this.blockCommentEndDelimiter = blockCommentEndDelimiter; } /** - * Execute the given SQL script. - * <p>The script will normally be loaded by classpath. There should be one statement - * per line. Any {@link #setSeparator(String) statement separators} will be removed. - * <p><b>Do not use this method to execute DDL if you expect rollback.</b> - * @param connection the JDBC Connection with which to perform JDBC operations - * @param resource the resource (potentially associated with a specific encoding) to load the SQL script from - * @param continueOnError whether or not to continue without throwing an exception in the event of an error - * @param ignoreFailedDrops whether of not to continue in the event of specifically an error on a {@code DROP} + * Flag to indicate that all failures in SQL should be logged but not cause a failure. + * <p>Defaults to {@code false}. + * @param continueOnError {@code true} if script execution should continue on error */ - private void executeSqlScript(Connection connection, EncodedResource resource, boolean continueOnError, - boolean ignoreFailedDrops) throws SQLException { - - if (logger.isInfoEnabled()) { - logger.info("Executing SQL script from " + resource); - } - long startTime = System.currentTimeMillis(); - List<String> statements = new LinkedList<String>(); - String script; - try { - script = readScript(resource); - } - catch (IOException ex) { - throw new CannotReadScriptException(resource, ex); - } - String delimiter = this.separator; - if (delimiter == null) { - delimiter = DEFAULT_STATEMENT_SEPARATOR; - if (!containsSqlScriptDelimiters(script, delimiter)) { - delimiter = "\n"; - } - } - splitSqlScript(script, delimiter, this.commentPrefix, statements); - int lineNumber = 0; - Statement stmt = connection.createStatement(); - try { - for (String statement : statements) { - lineNumber++; - try { - stmt.execute(statement); - int rowsAffected = stmt.getUpdateCount(); - if (logger.isDebugEnabled()) { - logger.debug(rowsAffected + " returned as updateCount for SQL: " + statement); - } - } - catch (SQLException ex) { - boolean dropStatement = StringUtils.startsWithIgnoreCase(statement.trim(), "drop"); - if (continueOnError || (dropStatement && ignoreFailedDrops)) { - if (logger.isDebugEnabled()) { - logger.debug("Failed to execute SQL script statement at line " + lineNumber + - " of resource " + resource + ": " + statement, ex); - } - } - else { - throw new ScriptStatementFailedException(statement, lineNumber, resource, ex); - } - } - } - } - finally { - try { - stmt.close(); - } - catch (Throwable ex) { - logger.debug("Could not close JDBC Statement", ex); - } - } - long elapsedTime = System.currentTimeMillis() - startTime; - if (logger.isInfoEnabled()) { - logger.info("Done executing SQL script from " + resource + " in " + elapsedTime + " ms."); - } + public void setContinueOnError(boolean continueOnError) { + this.continueOnError = continueOnError; } /** - * Read a script from the given resource and build a String containing the lines. - * @param resource the resource to be read - * @return {@code String} containing the script lines - * @throws IOException in case of I/O errors + * Flag to indicate that a failed SQL {@code DROP} statement can be ignored. + * <p>This is useful for non-embedded databases whose SQL dialect does not support an + * {@code IF EXISTS} clause in a {@code DROP} statement. + * <p>The default is {@code false} so that if the populator runs accidentally, it will + * fail fast if the script starts with a {@code DROP} statement. + * @param ignoreFailedDrops {@code true} if failed drop statements should be ignored */ - private String readScript(EncodedResource resource) throws IOException { - LineNumberReader lnr = new LineNumberReader(resource.getReader()); - try { - String currentStatement = lnr.readLine(); - StringBuilder scriptBuilder = new StringBuilder(); - while (currentStatement != null) { - if (StringUtils.hasText(currentStatement) && - (this.commentPrefix != null && !currentStatement.startsWith(this.commentPrefix))) { - if (scriptBuilder.length() > 0) { - scriptBuilder.append('\n'); - } - scriptBuilder.append(currentStatement); - } - currentStatement = lnr.readLine(); - } - maybeAddSeparatorToScript(scriptBuilder); - return scriptBuilder.toString(); - } - finally { - lnr.close(); - } - } - - private void maybeAddSeparatorToScript(StringBuilder scriptBuilder) { - if (this.separator == null) { - return; - } - String trimmed = this.separator.trim(); - if (trimmed.length() == this.separator.length()) { - return; - } - // separator ends in whitespace, so we might want to see if the script is trying - // to end the same way - if (scriptBuilder.lastIndexOf(trimmed) == scriptBuilder.length() - trimmed.length()) { - scriptBuilder.append(this.separator.substring(trimmed.length())); - } + public void setIgnoreFailedDrops(boolean ignoreFailedDrops) { + this.ignoreFailedDrops = ignoreFailedDrops; } /** - * Does the provided SQL script contain the specified delimiter? - * @param script the SQL script - * @param delim character delimiting each statement - typically a ';' character + * {@inheritDoc} */ - private boolean containsSqlScriptDelimiters(String script, String delim) { - boolean inLiteral = false; - char[] content = script.toCharArray(); - for (int i = 0; i < script.length(); i++) { - if (content[i] == '\'') { - inLiteral = !inLiteral; - } - if (!inLiteral && script.startsWith(delim, i)) { - return true; - } + @Override + public void populate(Connection connection) throws ScriptException { + for (Resource script : this.scripts) { + ScriptUtils.executeSqlScript(connection, encodeScript(script), this.continueOnError, + this.ignoreFailedDrops, this.commentPrefix, this.separator, this.blockCommentStartDelimiter, + this.blockCommentEndDelimiter); } - return false; } /** - * Split an SQL script into separate statements delimited by the provided delimiter - * string. Each individual statement will be added to the provided {@code List}. - * <p>Within a statement, the provided {@code commentPrefix} will be honored; - * any text beginning with the comment prefix and extending to the end of the - * line will be omitted from the statement. In addition, multiple adjacent - * whitespace characters will be collapsed into a single space. - * @param script the SQL script - * @param delim character delimiting each statement (typically a ';' character) - * @param commentPrefix the prefix that identifies line comments in the SQL script — typically "--" - * @param statements the List that will contain the individual statements + * {@link EncodedResource} is not a sub-type of {@link Resource}. Thus we + * always need to wrap each script resource in an encoded resource. */ - private void splitSqlScript(String script, String delim, String commentPrefix, List<String> statements) { - StringBuilder sb = new StringBuilder(); - boolean inLiteral = false; - boolean inEscape = false; - char[] content = script.toCharArray(); - for (int i = 0; i < script.length(); i++) { - char c = content[i]; - if (inEscape) { - inEscape = false; - sb.append(c); - continue; - } - // MySQL style escapes - if (c == '\\') { - inEscape = true; - sb.append(c); - continue; - } - if (c == '\'') { - inLiteral = !inLiteral; - } - if (!inLiteral) { - if (script.startsWith(delim, i)) { - // we've reached the end of the current statement - if (sb.length() > 0) { - statements.add(sb.toString()); - sb = new StringBuilder(); - } - i += delim.length() - 1; - continue; - } - else if (script.startsWith(commentPrefix, i)) { - // skip over any content from the start of the comment to the EOL - int indexOfNextNewline = script.indexOf("\n", i); - if (indexOfNextNewline > i) { - i = indexOfNextNewline; - continue; - } - else { - // if there's no newline after the comment, we must be at the end - // of the script, so stop here. - break; - } - } - else if (c == ' ' || c == '\n' || c == '\t') { - // avoid multiple adjacent whitespace characters - if (sb.length() > 0 && sb.charAt(sb.length() - 1) != ' ') { - c = ' '; - } - else { - continue; - } - } - } - sb.append(c); - } - if (StringUtils.hasText(sb)) { - statements.add(sb.toString()); - } + private EncodedResource encodeScript(Resource script) { + return new EncodedResource(script, this.sqlScriptEncoding); } } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptException.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptException.java new file mode 100644 index 00000000..198284d1 --- /dev/null +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptException.java @@ -0,0 +1,48 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jdbc.datasource.init; + +import org.springframework.dao.DataAccessException; + +/** + * Root of the hierarchy of data access exceptions that are related to processing + * of SQL scripts. + * + * @author Sam Brannen + * @since 4.0.3 + */ +@SuppressWarnings("serial") +public abstract class ScriptException extends DataAccessException { + + /** + * Constructor for {@code ScriptException}. + * @param message the detail message + */ + public ScriptException(String message) { + super(message); + } + + /** + * Constructor for {@code ScriptException}. + * @param message the detail message + * @param cause the root cause + */ + public ScriptException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptParseException.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptParseException.java new file mode 100644 index 00000000..63edc6b0 --- /dev/null +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptParseException.java @@ -0,0 +1,54 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jdbc.datasource.init; + +import org.springframework.core.io.support.EncodedResource; + +/** + * Thrown by {@link ScriptUtils} if an SQL script cannot be properly parsed. + * + * @author Sam Brannen + * @since 4.0.3 + */ +@SuppressWarnings("serial") +public class ScriptParseException extends ScriptException { + + /** + * Construct a new {@code ScriptParseException}. + * @param message detailed message + * @param resource the resource from which the SQL script was read + */ + public ScriptParseException(String message, EncodedResource resource) { + super(buildMessage(message, resource)); + } + + /** + * Construct a new {@code ScriptParseException}. + * @param message detailed message + * @param resource the resource from which the SQL script was read + * @param cause the underlying cause of the failure + */ + public ScriptParseException(String message, EncodedResource resource, Throwable cause) { + super(buildMessage(message, resource), cause); + } + + private static String buildMessage(String message, EncodedResource resource) { + return String.format("Failed to parse SQL script from resource [%s]: %s", (resource == null ? "<unknown>" + : resource), message); + } + +} diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptStatementFailedException.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptStatementFailedException.java index 016ab1ee..77c49a1c 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptStatementFailedException.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptStatementFailedException.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,15 +19,15 @@ package org.springframework.jdbc.datasource.init; import org.springframework.core.io.support.EncodedResource; /** - * Thrown by {@link ResourceDatabasePopulator} if a statement in one of its SQL scripts - * failed when executing it against the target database. + * Thrown by {@link ScriptUtils} if a statement in an SQL script failed when + * executing it against the target database. * * @author Juergen Hoeller * @author Sam Brannen * @since 3.0.5 */ @SuppressWarnings("serial") -public class ScriptStatementFailedException extends RuntimeException { +public class ScriptStatementFailedException extends ScriptException { /** * Construct a new {@code ScriptStatementFailedException}. @@ -37,8 +37,8 @@ public class ScriptStatementFailedException extends RuntimeException { * @param cause the underlying cause of the failure */ public ScriptStatementFailedException(String statement, int lineNumber, EncodedResource resource, Throwable cause) { - super("Failed to execute SQL script statement at line " + lineNumber + - " of resource " + resource + ": " + statement, cause); + super("Failed to execute SQL script statement at line " + lineNumber + " of resource " + resource + ": " + + statement, cause); } } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptUtils.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptUtils.java new file mode 100644 index 00000000..9f23e009 --- /dev/null +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptUtils.java @@ -0,0 +1,503 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jdbc.datasource.init; + +import java.io.IOException; +import java.io.LineNumberReader; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.LinkedList; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.EncodedResource; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * Generic utility methods for working with SQL scripts. Mainly for internal use + * within the framework. + * + * @author Thomas Risberg + * @author Sam Brannen + * @author Juergen Hoeller + * @author Keith Donald + * @author Dave Syer + * @author Chris Beams + * @author Oliver Gierke + * @author Chris Baldwin + * @since 4.0.3 + */ +public abstract class ScriptUtils { + + private static final Log logger = LogFactory.getLog(ScriptUtils.class); + + /** + * Default statement separator within SQL scripts. + */ + public static final String DEFAULT_STATEMENT_SEPARATOR = ";"; + + /** + * Fallback statement separator within SQL scripts. + * <p>Used if neither a custom defined separator nor the + * {@link #DEFAULT_STATEMENT_SEPARATOR} is present in a given script. + */ + public static final String FALLBACK_STATEMENT_SEPARATOR = "\n"; + + /** + * End of file (EOF) SQL statement separator. + * <p>This value may be supplied as the {@code separator} to {@link + * #executeSqlScript(Connection, EncodedResource, boolean, boolean, String, String, String, String)} + * to denote that an SQL script contains a single statement (potentially + * spanning multiple lines) with no explicit statement separator. Note that + * such a script should not actually contain this value; it is merely a + * <em>virtual</em> statement separator. + */ + public static final String EOF_STATEMENT_SEPARATOR = "^^^ END OF SCRIPT ^^^"; + + /** + * Default prefix for line comments within SQL scripts. + */ + public static final String DEFAULT_COMMENT_PREFIX = "--"; + + /** + * Default start delimiter for block comments within SQL scripts. + */ + public static final String DEFAULT_BLOCK_COMMENT_START_DELIMITER = "/*"; + + /** + * Default end delimiter for block comments within SQL scripts. + */ + public static final String DEFAULT_BLOCK_COMMENT_END_DELIMITER = "*/"; + + + /** + * Prevent instantiation of this utility class. + */ + private ScriptUtils() { + /* no-op */ + } + + /** + * Split an SQL script into separate statements delimited by the provided + * separator character. Each individual statement will be added to the + * provided {@code List}. + * <p>Within the script, {@value #DEFAULT_COMMENT_PREFIX} will be used as the + * comment prefix; any text beginning with the comment prefix and extending to + * the end of the line will be omitted from the output. Similarly, + * {@value #DEFAULT_BLOCK_COMMENT_START_DELIMITER} and + * {@value #DEFAULT_BLOCK_COMMENT_END_DELIMITER} will be used as the + * <em>start</em> and <em>end</em> block comment delimiters: any text enclosed + * in a block comment will be omitted from the output. In addition, multiple + * adjacent whitespace characters will be collapsed into a single space. + * @param script the SQL script + * @param separator character separating each statement — typically a ';' + * @param statements the list that will contain the individual statements + * @throws ScriptException if an error occurred while splitting the SQL script + * @see #splitSqlScript(String, String, List) + * @see #splitSqlScript(EncodedResource, String, String, String, String, String, List) + */ + public static void splitSqlScript(String script, char separator, List<String> statements) throws ScriptException { + splitSqlScript(script, String.valueOf(separator), statements); + } + + /** + * Split an SQL script into separate statements delimited by the provided + * separator string. Each individual statement will be added to the + * provided {@code List}. + * <p>Within the script, {@value #DEFAULT_COMMENT_PREFIX} will be used as the + * comment prefix; any text beginning with the comment prefix and extending to + * the end of the line will be omitted from the output. Similarly, + * {@value #DEFAULT_BLOCK_COMMENT_START_DELIMITER} and + * {@value #DEFAULT_BLOCK_COMMENT_END_DELIMITER} will be used as the + * <em>start</em> and <em>end</em> block comment delimiters: any text enclosed + * in a block comment will be omitted from the output. In addition, multiple + * adjacent whitespace characters will be collapsed into a single space. + * @param script the SQL script + * @param separator text separating each statement — typically a ';' or newline character + * @param statements the list that will contain the individual statements + * @throws ScriptException if an error occurred while splitting the SQL script + * @see #splitSqlScript(String, char, List) + * @see #splitSqlScript(EncodedResource, String, String, String, String, String, List) + */ + public static void splitSqlScript(String script, String separator, List<String> statements) throws ScriptException { + splitSqlScript(null, script, separator, DEFAULT_COMMENT_PREFIX, DEFAULT_BLOCK_COMMENT_START_DELIMITER, + DEFAULT_BLOCK_COMMENT_END_DELIMITER, statements); + } + + /** + * Split an SQL script into separate statements delimited by the provided + * separator string. Each individual statement will be added to the provided + * {@code List}. + * <p>Within the script, the provided {@code commentPrefix} will be honored: + * any text beginning with the comment prefix and extending to the end of the + * line will be omitted from the output. Similarly, the provided + * {@code blockCommentStartDelimiter} and {@code blockCommentEndDelimiter} + * delimiters will be honored: any text enclosed in a block comment will be + * omitted from the output. In addition, multiple adjacent whitespace characters + * will be collapsed into a single space. + * @param resource the resource from which the script was read + * @param script the SQL script; never {@code null} or empty + * @param separator text separating each statement — typically a ';' or + * newline character; never {@code null} + * @param commentPrefix the prefix that identifies SQL line comments — + * typically "--"; never {@code null} or empty + * @param blockCommentStartDelimiter the <em>start</em> block comment delimiter; + * never {@code null} or empty + * @param blockCommentEndDelimiter the <em>end</em> block comment delimiter; + * never {@code null} or empty + * @param statements the list that will contain the individual statements + * @throws ScriptException if an error occurred while splitting the SQL script + */ + public static void splitSqlScript(EncodedResource resource, String script, String separator, String commentPrefix, + String blockCommentStartDelimiter, String blockCommentEndDelimiter, List<String> statements) + throws ScriptException { + + Assert.hasText(script, "script must not be null or empty"); + Assert.notNull(separator, "separator must not be null"); + Assert.hasText(commentPrefix, "commentPrefix must not be null or empty"); + Assert.hasText(blockCommentStartDelimiter, "blockCommentStartDelimiter must not be null or empty"); + Assert.hasText(blockCommentEndDelimiter, "blockCommentEndDelimiter must not be null or empty"); + + StringBuilder sb = new StringBuilder(); + boolean inLiteral = false; + boolean inEscape = false; + char[] content = script.toCharArray(); + for (int i = 0; i < script.length(); i++) { + char c = content[i]; + if (inEscape) { + inEscape = false; + sb.append(c); + continue; + } + // MySQL style escapes + if (c == '\\') { + inEscape = true; + sb.append(c); + continue; + } + if (c == '\'') { + inLiteral = !inLiteral; + } + if (!inLiteral) { + if (script.startsWith(separator, i)) { + // we've reached the end of the current statement + if (sb.length() > 0) { + statements.add(sb.toString()); + sb = new StringBuilder(); + } + i += separator.length() - 1; + continue; + } + else if (script.startsWith(commentPrefix, i)) { + // skip over any content from the start of the comment to the EOL + int indexOfNextNewline = script.indexOf("\n", i); + if (indexOfNextNewline > i) { + i = indexOfNextNewline; + continue; + } + else { + // if there's no EOL, we must be at the end + // of the script, so stop here. + break; + } + } + else if (script.startsWith(blockCommentStartDelimiter, i)) { + // skip over any block comments + int indexOfCommentEnd = script.indexOf(blockCommentEndDelimiter, i); + if (indexOfCommentEnd > i) { + i = indexOfCommentEnd + blockCommentEndDelimiter.length() - 1; + continue; + } + else { + throw new ScriptParseException(String.format("Missing block comment end delimiter [%s].", + blockCommentEndDelimiter), resource); + } + } + else if (c == ' ' || c == '\n' || c == '\t') { + // avoid multiple adjacent whitespace characters + if (sb.length() > 0 && sb.charAt(sb.length() - 1) != ' ') { + c = ' '; + } + else { + continue; + } + } + } + sb.append(c); + } + if (StringUtils.hasText(sb)) { + statements.add(sb.toString()); + } + } + + /** + * Read a script from the given resource, using "{@code --}" as the comment prefix + * and "{@code ;}" as the statement separator, and build a String containing the lines. + * @param resource the {@code EncodedResource} to be read + * @return {@code String} containing the script lines + * @throws IOException in case of I/O errors + */ + static String readScript(EncodedResource resource) throws IOException { + return readScript(resource, DEFAULT_COMMENT_PREFIX, DEFAULT_STATEMENT_SEPARATOR); + } + + /** + * Read a script from the provided resource, using the supplied comment prefix + * and statement separator, and build a {@code String} containing the lines. + * <p>Lines <em>beginning</em> with the comment prefix are excluded from the + * results; however, line comments anywhere else — for example, within + * a statement — will be included in the results. + * @param resource the {@code EncodedResource} containing the script + * to be processed + * @param commentPrefix the prefix that identifies comments in the SQL script — + * typically "--" + * @param separator the statement separator in the SQL script — typically ";" + * @return a {@code String} containing the script lines + * @throws IOException in case of I/O errors + */ + private static String readScript(EncodedResource resource, String commentPrefix, String separator) + throws IOException { + LineNumberReader lnr = new LineNumberReader(resource.getReader()); + try { + return readScript(lnr, commentPrefix, separator); + } + finally { + lnr.close(); + } + } + + /** + * Read a script from the provided {@code LineNumberReader}, using the supplied + * comment prefix and statement separator, and build a {@code String} containing + * the lines. + * <p>Lines <em>beginning</em> with the comment prefix are excluded from the + * results; however, line comments anywhere else — for example, within + * a statement — will be included in the results. + * @param lineNumberReader the {@code LineNumberReader} containing the script + * to be processed + * @param commentPrefix the prefix that identifies comments in the SQL script — + * typically "--" + * @param separator the statement separator in the SQL script — typically ";" + * @return a {@code String} containing the script lines + * @throws IOException in case of I/O errors + */ + public static String readScript(LineNumberReader lineNumberReader, String commentPrefix, String separator) + throws IOException { + String currentStatement = lineNumberReader.readLine(); + StringBuilder scriptBuilder = new StringBuilder(); + while (currentStatement != null) { + if (commentPrefix != null && !currentStatement.startsWith(commentPrefix)) { + if (scriptBuilder.length() > 0) { + scriptBuilder.append('\n'); + } + scriptBuilder.append(currentStatement); + } + currentStatement = lineNumberReader.readLine(); + } + appendSeparatorToScriptIfNecessary(scriptBuilder, separator); + return scriptBuilder.toString(); + } + + private static void appendSeparatorToScriptIfNecessary(StringBuilder scriptBuilder, String separator) { + if (separator == null) { + return; + } + String trimmed = separator.trim(); + if (trimmed.length() == separator.length()) { + return; + } + // separator ends in whitespace, so we might want to see if the script is trying + // to end the same way + if (scriptBuilder.lastIndexOf(trimmed) == scriptBuilder.length() - trimmed.length()) { + scriptBuilder.append(separator.substring(trimmed.length())); + } + } + + /** + * Does the provided SQL script contain the specified delimiter? + * @param script the SQL script + * @param delim String delimiting each statement - typically a ';' character + */ + public static boolean containsSqlScriptDelimiters(String script, String delim) { + boolean inLiteral = false; + char[] content = script.toCharArray(); + for (int i = 0; i < script.length(); i++) { + if (content[i] == '\'') { + inLiteral = !inLiteral; + } + if (!inLiteral && script.startsWith(delim, i)) { + return true; + } + } + return false; + } + + /** + * Execute the given SQL script using default settings for separator separators, + * comment delimiters, and exception handling flags. + * <p>Statement separators and comments will be removed before executing + * individual statements within the supplied script. + * <p><b>Do not use this method to execute DDL if you expect rollback.</b> + * @param connection the JDBC connection to use to execute the script; already + * configured and ready to use + * @param resource the resource to load the SQL script from; encoded with the + * current platform's default encoding + * @throws ScriptException if an error occurred while executing the SQL script + * @see #executeSqlScript(Connection, EncodedResource, boolean, boolean, String, String, String, String) + * @see #DEFAULT_COMMENT_PREFIX + * @see #DEFAULT_STATEMENT_SEPARATOR + * @see #DEFAULT_BLOCK_COMMENT_START_DELIMITER + * @see #DEFAULT_BLOCK_COMMENT_END_DELIMITER + */ + public static void executeSqlScript(Connection connection, Resource resource) throws ScriptException { + executeSqlScript(connection, new EncodedResource(resource)); + } + + /** + * Execute the given SQL script using default settings for separator separators, + * comment delimiters, and exception handling flags. + * <p>Statement separators and comments will be removed before executing + * individual statements within the supplied script. + * <p><b>Do not use this method to execute DDL if you expect rollback.</b> + * @param connection the JDBC connection to use to execute the script; already + * configured and ready to use + * @param resource the resource (potentially associated with a specific encoding) + * to load the SQL script from + * @throws ScriptException if an error occurred while executing the SQL script + * @see #executeSqlScript(Connection, EncodedResource, boolean, boolean, String, String, String, String) + * @see #DEFAULT_COMMENT_PREFIX + * @see #DEFAULT_STATEMENT_SEPARATOR + * @see #DEFAULT_BLOCK_COMMENT_START_DELIMITER + * @see #DEFAULT_BLOCK_COMMENT_END_DELIMITER + */ + public static void executeSqlScript(Connection connection, EncodedResource resource) throws ScriptException { + executeSqlScript(connection, resource, false, false, DEFAULT_COMMENT_PREFIX, DEFAULT_STATEMENT_SEPARATOR, + DEFAULT_BLOCK_COMMENT_START_DELIMITER, DEFAULT_BLOCK_COMMENT_END_DELIMITER); + } + + /** + * Execute the given SQL script. + * <p>Statement separators and comments will be removed before executing + * individual statements within the supplied script. + * <p><b>Do not use this method to execute DDL if you expect rollback.</b> + * @param connection the JDBC connection to use to execute the script; already + * configured and ready to use + * @param resource the resource (potentially associated with a specific encoding) + * to load the SQL script from + * @param continueOnError whether or not to continue without throwing an exception + * in the event of an error + * @param ignoreFailedDrops whether or not to continue in the event of specifically + * an error on a {@code DROP} statement + * @param commentPrefix the prefix that identifies comments in the SQL script — + * typically "--" + * @param separator the script statement separator; defaults to + * {@value #DEFAULT_STATEMENT_SEPARATOR} if not specified and falls back to + * {@value #FALLBACK_STATEMENT_SEPARATOR} as a last resort; may be set to + * {@value #EOF_STATEMENT_SEPARATOR} to signal that the script contains a + * single statement without a separator + * @param blockCommentStartDelimiter the <em>start</em> block comment delimiter; never + * {@code null} or empty + * @param blockCommentEndDelimiter the <em>end</em> block comment delimiter; never + * {@code null} or empty + * @throws ScriptException if an error occurred while executing the SQL script + * @see #DEFAULT_STATEMENT_SEPARATOR + * @see #FALLBACK_STATEMENT_SEPARATOR + * @see #EOF_STATEMENT_SEPARATOR + */ + public static void executeSqlScript(Connection connection, EncodedResource resource, boolean continueOnError, + boolean ignoreFailedDrops, String commentPrefix, String separator, String blockCommentStartDelimiter, + String blockCommentEndDelimiter) throws ScriptException { + + try { + if (logger.isInfoEnabled()) { + logger.info("Executing SQL script from " + resource); + } + + long startTime = System.currentTimeMillis(); + List<String> statements = new LinkedList<String>(); + String script; + try { + script = readScript(resource, commentPrefix, separator); + } + catch (IOException ex) { + throw new CannotReadScriptException(resource, ex); + } + + if (separator == null) { + separator = DEFAULT_STATEMENT_SEPARATOR; + } + if (!EOF_STATEMENT_SEPARATOR.equals(separator) && !containsSqlScriptDelimiters(script, separator)) { + separator = FALLBACK_STATEMENT_SEPARATOR; + } + + splitSqlScript(resource, script, separator, commentPrefix, blockCommentStartDelimiter, + blockCommentEndDelimiter, statements); + int lineNumber = 0; + Statement stmt = connection.createStatement(); + try { + for (String statement : statements) { + lineNumber++; + try { + stmt.execute(statement); + int rowsAffected = stmt.getUpdateCount(); + if (logger.isDebugEnabled()) { + logger.debug(rowsAffected + " returned as updateCount for SQL: " + statement); + } + } + catch (SQLException ex) { + boolean dropStatement = StringUtils.startsWithIgnoreCase(statement.trim(), "drop"); + if (continueOnError || (dropStatement && ignoreFailedDrops)) { + if (logger.isDebugEnabled()) { + logger.debug("Failed to execute SQL script statement at line " + lineNumber + + " of resource " + resource + ": " + statement, ex); + } + } + else { + throw new ScriptStatementFailedException(statement, lineNumber, resource, ex); + } + } + } + } + finally { + try { + stmt.close(); + } + catch (Throwable ex) { + logger.debug("Could not close JDBC Statement", ex); + } + } + + long elapsedTime = System.currentTimeMillis() - startTime; + if (logger.isInfoEnabled()) { + logger.info("Executed SQL script from " + resource + " in " + elapsedTime + " ms."); + } + } + catch (Exception ex) { + if (ex instanceof ScriptException) { + throw (ScriptException) ex; + } + + throw new UncategorizedScriptException( + "Failed to execute database script from resource [" + resource + "]", ex); + } + } + +} diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/UncategorizedScriptException.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/UncategorizedScriptException.java new file mode 100644 index 00000000..bf50befb --- /dev/null +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/UncategorizedScriptException.java @@ -0,0 +1,47 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jdbc.datasource.init; + +/** + * Thrown when we cannot determine anything more specific than "something went + * wrong while processing an SQL script": for example, a {@link java.sql.SQLException} + * from JDBC that we cannot pinpoint more precisely. + * + * @author Sam Brannen + * @since 4.0.3 + */ +@SuppressWarnings("serial") +public class UncategorizedScriptException extends ScriptException { + + /** + * Construct a new {@code UncategorizedScriptException}. + * @param message detailed message + */ + public UncategorizedScriptException(String message) { + super(message); + } + + /** + * Construct a new {@code UncategorizedScriptException}. + * @param message detailed message + * @param cause the root cause + */ + public UncategorizedScriptException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/package-info.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/package-info.java index 5b10ffff..0e849199 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/package-info.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/package-info.java @@ -1,8 +1,6 @@ /** - * * Provides extensible support for initializing databases through scripts. - * */ package org.springframework.jdbc.datasource.init; diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/AbstractRoutingDataSource.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/AbstractRoutingDataSource.java index f42cbb72..7e688c6a 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/AbstractRoutingDataSource.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/AbstractRoutingDataSource.java @@ -107,12 +107,13 @@ public abstract class AbstractRoutingDataSource extends AbstractDataSource imple } + @Override public void afterPropertiesSet() { if (this.targetDataSources == null) { throw new IllegalArgumentException("Property 'targetDataSources' is required"); } this.resolvedDataSources = new HashMap<Object, DataSource>(this.targetDataSources.size()); - for (Map.Entry entry : this.targetDataSources.entrySet()) { + for (Map.Entry<Object, Object> entry : this.targetDataSources.entrySet()) { Object lookupKey = resolveSpecifiedLookupKey(entry.getKey()); DataSource dataSource = resolveSpecifiedDataSource(entry.getValue()); this.resolvedDataSources.put(lookupKey, dataSource); @@ -158,10 +159,12 @@ public abstract class AbstractRoutingDataSource extends AbstractDataSource imple } + @Override public Connection getConnection() throws SQLException { return determineTargetDataSource().getConnection(); } + @Override public Connection getConnection(String username, String password) throws SQLException { return determineTargetDataSource().getConnection(username, password); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/BeanFactoryDataSourceLookup.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/BeanFactoryDataSourceLookup.java index 915b3271..f4dbbaf5 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/BeanFactoryDataSourceLookup.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/BeanFactoryDataSourceLookup.java @@ -62,11 +62,13 @@ public class BeanFactoryDataSourceLookup implements DataSourceLookup, BeanFactor } + @Override public void setBeanFactory(BeanFactory beanFactory) { this.beanFactory = beanFactory; } + @Override public DataSource getDataSource(String dataSourceName) throws DataSourceLookupFailureException { Assert.state(this.beanFactory != null, "BeanFactory is required"); try { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/IsolationLevelDataSourceRouter.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/IsolationLevelDataSourceRouter.java index f194ca56..63bb1b66 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/IsolationLevelDataSourceRouter.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/IsolationLevelDataSourceRouter.java @@ -41,7 +41,7 @@ import org.springframework.transaction.support.TransactionSynchronizationManager * DataSources are defined as individual Spring beans with names * "myRepeatableReadDataSource", "mySerializableDataSource" and "myDefaultDataSource": * - * <pre> + * <pre class="code"> * <bean id="dataSourceRouter" class="org.springframework.jdbc.datasource.lookup.IsolationLevelDataSourceRouter"> * <property name="targetDataSources"> * <map> @@ -57,7 +57,7 @@ import org.springframework.transaction.support.TransactionSynchronizationManager * names for a standard JNDI lookup. This allows for a single concise definition * without the need for separate DataSource bean definitions. * - * <pre> + * <pre class="code"> * <bean id="dataSourceRouter" class="org.springframework.jdbc.datasource.lookup.IsolationLevelDataSourceRouter"> * <property name="targetDataSources"> * <map> @@ -74,7 +74,7 @@ import org.springframework.transaction.support.TransactionSynchronizationManager * (By default, JtaTransactionManager will only accept a default isolation level * because of the lack of isolation level support in standard JTA itself.) * - * <pre> + * <pre class="code"> * <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> * <property name="allowCustomIsolationLevels" value="true"/> * </bean></pre> diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/JndiDataSourceLookup.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/JndiDataSourceLookup.java index 2a48efaa..96677aa2 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/JndiDataSourceLookup.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/JndiDataSourceLookup.java @@ -39,6 +39,7 @@ public class JndiDataSourceLookup extends JndiLocatorSupport implements DataSour setResourceRef(true); } + @Override public DataSource getDataSource(String dataSourceName) throws DataSourceLookupFailureException { try { return lookup(dataSourceName, DataSource.class); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/MapDataSourceLookup.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/MapDataSourceLookup.java index 0a4eb32b..e392303e 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/MapDataSourceLookup.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/MapDataSourceLookup.java @@ -98,6 +98,7 @@ public class MapDataSourceLookup implements DataSourceLookup { this.dataSources.put(dataSourceName, dataSource); } + @Override public DataSource getDataSource(String dataSourceName) throws DataSourceLookupFailureException { Assert.notNull(dataSourceName, "DataSource name must not be null"); DataSource dataSource = this.dataSources.get(dataSourceName); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/SingleDataSourceLookup.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/SingleDataSourceLookup.java index 3443a713..8bd9a4bb 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/SingleDataSourceLookup.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/SingleDataSourceLookup.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2006 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +42,7 @@ public class SingleDataSourceLookup implements DataSourceLookup { } + @Override public DataSource getDataSource(String dataSourceName) { return this.dataSource; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/object/BatchSqlUpdate.java b/spring-jdbc/src/main/java/org/springframework/jdbc/object/BatchSqlUpdate.java index 039e5c34..63729908 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/object/BatchSqlUpdate.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/object/BatchSqlUpdate.java @@ -184,9 +184,11 @@ public class BatchSqlUpdate extends SqlUpdate { int[] rowsAffected = getJdbcTemplate().batchUpdate( getSql(), new BatchPreparedStatementSetter() { + @Override public int getBatchSize() { return parameterQueue.size(); } + @Override public void setValues(PreparedStatement ps, int index) throws SQLException { Object[] params = parameterQueue.removeFirst(); newPreparedStatementSetter(params).setValues(ps); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/object/GenericSqlQuery.java b/spring-jdbc/src/main/java/org/springframework/jdbc/object/GenericSqlQuery.java index 1cf222e0..6854921d 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/object/GenericSqlQuery.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/object/GenericSqlQuery.java @@ -22,13 +22,14 @@ import org.springframework.jdbc.core.RowMapper; import org.springframework.util.Assert; import org.springframework.dao.InvalidDataAccessResourceUsageException; -public class GenericSqlQuery extends SqlQuery { +public class GenericSqlQuery<T> extends SqlQuery<T> { - Class rowMapperClass; + Class<?> rowMapperClass; - RowMapper rowMapper; + RowMapper<?> rowMapper; - public void setRowMapperClass(Class rowMapperClass) + @SuppressWarnings("rawtypes") + public void setRowMapperClass(Class<? extends RowMapper> rowMapperClass) throws IllegalAccessException, InstantiationException { this.rowMapperClass = rowMapperClass; if (!RowMapper.class.isAssignableFrom(rowMapperClass)) @@ -37,14 +38,17 @@ public class GenericSqlQuery extends SqlQuery { "'org.springframework.jdbc.core.RowMapper'"); } + @Override public void afterPropertiesSet() { super.afterPropertiesSet(); Assert.notNull(rowMapperClass, "The 'rowMapperClass' property is required"); } - protected RowMapper newRowMapper(Object[] parameters, Map context) { + @Override + @SuppressWarnings("unchecked") + protected RowMapper<T> newRowMapper(Object[] parameters, Map<?, ?> context) { try { - return (RowMapper) rowMapperClass.newInstance(); + return (RowMapper<T>) rowMapperClass.newInstance(); } catch (InstantiationException e) { throw new InvalidDataAccessResourceUsageException("Unable to instantiate RowMapper", e); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/object/MappingSqlQuery.java b/spring-jdbc/src/main/java/org/springframework/jdbc/object/MappingSqlQuery.java index 1f3ec187..e88a9c82 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/object/MappingSqlQuery.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/object/MappingSqlQuery.java @@ -59,7 +59,7 @@ public abstract class MappingSqlQuery<T> extends MappingSqlQueryWithParameters<T * @see #mapRow(ResultSet, int) */ @Override - protected final T mapRow(ResultSet rs, int rowNum, Object[] parameters, Map context) + protected final T mapRow(ResultSet rs, int rowNum, Object[] parameters, Map<?, ?> context) throws SQLException { return mapRow(rs, rowNum); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/object/MappingSqlQueryWithParameters.java b/spring-jdbc/src/main/java/org/springframework/jdbc/object/MappingSqlQueryWithParameters.java index 6e8355e6..ae0b5fc3 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/object/MappingSqlQueryWithParameters.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/object/MappingSqlQueryWithParameters.java @@ -70,7 +70,7 @@ public abstract class MappingSqlQueryWithParameters<T> extends SqlQuery<T> { * implementation of the mapRow() method. */ @Override - protected RowMapper<T> newRowMapper(Object[] parameters, Map context) { + protected RowMapper<T> newRowMapper(Object[] parameters, Map<?, ?> context) { return new RowMapperImpl(parameters, context); } @@ -89,7 +89,7 @@ public abstract class MappingSqlQueryWithParameters<T> extends SqlQuery<T> { * Subclasses can simply not catch SQLExceptions, relying on the * framework to clean up. */ - protected abstract T mapRow(ResultSet rs, int rowNum, Object[] parameters, Map context) + protected abstract T mapRow(ResultSet rs, int rowNum, Object[] parameters, Map<?, ?> context) throws SQLException; @@ -101,16 +101,17 @@ public abstract class MappingSqlQueryWithParameters<T> extends SqlQuery<T> { private final Object[] params; - private final Map context; + private final Map<?, ?> context; /** * Use an array results. More efficient if we know how many results to expect. */ - public RowMapperImpl(Object[] parameters, Map context) { + public RowMapperImpl(Object[] parameters, Map<?, ?> context) { this.params = parameters; this.context = context; } + @Override public T mapRow(ResultSet rs, int rowNum) throws SQLException { return MappingSqlQueryWithParameters.this.mapRow(rs, rowNum, this.params, this.context); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/object/RdbmsOperation.java b/spring-jdbc/src/main/java/org/springframework/jdbc/object/RdbmsOperation.java index 263e9d12..61c52338 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/object/RdbmsOperation.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/object/RdbmsOperation.java @@ -313,6 +313,7 @@ public abstract class RdbmsOperation implements InitializingBean { /** * Ensures compilation if used in a bean factory. */ + @Override public void afterPropertiesSet() { compile(); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/object/SqlQuery.java b/spring-jdbc/src/main/java/org/springframework/jdbc/object/SqlQuery.java index 58f8f3d2..ea4d8582 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/object/SqlQuery.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/object/SqlQuery.java @@ -106,7 +106,7 @@ public abstract class SqlQuery<T> extends SqlOperation { * @return a List of objects, one per row of the ResultSet. Normally all these * will be of the same class, although it is possible to use different types. */ - public List<T> execute(Object[] params, Map context) throws DataAccessException { + public List<T> execute(Object[] params, Map<?, ?> context) throws DataAccessException { validateParameters(params); RowMapper<T> rowMapper = newRowMapper(params, context); return getJdbcTemplate().query(newPreparedStatementCreator(params), rowMapper); @@ -126,7 +126,7 @@ public abstract class SqlQuery<T> extends SqlOperation { * Convenient method to execute without parameters. * @param context the contextual information for object creation */ - public List<T> execute(Map context) throws DataAccessException { + public List<T> execute(Map<?, ?> context) throws DataAccessException { return execute((Object[]) null, context); } @@ -142,7 +142,7 @@ public abstract class SqlQuery<T> extends SqlOperation { * @param p1 single int parameter * @param context the contextual information for object creation */ - public List<T> execute(int p1, Map context) throws DataAccessException { + public List<T> execute(int p1, Map<?, ?> context) throws DataAccessException { return execute(new Object[] {p1}, context); } @@ -160,7 +160,7 @@ public abstract class SqlQuery<T> extends SqlOperation { * @param p2 second int parameter * @param context the contextual information for object creation */ - public List<T> execute(int p1, int p2, Map context) throws DataAccessException { + public List<T> execute(int p1, int p2, Map<?, ?> context) throws DataAccessException { return execute(new Object[] {p1, p2}, context); } @@ -178,7 +178,7 @@ public abstract class SqlQuery<T> extends SqlOperation { * @param p1 single long parameter * @param context the contextual information for object creation */ - public List<T> execute(long p1, Map context) throws DataAccessException { + public List<T> execute(long p1, Map<?, ?> context) throws DataAccessException { return execute(new Object[] {p1}, context); } @@ -195,7 +195,7 @@ public abstract class SqlQuery<T> extends SqlOperation { * @param p1 single String parameter * @param context the contextual information for object creation */ - public List<T> execute(String p1, Map context) throws DataAccessException { + public List<T> execute(String p1, Map<?, ?> context) throws DataAccessException { return execute(new Object[] {p1}, context); } @@ -219,7 +219,7 @@ public abstract class SqlQuery<T> extends SqlOperation { * @return a List of objects, one per row of the ResultSet. Normally all these * will be of the same class, although it is possible to use different types. */ - public List<T> executeByNamedParam(Map<String, ?> paramMap, Map context) throws DataAccessException { + public List<T> executeByNamedParam(Map<String, ?> paramMap, Map<?, ?> context) throws DataAccessException { validateNamedParameters(paramMap); ParsedSql parsedSql = getParsedSql(); MapSqlParameterSource paramSource = new MapSqlParameterSource(paramMap); @@ -248,7 +248,7 @@ public abstract class SqlQuery<T> extends SqlOperation { * choose to treat this as an error and throw an exception. * @see org.springframework.dao.support.DataAccessUtils#singleResult */ - public T findObject(Object[] params, Map context) throws DataAccessException { + public T findObject(Object[] params, Map<?, ?> context) throws DataAccessException { List<T> results = execute(params, context); return DataAccessUtils.singleResult(results); } @@ -264,7 +264,7 @@ public abstract class SqlQuery<T> extends SqlOperation { * Convenient method to find a single object given a single int parameter * and a context. */ - public T findObject(int p1, Map context) throws DataAccessException { + public T findObject(int p1, Map<?, ?> context) throws DataAccessException { return findObject(new Object[] {p1}, context); } @@ -279,7 +279,7 @@ public abstract class SqlQuery<T> extends SqlOperation { * Convenient method to find a single object given two int parameters * and a context. */ - public T findObject(int p1, int p2, Map context) throws DataAccessException { + public T findObject(int p1, int p2, Map<?, ?> context) throws DataAccessException { return findObject(new Object[] {p1, p2}, context); } @@ -294,7 +294,7 @@ public abstract class SqlQuery<T> extends SqlOperation { * Convenient method to find a single object given a single long parameter * and a context. */ - public T findObject(long p1, Map context) throws DataAccessException { + public T findObject(long p1, Map<?, ?> context) throws DataAccessException { return findObject(new Object[] {p1}, context); } @@ -309,7 +309,7 @@ public abstract class SqlQuery<T> extends SqlOperation { * Convenient method to find a single object given a single String parameter * and a context. */ - public T findObject(String p1, Map context) throws DataAccessException { + public T findObject(String p1, Map<?, ?> context) throws DataAccessException { return findObject(new Object[] {p1}, context); } @@ -331,7 +331,7 @@ public abstract class SqlQuery<T> extends SqlOperation { * @return a List of objects, one per row of the ResultSet. Normally all these * will be of the same class, although it is possible to use different types. */ - public T findObjectByNamedParam(Map<String, ?> paramMap, Map context) throws DataAccessException { + public T findObjectByNamedParam(Map<String, ?> paramMap, Map<?, ?> context) throws DataAccessException { List<T> results = executeByNamedParam(paramMap, context); return DataAccessUtils.singleResult(results); } @@ -358,6 +358,6 @@ public abstract class SqlQuery<T> extends SqlOperation { * but it can be useful for creating the objects of the result list. * @see #execute */ - protected abstract RowMapper<T> newRowMapper(Object[] parameters, Map context); + protected abstract RowMapper<T> newRowMapper(Object[] parameters, Map<?, ?> context); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/object/StoredProcedure.java b/spring-jdbc/src/main/java/org/springframework/jdbc/object/StoredProcedure.java index c359b49f..077a59e2 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/object/StoredProcedure.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/object/StoredProcedure.java @@ -33,9 +33,7 @@ import org.springframework.jdbc.core.SqlParameter; * {@link #execute} method. * * <p>The inherited {@code sql} property is the name of the stored - * procedure in the RDBMS. Note that JDBC 3.0 introduces named parameters, - * although the other features provided by this class are still necessary - * in JDBC 3.0. + * procedure in the RDBMS. * * @author Rod Johnson * @author Thomas Risberg diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/object/UpdatableSqlQuery.java b/spring-jdbc/src/main/java/org/springframework/jdbc/object/UpdatableSqlQuery.java index 90603687..7f4acdbc 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/object/UpdatableSqlQuery.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/object/UpdatableSqlQuery.java @@ -60,7 +60,7 @@ public abstract class UpdatableSqlQuery<T> extends SqlQuery<T> { * implementation of the {@code updateRow()} method. */ @Override - protected RowMapper<T> newRowMapper(Object[] parameters, Map context) { + protected RowMapper<T> newRowMapper(Object[] parameters, Map<?, ?> context) { return new RowMapperImpl(context); } @@ -79,7 +79,7 @@ public abstract class UpdatableSqlQuery<T> extends SqlQuery<T> { * Subclasses can simply not catch SQLExceptions, relying on the * framework to clean up. */ - protected abstract T updateRow(ResultSet rs, int rowNum, Map context) throws SQLException; + protected abstract T updateRow(ResultSet rs, int rowNum, Map<?, ?> context) throws SQLException; /** @@ -88,12 +88,13 @@ public abstract class UpdatableSqlQuery<T> extends SqlQuery<T> { */ protected class RowMapperImpl implements RowMapper<T> { - private final Map context; + private final Map<?, ?> context; - public RowMapperImpl(Map context) { + public RowMapperImpl(Map<?, ?> context) { this.context = context; } + @Override public T mapRow(ResultSet rs, int rowNum) throws SQLException { T result = updateRow(rs, rowNum, this.context); rs.updateRow(); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/package-info.java b/spring-jdbc/src/main/java/org/springframework/jdbc/package-info.java index a58744a9..662b09ff 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/package-info.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/package-info.java @@ -4,7 +4,7 @@ * The classes in this package make JDBC easier to use and * reduce the likelihood of common errors. In particular, they: * <ul> - * <li>Simplify error handling, avoiding the need for try/catch/final + * <li>Simplify error handling, avoiding the need for try/catch/finally * blocks in application code. * <li>Present exceptions to application code in a generic hierarchy of * unchecked exceptions, enabling applications to catch data access diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java index 7b6d9181..6e4c548e 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java @@ -60,6 +60,7 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep * Pre-checks the arguments, calls {@link #doTranslate}, and invokes the * {@link #getFallbackTranslator() fallback translator} if necessary. */ + @Override public DataAccessException translate(String task, String sql, SQLException ex) { Assert.notNull(ex, "Cannot translate a null SQLException"); if (task == null) { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/CustomSQLErrorCodesTranslation.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/CustomSQLErrorCodesTranslation.java index 82954fd4..77275108 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/CustomSQLErrorCodesTranslation.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/CustomSQLErrorCodesTranslation.java @@ -32,7 +32,7 @@ public class CustomSQLErrorCodesTranslation { private String[] errorCodes = new String[0]; - private Class exceptionClass; + private Class<?> exceptionClass; /** @@ -52,7 +52,7 @@ public class CustomSQLErrorCodesTranslation { /** * Set the exception class for the specified error codes. */ - public void setExceptionClass(Class exceptionClass) { + public void setExceptionClass(Class<?> exceptionClass) { if (!DataAccessException.class.isAssignableFrom(exceptionClass)) { throw new IllegalArgumentException("Invalid exception class [" + exceptionClass + "]: needs to be a subclass of [org.springframework.dao.DataAccessException]"); @@ -63,7 +63,7 @@ public class CustomSQLErrorCodesTranslation { /** * Return the exception class for the specified error codes. */ - public Class getExceptionClass() { + public Class<?> getExceptionClass() { return this.exceptionClass; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/CustomSQLExceptionTranslatorRegistrar.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/CustomSQLExceptionTranslatorRegistrar.java index 66802216..2faaaba1 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/CustomSQLExceptionTranslatorRegistrar.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/CustomSQLExceptionTranslatorRegistrar.java @@ -48,6 +48,7 @@ public class CustomSQLExceptionTranslatorRegistrar implements InitializingBean { this.translators.putAll(translators); } + @Override public void afterPropertiesSet() { for (String dbName : this.translators.keySet()) { CustomSQLExceptionTranslatorRegistry.getInstance().registerTranslator(dbName, this.translators.get(dbName)); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/DatabaseStartupValidator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/DatabaseStartupValidator.java index acc95cca..738709ac 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/DatabaseStartupValidator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/DatabaseStartupValidator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -93,6 +93,7 @@ public class DatabaseStartupValidator implements InitializingBean { * from the specified DataSource, with the specified interval between * checks, until the specified timeout. */ + @Override public void afterPropertiesSet() { if (this.dataSource == null) { throw new IllegalArgumentException("dataSource is required"); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/GeneratedKeyHolder.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/GeneratedKeyHolder.java index a624e3fa..abdab1e8 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/GeneratedKeyHolder.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/GeneratedKeyHolder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -57,6 +57,7 @@ public class GeneratedKeyHolder implements KeyHolder { } + @Override public Number getKey() throws InvalidDataAccessApiUsageException, DataRetrievalFailureException { if (this.keyList.size() == 0) { return null; @@ -83,6 +84,7 @@ public class GeneratedKeyHolder implements KeyHolder { } } + @Override public Map<String, Object> getKeys() throws InvalidDataAccessApiUsageException { if (this.keyList.size() == 0) { return null; @@ -94,6 +96,7 @@ public class GeneratedKeyHolder implements KeyHolder { return this.keyList.get(0); } + @Override public List<Map<String, Object>> getKeyList() { return this.keyList; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcAccessor.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcAccessor.java index 89940f0c..f383a4d8 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcAccessor.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcAccessor.java @@ -129,6 +129,7 @@ public abstract class JdbcAccessor implements InitializingBean { * Eagerly initialize the exception translator, if demanded, * creating a default one for the specified DataSource if none set. */ + @Override public void afterPropertiesSet() { if (getDataSource() == null) { throw new IllegalArgumentException("Property 'dataSource' is required"); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcUtils.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcUtils.java index 95f2ee36..ea6be1ab 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcUtils.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcUtils.java @@ -129,7 +129,7 @@ public abstract class JdbcUtils { * @return the value object * @throws SQLException if thrown by the JDBC API */ - public static Object getResultSetValue(ResultSet rs, int index, Class requiredType) throws SQLException { + public static Object getResultSetValue(ResultSet rs, int index, Class<?> requiredType) throws SQLException { if (requiredType == null) { return getResultSetValue(rs, index); } @@ -319,6 +319,7 @@ public abstract class JdbcUtils { return extractDatabaseMetaData(dataSource, new DatabaseMetaDataCallback() { + @Override public Object processMetaData(DatabaseMetaData dbmd) throws SQLException, MetaDataAccessException { try { Method method = DatabaseMetaData.class.getMethod(metaDataMethodName, (Class[]) null); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java index 3bf52d3f..31da4219 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java @@ -22,7 +22,6 @@ import java.sql.SQLException; import java.util.Arrays; import javax.sql.DataSource; -import org.springframework.core.JdkVersion; import org.springframework.dao.CannotAcquireLockException; import org.springframework.dao.CannotSerializeTransactionException; import org.springframework.dao.DataAccessException; @@ -82,12 +81,7 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep * The SqlErrorCodes or DataSource property must be set. */ public SQLErrorCodeSQLExceptionTranslator() { - if (JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_16) { - setFallbackTranslator(new SQLExceptionSubclassTranslator()); - } - else { - setFallbackTranslator(new SQLStateSQLExceptionTranslator()); - } + setFallbackTranslator(new SQLExceptionSubclassTranslator()); } /** @@ -319,14 +313,14 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep * @see CustomSQLErrorCodesTranslation#setExceptionClass */ protected DataAccessException createCustomException( - String task, String sql, SQLException sqlEx, Class exceptionClass) { + String task, String sql, SQLException sqlEx, Class<?> exceptionClass) { // find appropriate constructor try { int constructorType = 0; - Constructor[] constructors = exceptionClass.getConstructors(); - for (Constructor constructor : constructors) { - Class[] parameterTypes = constructor.getParameterTypes(); + Constructor<?>[] constructors = exceptionClass.getConstructors(); + for (Constructor<?> constructor : constructors) { + Class<?>[] parameterTypes = constructor.getParameterTypes(); if (parameterTypes.length == 1 && parameterTypes[0].equals(String.class)) { if (constructorType < MESSAGE_ONLY_CONSTRUCTOR) constructorType = MESSAGE_ONLY_CONSTRUCTOR; @@ -354,30 +348,30 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep } // invoke constructor - Constructor exceptionConstructor; + Constructor<?> exceptionConstructor; switch (constructorType) { case MESSAGE_SQL_SQLEX_CONSTRUCTOR: - Class[] messageAndSqlAndSqlExArgsClass = new Class[] {String.class, String.class, SQLException.class}; + Class<?>[] messageAndSqlAndSqlExArgsClass = new Class<?>[] {String.class, String.class, SQLException.class}; Object[] messageAndSqlAndSqlExArgs = new Object[] {task, sql, sqlEx}; exceptionConstructor = exceptionClass.getConstructor(messageAndSqlAndSqlExArgsClass); return (DataAccessException) exceptionConstructor.newInstance(messageAndSqlAndSqlExArgs); case MESSAGE_SQL_THROWABLE_CONSTRUCTOR: - Class[] messageAndSqlAndThrowableArgsClass = new Class[] {String.class, String.class, Throwable.class}; + Class<?>[] messageAndSqlAndThrowableArgsClass = new Class<?>[] {String.class, String.class, Throwable.class}; Object[] messageAndSqlAndThrowableArgs = new Object[] {task, sql, sqlEx}; exceptionConstructor = exceptionClass.getConstructor(messageAndSqlAndThrowableArgsClass); return (DataAccessException) exceptionConstructor.newInstance(messageAndSqlAndThrowableArgs); case MESSAGE_SQLEX_CONSTRUCTOR: - Class[] messageAndSqlExArgsClass = new Class[] {String.class, SQLException.class}; + Class<?>[] messageAndSqlExArgsClass = new Class<?>[] {String.class, SQLException.class}; Object[] messageAndSqlExArgs = new Object[] {task + ": " + sqlEx.getMessage(), sqlEx}; exceptionConstructor = exceptionClass.getConstructor(messageAndSqlExArgsClass); return (DataAccessException) exceptionConstructor.newInstance(messageAndSqlExArgs); case MESSAGE_THROWABLE_CONSTRUCTOR: - Class[] messageAndThrowableArgsClass = new Class[] {String.class, Throwable.class}; + Class<?>[] messageAndThrowableArgsClass = new Class<?>[] {String.class, Throwable.class}; Object[] messageAndThrowableArgs = new Object[] {task + ": " + sqlEx.getMessage(), sqlEx}; exceptionConstructor = exceptionClass.getConstructor(messageAndThrowableArgsClass); return (DataAccessException)exceptionConstructor.newInstance(messageAndThrowableArgs); case MESSAGE_ONLY_CONSTRUCTOR: - Class[] messageOnlyArgsClass = new Class[] {String.class}; + Class<?>[] messageOnlyArgsClass = new Class<?>[] {String.class}; Object[] messageOnlyArgs = new Object[] {task + ": " + sqlEx.getMessage()}; exceptionConstructor = exceptionClass.getConstructor(messageOnlyArgsClass); return (DataAccessException) exceptionConstructor.newInstance(messageOnlyArgs); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionSubclassTranslator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionSubclassTranslator.java index 7febfc29..78455c18 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionSubclassTranslator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionSubclassTranslator.java @@ -45,9 +45,8 @@ import org.springframework.jdbc.BadSqlGrammarException; * {@link SQLExceptionTranslator} implementation which analyzes the specific * {@link java.sql.SQLException} subclass thrown by the JDBC driver. * - * <p>This is only available with JDBC 4.0 and later drivers when using Java 6 or later. - * Falls back to a standard {@link SQLStateSQLExceptionTranslator} if the JDBC driver - * does not actually expose JDBC 4 compliant {@code SQLException} subclasses. + * <p>Falls back to a standard {@link SQLStateSQLExceptionTranslator} if the JDBC + * driver does not actually expose JDBC 4 compliant {@code SQLException} subclasses. * * @author Thomas Risberg * @author Juergen Hoeller diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/incrementer/AbstractColumnMaxValueIncrementer.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/incrementer/AbstractColumnMaxValueIncrementer.java index 713d095a..121eef0b 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/incrementer/AbstractColumnMaxValueIncrementer.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/incrementer/AbstractColumnMaxValueIncrementer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,7 @@ import org.springframework.util.Assert; /** * Abstract base class for {@link DataFieldMaxValueIncrementer} implementations that use * a column in a custom sequence table. Subclasses need to provide the specific handling - * of that table in their {@link #getNextKey()} implementation.. + * of that table in their {@link #getNextKey()} implementation. * * @author Juergen Hoeller * @since 2.5.3 diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/incrementer/AbstractDataFieldMaxValueIncrementer.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/incrementer/AbstractDataFieldMaxValueIncrementer.java index 3fd0d80f..933c166a 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/incrementer/AbstractDataFieldMaxValueIncrementer.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/incrementer/AbstractDataFieldMaxValueIncrementer.java @@ -107,6 +107,7 @@ public abstract class AbstractDataFieldMaxValueIncrementer implements DataFieldM return this.paddingLength; } + @Override public void afterPropertiesSet() { if (this.dataSource == null) { throw new IllegalArgumentException("Property 'dataSource' is required"); @@ -117,14 +118,17 @@ public abstract class AbstractDataFieldMaxValueIncrementer implements DataFieldM } + @Override public int nextIntValue() throws DataAccessException { return (int) getNextKey(); } + @Override public long nextLongValue() throws DataAccessException { return getNextKey(); } + @Override public String nextStringValue() throws DataAccessException { String s = Long.toString(getNextKey()); int len = s.length(); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/AbstractLobHandler.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/AbstractLobHandler.java index 4da40d61..2caea6f2 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/AbstractLobHandler.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/AbstractLobHandler.java @@ -33,22 +33,27 @@ import java.sql.SQLException; */ public abstract class AbstractLobHandler implements LobHandler { + @Override public byte[] getBlobAsBytes(ResultSet rs, String columnName) throws SQLException { return getBlobAsBytes(rs, rs.findColumn(columnName)); } + @Override public InputStream getBlobAsBinaryStream(ResultSet rs, String columnName) throws SQLException { return getBlobAsBinaryStream(rs, rs.findColumn(columnName)); } + @Override public String getClobAsString(ResultSet rs, String columnName) throws SQLException { return getClobAsString(rs, rs.findColumn(columnName)); } + @Override public InputStream getClobAsAsciiStream(ResultSet rs, String columnName) throws SQLException { return getClobAsAsciiStream(rs, rs.findColumn(columnName)); } + @Override public Reader getClobAsCharacterStream(ResultSet rs, String columnName) throws SQLException { return getClobAsCharacterStream(rs, rs.findColumn(columnName)); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/DefaultLobHandler.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/DefaultLobHandler.java index e570be24..c1ae28cb 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/DefaultLobHandler.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/DefaultLobHandler.java @@ -139,6 +139,7 @@ public class DefaultLobHandler extends AbstractLobHandler { } + @Override public byte[] getBlobAsBytes(ResultSet rs, int columnIndex) throws SQLException { logger.debug("Returning BLOB as bytes"); if (this.wrapAsLob) { @@ -150,6 +151,7 @@ public class DefaultLobHandler extends AbstractLobHandler { } } + @Override public InputStream getBlobAsBinaryStream(ResultSet rs, int columnIndex) throws SQLException { logger.debug("Returning BLOB as binary stream"); if (this.wrapAsLob) { @@ -161,6 +163,7 @@ public class DefaultLobHandler extends AbstractLobHandler { } } + @Override public String getClobAsString(ResultSet rs, int columnIndex) throws SQLException { logger.debug("Returning CLOB as string"); if (this.wrapAsLob) { @@ -172,6 +175,7 @@ public class DefaultLobHandler extends AbstractLobHandler { } } + @Override public InputStream getClobAsAsciiStream(ResultSet rs, int columnIndex) throws SQLException { logger.debug("Returning CLOB as ASCII stream"); if (this.wrapAsLob) { @@ -183,6 +187,7 @@ public class DefaultLobHandler extends AbstractLobHandler { } } + @Override public Reader getClobAsCharacterStream(ResultSet rs, int columnIndex) throws SQLException { logger.debug("Returning CLOB as character stream"); if (this.wrapAsLob) { @@ -194,6 +199,8 @@ public class DefaultLobHandler extends AbstractLobHandler { } } + @Override + @SuppressWarnings("resource") public LobCreator getLobCreator() { return (this.createTemporaryLob ? new TemporaryLobCreator() : new DefaultLobCreator()); } @@ -205,6 +212,7 @@ public class DefaultLobHandler extends AbstractLobHandler { */ protected class DefaultLobCreator implements LobCreator { + @Override public void setBlobAsBytes(PreparedStatement ps, int paramIndex, byte[] content) throws SQLException { @@ -233,6 +241,7 @@ public class DefaultLobHandler extends AbstractLobHandler { } } + @Override public void setBlobAsBinaryStream( PreparedStatement ps, int paramIndex, InputStream binaryStream, int contentLength) throws SQLException { @@ -262,6 +271,7 @@ public class DefaultLobHandler extends AbstractLobHandler { } } + @Override public void setClobAsString(PreparedStatement ps, int paramIndex, String content) throws SQLException { @@ -290,6 +300,7 @@ public class DefaultLobHandler extends AbstractLobHandler { } } + @Override public void setClobAsAsciiStream( PreparedStatement ps, int paramIndex, InputStream asciiStream, int contentLength) throws SQLException { @@ -324,6 +335,7 @@ public class DefaultLobHandler extends AbstractLobHandler { } } + @Override public void setClobAsCharacterStream( PreparedStatement ps, int paramIndex, Reader characterStream, int contentLength) throws SQLException { @@ -353,6 +365,7 @@ public class DefaultLobHandler extends AbstractLobHandler { } } + @Override public void close() { // nothing to do when not creating temporary LOBs } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/JtaLobCreatorSynchronization.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/JtaLobCreatorSynchronization.java index 19c85608..80ae5d1e 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/JtaLobCreatorSynchronization.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/JtaLobCreatorSynchronization.java @@ -46,6 +46,7 @@ public class JtaLobCreatorSynchronization implements Synchronization { this.lobCreator = lobCreator; } + @Override public void beforeCompletion() { // Close the LobCreator early if possible, to avoid issues with strict JTA // implementations that issue warnings when doing JDBC operations after @@ -54,6 +55,7 @@ public class JtaLobCreatorSynchronization implements Synchronization { this.lobCreator.close(); } + @Override public void afterCompletion(int status) { if (!this.beforeCompletionCalled) { // beforeCompletion not called before (probably because of JTA rollback). diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/LobCreator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/LobCreator.java index ad0e3719..8bee169c 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/LobCreator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/LobCreator.java @@ -135,6 +135,7 @@ public interface LobCreator extends Closeable { * been executed or the affected O/R mapping sessions have been flushed. * Otherwise, the database resources for the temporary BLOBs might stay allocated. */ + @Override void close(); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/OracleLobHandler.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/OracleLobHandler.java index 2b239b35..0861b92d 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/OracleLobHandler.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/OracleLobHandler.java @@ -111,15 +111,15 @@ public class OracleLobHandler extends AbstractLobHandler { private Boolean releaseResourcesAfterRead = Boolean.FALSE; - private Class blobClass; + private Class<?> blobClass; - private Class clobClass; + private Class<?> clobClass; - private final Map<Class, Integer> durationSessionConstants = new HashMap<Class, Integer>(2); + private final Map<Class<?>, Integer> durationSessionConstants = new HashMap<Class<?>, Integer>(2); - private final Map<Class, Integer> modeReadWriteConstants = new HashMap<Class, Integer>(2); + private final Map<Class<?>, Integer> modeReadWriteConstants = new HashMap<Class<?>, Integer>(2); - private final Map<Class, Integer> modeReadOnlyConstants = new HashMap<Class, Integer>(2); + private final Map<Class<?>, Integer> modeReadOnlyConstants = new HashMap<Class<?>, Integer>(2); /** @@ -227,6 +227,7 @@ public class OracleLobHandler extends AbstractLobHandler { } + @Override public byte[] getBlobAsBytes(ResultSet rs, int columnIndex) throws SQLException { logger.debug("Returning Oracle BLOB as bytes"); Blob blob = rs.getBlob(columnIndex); @@ -236,6 +237,7 @@ public class OracleLobHandler extends AbstractLobHandler { return retVal; } + @Override public InputStream getBlobAsBinaryStream(ResultSet rs, int columnIndex) throws SQLException { logger.debug("Returning Oracle BLOB as binary stream"); Blob blob = rs.getBlob(columnIndex); @@ -245,6 +247,7 @@ public class OracleLobHandler extends AbstractLobHandler { return retVal; } + @Override public String getClobAsString(ResultSet rs, int columnIndex) throws SQLException { logger.debug("Returning Oracle CLOB as string"); Clob clob = rs.getClob(columnIndex); @@ -254,6 +257,7 @@ public class OracleLobHandler extends AbstractLobHandler { return retVal; } + @Override public InputStream getClobAsAsciiStream(ResultSet rs, int columnIndex) throws SQLException { logger.debug("Returning Oracle CLOB as ASCII stream"); Clob clob = rs.getClob(columnIndex); @@ -263,6 +267,7 @@ public class OracleLobHandler extends AbstractLobHandler { return retVal; } + @Override public Reader getClobAsCharacterStream(ResultSet rs, int columnIndex) throws SQLException { logger.debug("Returning Oracle CLOB as character stream"); Clob clob = rs.getClob(columnIndex); @@ -272,6 +277,7 @@ public class OracleLobHandler extends AbstractLobHandler { return retVal; } + @Override public LobCreator getLobCreator() { return new OracleLobCreator(); } @@ -384,11 +390,13 @@ public class OracleLobHandler extends AbstractLobHandler { private final List<Object> temporaryLobs = new LinkedList<Object>(); + @Override public void setBlobAsBytes(PreparedStatement ps, int paramIndex, final byte[] content) throws SQLException { if (content != null) { Blob blob = (Blob) createLob(ps, false, new LobCallback() { + @Override public void populateLob(Object lob) throws Exception { Method methodToInvoke = lob.getClass().getMethod("getBinaryOutputStream"); OutputStream out = (OutputStream) methodToInvoke.invoke(lob); @@ -406,12 +414,14 @@ public class OracleLobHandler extends AbstractLobHandler { } } + @Override public void setBlobAsBinaryStream( PreparedStatement ps, int paramIndex, final InputStream binaryStream, int contentLength) throws SQLException { if (binaryStream != null) { Blob blob = (Blob) createLob(ps, false, new LobCallback() { + @Override public void populateLob(Object lob) throws Exception { Method methodToInvoke = lob.getClass().getMethod("getBinaryOutputStream", (Class[]) null); OutputStream out = (OutputStream) methodToInvoke.invoke(lob, (Object[]) null); @@ -429,11 +439,13 @@ public class OracleLobHandler extends AbstractLobHandler { } } + @Override public void setClobAsString(PreparedStatement ps, int paramIndex, final String content) throws SQLException { if (content != null) { Clob clob = (Clob) createLob(ps, true, new LobCallback() { + @Override public void populateLob(Object lob) throws Exception { Method methodToInvoke = lob.getClass().getMethod("getCharacterOutputStream", (Class[]) null); Writer writer = (Writer) methodToInvoke.invoke(lob, (Object[]) null); @@ -451,12 +463,14 @@ public class OracleLobHandler extends AbstractLobHandler { } } + @Override public void setClobAsAsciiStream( PreparedStatement ps, int paramIndex, final InputStream asciiStream, int contentLength) throws SQLException { if (asciiStream != null) { Clob clob = (Clob) createLob(ps, true, new LobCallback() { + @Override public void populateLob(Object lob) throws Exception { Method methodToInvoke = lob.getClass().getMethod("getAsciiOutputStream", (Class[]) null); OutputStream out = (OutputStream) methodToInvoke.invoke(lob, (Object[]) null); @@ -474,12 +488,14 @@ public class OracleLobHandler extends AbstractLobHandler { } } + @Override public void setClobAsCharacterStream( PreparedStatement ps, int paramIndex, final Reader characterStream, int contentLength) throws SQLException { if (characterStream != null) { Clob clob = (Clob) createLob(ps, true, new LobCallback() { + @Override public void populateLob(Object lob) throws Exception { Method methodToInvoke = lob.getClass().getMethod("getCharacterOutputStream", (Class[]) null); Writer writer = (Writer) methodToInvoke.invoke(lob, (Object[]) null); @@ -553,7 +569,7 @@ public class OracleLobHandler extends AbstractLobHandler { /** * Create and open an oracle.sql.BLOB/CLOB instance via reflection. */ - protected Object prepareLob(Connection con, Class lobClass) throws Exception { + protected Object prepareLob(Connection con, Class<?> lobClass) throws Exception { /* BLOB blob = BLOB.createTemporary(con, false, BLOB.DURATION_SESSION); blob.open(BLOB.MODE_READWRITE); @@ -570,9 +586,10 @@ public class OracleLobHandler extends AbstractLobHandler { /** * Free all temporary BLOBs and CLOBs created by this creator. */ + @Override public void close() { try { - for (Iterator it = this.temporaryLobs.iterator(); it.hasNext();) { + for (Iterator<?> it = this.temporaryLobs.iterator(); it.hasNext();) { /* BLOB blob = (BLOB) it.next(); blob.freeTemporary(); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/PassThroughBlob.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/PassThroughBlob.java index 822b3e48..d55a0fd5 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/PassThroughBlob.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/PassThroughBlob.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,47 +49,58 @@ class PassThroughBlob implements Blob { } + @Override public long length() throws SQLException { return this.contentLength; } + @Override public InputStream getBinaryStream() throws SQLException { return (this.content != null ? new ByteArrayInputStream(this.content) : this.binaryStream); } + @Override public InputStream getBinaryStream(long pos, long length) throws SQLException { throw new UnsupportedOperationException(); } + @Override public OutputStream setBinaryStream(long pos) throws SQLException { throw new UnsupportedOperationException(); } + @Override public byte[] getBytes(long pos, int length) throws SQLException { throw new UnsupportedOperationException(); } + @Override public int setBytes(long pos, byte[] bytes) throws SQLException { throw new UnsupportedOperationException(); } + @Override public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException { throw new UnsupportedOperationException(); } + @Override public long position(byte pattern[], long start) throws SQLException { throw new UnsupportedOperationException(); } + @Override public long position(Blob pattern, long start) throws SQLException { throw new UnsupportedOperationException(); } + @Override public void truncate(long len) throws SQLException { throw new UnsupportedOperationException(); } + @Override public void free() throws SQLException { // no-op } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/PassThroughClob.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/PassThroughClob.java index 1effc342..82e5d004 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/PassThroughClob.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/PassThroughClob.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -64,10 +64,12 @@ class PassThroughClob implements Clob { } + @Override public long length() throws SQLException { return this.contentLength; } + @Override public Reader getCharacterStream() throws SQLException { try { if (this.content != null) { @@ -85,6 +87,7 @@ class PassThroughClob implements Clob { } } + @Override public InputStream getAsciiStream() throws SQLException { try { if (this.content != null) { @@ -107,42 +110,52 @@ class PassThroughClob implements Clob { } + @Override public Reader getCharacterStream(long pos, long length) throws SQLException { throw new UnsupportedOperationException(); } + @Override public Writer setCharacterStream(long pos) throws SQLException { throw new UnsupportedOperationException(); } + @Override public OutputStream setAsciiStream(long pos) throws SQLException { throw new UnsupportedOperationException(); } + @Override public String getSubString(long pos, int length) throws SQLException { throw new UnsupportedOperationException(); } + @Override public int setString(long pos, String str) throws SQLException { throw new UnsupportedOperationException(); } + @Override public int setString(long pos, String str, int offset, int len) throws SQLException { throw new UnsupportedOperationException(); } + @Override public long position(String searchstr, long start) throws SQLException { throw new UnsupportedOperationException(); } + @Override public long position(Clob searchstr, long start) throws SQLException { throw new UnsupportedOperationException(); } + @Override public void truncate(long len) throws SQLException { throw new UnsupportedOperationException(); } + @Override public void free() throws SQLException { // no-op } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/TemporaryLobCreator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/TemporaryLobCreator.java index f8c52660..fbe1b557 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/TemporaryLobCreator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/TemporaryLobCreator.java @@ -55,6 +55,7 @@ public class TemporaryLobCreator implements LobCreator { private final Set<Clob> temporaryClobs = new LinkedHashSet<Clob>(1); + @Override public void setBlobAsBytes(PreparedStatement ps, int paramIndex, byte[] content) throws SQLException { @@ -70,6 +71,7 @@ public class TemporaryLobCreator implements LobCreator { } } + @Override public void setBlobAsBinaryStream( PreparedStatement ps, int paramIndex, InputStream binaryStream, int contentLength) throws SQLException { @@ -92,6 +94,7 @@ public class TemporaryLobCreator implements LobCreator { } } + @Override public void setClobAsString(PreparedStatement ps, int paramIndex, String content) throws SQLException { @@ -107,6 +110,7 @@ public class TemporaryLobCreator implements LobCreator { } } + @Override public void setClobAsAsciiStream( PreparedStatement ps, int paramIndex, InputStream asciiStream, int contentLength) throws SQLException { @@ -129,6 +133,7 @@ public class TemporaryLobCreator implements LobCreator { } } + @Override public void setClobAsCharacterStream( PreparedStatement ps, int paramIndex, Reader characterStream, int contentLength) throws SQLException { @@ -151,6 +156,7 @@ public class TemporaryLobCreator implements LobCreator { } } + @Override public void close() { try { for (Blob blob : this.temporaryBlobs) { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/C3P0NativeJdbcExtractor.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/C3P0NativeJdbcExtractor.java index 186b28ba..d109506b 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/C3P0NativeJdbcExtractor.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/C3P0NativeJdbcExtractor.java @@ -63,7 +63,7 @@ public class C3P0NativeJdbcExtractor extends NativeJdbcExtractorAdapter { public C3P0NativeJdbcExtractor() { try { - this.getRawConnectionMethod = getClass().getMethod("getRawConnection", new Class[] {Connection.class}); + this.getRawConnectionMethod = getClass().getMethod("getRawConnection", new Class<?>[] {Connection.class}); } catch (NoSuchMethodException ex) { throw new IllegalStateException("Internal error in C3P0NativeJdbcExtractor: " + ex.getMessage()); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/CommonsDbcpNativeJdbcExtractor.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/CommonsDbcpNativeJdbcExtractor.java index 964f31d5..ee7d46f0 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/CommonsDbcpNativeJdbcExtractor.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/CommonsDbcpNativeJdbcExtractor.java @@ -63,7 +63,7 @@ public class CommonsDbcpNativeJdbcExtractor extends NativeJdbcExtractorAdapter { return null; } try { - Class classToAnalyze = obj.getClass(); + Class<?> classToAnalyze = obj.getClass(); while (!Modifier.isPublic(classToAnalyze.getModifiers())) { classToAnalyze = classToAnalyze.getSuperclass(); if (classToAnalyze == null) { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/JBossNativeJdbcExtractor.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/JBossNativeJdbcExtractor.java index 81b2d2ae..e85a1efe 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/JBossNativeJdbcExtractor.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/JBossNativeJdbcExtractor.java @@ -55,11 +55,11 @@ public class JBossNativeJdbcExtractor extends NativeJdbcExtractorAdapter { private static final String JBOSS_RESOURCE_PREFIX = "org.jboss.resource.adapter.jdbc."; - private Class wrappedConnectionClass; + private Class<?> wrappedConnectionClass; - private Class wrappedStatementClass; + private Class<?> wrappedStatementClass; - private Class wrappedResultSetClass; + private Class<?> wrappedResultSetClass; private Method getUnderlyingConnectionMethod; diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/NativeJdbcExtractorAdapter.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/NativeJdbcExtractorAdapter.java index 2614338b..60d859b7 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/NativeJdbcExtractorAdapter.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/NativeJdbcExtractorAdapter.java @@ -61,6 +61,7 @@ public abstract class NativeJdbcExtractorAdapter implements NativeJdbcExtractor /** * Return {@code false} by default. */ + @Override public boolean isNativeConnectionNecessaryForNativeStatements() { return false; } @@ -68,6 +69,7 @@ public abstract class NativeJdbcExtractorAdapter implements NativeJdbcExtractor /** * Return {@code false} by default. */ + @Override public boolean isNativeConnectionNecessaryForNativePreparedStatements() { return false; } @@ -75,6 +77,7 @@ public abstract class NativeJdbcExtractorAdapter implements NativeJdbcExtractor /** * Return {@code false} by default. */ + @Override public boolean isNativeConnectionNecessaryForNativeCallableStatements() { return false; } @@ -91,6 +94,7 @@ public abstract class NativeJdbcExtractorAdapter implements NativeJdbcExtractor * @see org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy * @see org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy */ + @Override public Connection getNativeConnection(Connection con) throws SQLException { if (con == null) { return null; @@ -128,6 +132,7 @@ public abstract class NativeJdbcExtractorAdapter implements NativeJdbcExtractor * @see #getNativeConnection * @see Statement#getConnection */ + @Override public Connection getNativeConnectionFromStatement(Statement stmt) throws SQLException { if (stmt == null) { return null; @@ -138,6 +143,7 @@ public abstract class NativeJdbcExtractorAdapter implements NativeJdbcExtractor /** * Not able to unwrap: return passed-in Statement. */ + @Override public Statement getNativeStatement(Statement stmt) throws SQLException { return stmt; } @@ -145,6 +151,7 @@ public abstract class NativeJdbcExtractorAdapter implements NativeJdbcExtractor /** * Not able to unwrap: return passed-in PreparedStatement. */ + @Override public PreparedStatement getNativePreparedStatement(PreparedStatement ps) throws SQLException { return ps; } @@ -152,6 +159,7 @@ public abstract class NativeJdbcExtractorAdapter implements NativeJdbcExtractor /** * Not able to unwrap: return passed-in CallableStatement. */ + @Override public CallableStatement getNativeCallableStatement(CallableStatement cs) throws SQLException { return cs; } @@ -159,6 +167,7 @@ public abstract class NativeJdbcExtractorAdapter implements NativeJdbcExtractor /** * Not able to unwrap: return passed-in ResultSet. */ + @Override public ResultSet getNativeResultSet(ResultSet rs) throws SQLException { return rs; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/SimpleNativeJdbcExtractor.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/SimpleNativeJdbcExtractor.java index 0d00da4d..fa0a1efc 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/SimpleNativeJdbcExtractor.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/SimpleNativeJdbcExtractor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,22 +38,14 @@ package org.springframework.jdbc.support.nativejdbc; * <p>SimpleNativeJdbcExtractor is a common choice for use with OracleLobHandler, * which just needs Connection unwrapping via the * {@link #getNativeConnectionFromStatement} method. This usage will work - * with almost any connection pool. Known to work are, for example: - * <ul> - * <li>Caucho Resin 2.1.x, 3.0.x - * <li>Sun Java System Application Server 8 - * <li>Oracle OC4J 9.0.3, 9.0.4 - * <li>C3P0 0.8.x - * <li>Jakarta Commons DBCP 1.0, 1.1, 1.2 (used in Tomcat 4.1.x, 5.0.x) - * <li>JBoss 3.2.x - * </ul> + * with almost any connection pool. * * <p>For full usage with JdbcTemplate, i.e. to also provide Statement unwrapping: * <ul> * <li>Use a default SimpleNativeJdbcExtractor for Resin and SJSAS (no JDBC * Statement objects are wrapped, therefore no special unwrapping is necessary). * <li>Use a SimpleNativeJdbcExtractor with all "nativeConnectionNecessaryForXxx" - * flags set to "true" for OC4J and C3P0 (all JDBC Statement objects are wrapped, + * flags set to "true" for C3P0 (all JDBC Statement objects are wrapped, * but none of the wrappers allow for unwrapping). * <li>Use a CommonsDbcpNativeJdbcExtractor for Jakarta Commons DBCP respectively * a JBossNativeJdbcExtractor for JBoss (all JDBC Statement objects are wrapped, diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/WebLogicNativeJdbcExtractor.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/WebLogicNativeJdbcExtractor.java index 09129320..aa77ddca 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/WebLogicNativeJdbcExtractor.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/WebLogicNativeJdbcExtractor.java @@ -46,7 +46,7 @@ public class WebLogicNativeJdbcExtractor extends NativeJdbcExtractorAdapter { private static final String JDBC_EXTENSION_NAME = "weblogic.jdbc.extensions.WLConnection"; - private final Class jdbcExtensionClass; + private final Class<?> jdbcExtensionClass; private final Method getVendorConnectionMethod; diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/WebSphereNativeJdbcExtractor.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/WebSphereNativeJdbcExtractor.java index b225ea19..55e818d3 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/WebSphereNativeJdbcExtractor.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/nativejdbc/WebSphereNativeJdbcExtractor.java @@ -45,7 +45,7 @@ public class WebSphereNativeJdbcExtractor extends NativeJdbcExtractorAdapter { private static final String JDBC_ADAPTER_UTIL_NAME = "com.ibm.ws.rsadapter.jdbc.WSJdbcUtil"; - private Class webSphereConnectionClass; + private Class<?> webSphereConnectionClass; private Method webSphereNativeConnectionMethod; @@ -57,9 +57,9 @@ public class WebSphereNativeJdbcExtractor extends NativeJdbcExtractorAdapter { public WebSphereNativeJdbcExtractor() { try { this.webSphereConnectionClass = getClass().getClassLoader().loadClass(JDBC_ADAPTER_CONNECTION_NAME); - Class jdbcAdapterUtilClass = getClass().getClassLoader().loadClass(JDBC_ADAPTER_UTIL_NAME); + Class<?> jdbcAdapterUtilClass = getClass().getClassLoader().loadClass(JDBC_ADAPTER_UTIL_NAME); this.webSphereNativeConnectionMethod = - jdbcAdapterUtilClass.getMethod("getNativeConnection", new Class[] {this.webSphereConnectionClass}); + jdbcAdapterUtilClass.getMethod("getNativeConnection", new Class<?>[] {this.webSphereConnectionClass}); } catch (Exception ex) { throw new IllegalStateException( diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/rowset/ResultSetWrappingSqlRowSet.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/rowset/ResultSetWrappingSqlRowSet.java index 83fb15c1..14d20761 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/rowset/ResultSetWrappingSqlRowSet.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/rowset/ResultSetWrappingSqlRowSet.java @@ -129,6 +129,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSetMetaData#getCatalogName(int) */ + @Override public final SqlRowSetMetaData getMetaData() { return this.rowSetMetaData; } @@ -136,6 +137,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#findColumn(String) */ + @Override public int findColumn(String columnLabel) throws InvalidResultSetAccessException { Integer columnIndex = this.columnLabelMap.get(columnLabel); if (columnIndex != null) { @@ -157,6 +159,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getBigDecimal(int) */ + @Override public BigDecimal getBigDecimal(int columnIndex) throws InvalidResultSetAccessException { try { return this.resultSet.getBigDecimal(columnIndex); @@ -169,6 +172,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getBigDecimal(String) */ + @Override public BigDecimal getBigDecimal(String columnLabel) throws InvalidResultSetAccessException { return getBigDecimal(findColumn(columnLabel)); } @@ -176,6 +180,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getBoolean(int) */ + @Override public boolean getBoolean(int columnIndex) throws InvalidResultSetAccessException { try { return this.resultSet.getBoolean(columnIndex); @@ -188,6 +193,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getBoolean(String) */ + @Override public boolean getBoolean(String columnLabel) throws InvalidResultSetAccessException { return getBoolean(findColumn(columnLabel)); } @@ -195,6 +201,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getByte(int) */ + @Override public byte getByte(int columnIndex) throws InvalidResultSetAccessException { try { return this.resultSet.getByte(columnIndex); @@ -207,6 +214,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getByte(String) */ + @Override public byte getByte(String columnLabel) throws InvalidResultSetAccessException { return getByte(findColumn(columnLabel)); } @@ -214,6 +222,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getDate(int) */ + @Override public Date getDate(int columnIndex) throws InvalidResultSetAccessException { try { return this.resultSet.getDate(columnIndex); @@ -226,6 +235,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getDate(String) */ + @Override public Date getDate(String columnLabel) throws InvalidResultSetAccessException { return getDate(findColumn(columnLabel)); } @@ -233,6 +243,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getDate(int, Calendar) */ + @Override public Date getDate(int columnIndex, Calendar cal) throws InvalidResultSetAccessException { try { return this.resultSet.getDate(columnIndex, cal); @@ -245,6 +256,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getDate(String, Calendar) */ + @Override public Date getDate(String columnLabel, Calendar cal) throws InvalidResultSetAccessException { return getDate(findColumn(columnLabel), cal); } @@ -252,6 +264,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getDouble(int) */ + @Override public double getDouble(int columnIndex) throws InvalidResultSetAccessException { try { return this.resultSet.getDouble(columnIndex); @@ -264,6 +277,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getDouble(String) */ + @Override public double getDouble(String columnLabel) throws InvalidResultSetAccessException { return getDouble(findColumn(columnLabel)); } @@ -271,6 +285,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getFloat(int) */ + @Override public float getFloat(int columnIndex) throws InvalidResultSetAccessException { try { return this.resultSet.getFloat(columnIndex); @@ -283,6 +298,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getFloat(String) */ + @Override public float getFloat(String columnLabel) throws InvalidResultSetAccessException { return getFloat(findColumn(columnLabel)); } @@ -290,6 +306,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getInt(int) */ + @Override public int getInt(int columnIndex) throws InvalidResultSetAccessException { try { return this.resultSet.getInt(columnIndex); @@ -302,6 +319,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getInt(String) */ + @Override public int getInt(String columnLabel) throws InvalidResultSetAccessException { return getInt(findColumn(columnLabel)); } @@ -309,6 +327,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getLong(int) */ + @Override public long getLong(int columnIndex) throws InvalidResultSetAccessException { try { return this.resultSet.getLong(columnIndex); @@ -321,6 +340,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getLong(String) */ + @Override public long getLong(String columnLabel) throws InvalidResultSetAccessException { return getLong(findColumn(columnLabel)); } @@ -328,6 +348,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getObject(int) */ + @Override public Object getObject(int columnIndex) throws InvalidResultSetAccessException { try { return this.resultSet.getObject(columnIndex); @@ -340,6 +361,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getObject(String) */ + @Override public Object getObject(String columnLabel) throws InvalidResultSetAccessException { return getObject(findColumn(columnLabel)); } @@ -347,6 +369,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getObject(int, Map) */ + @Override public Object getObject(int columnIndex, Map<String, Class<?>> map) throws InvalidResultSetAccessException { try { return this.resultSet.getObject(columnIndex, map); @@ -359,6 +382,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getObject(String, Map) */ + @Override public Object getObject(String columnLabel, Map<String, Class<?>> map) throws InvalidResultSetAccessException { return getObject(findColumn(columnLabel), map); } @@ -366,6 +390,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getShort(int) */ + @Override public short getShort(int columnIndex) throws InvalidResultSetAccessException { try { return this.resultSet.getShort(columnIndex); @@ -378,6 +403,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getShort(String) */ + @Override public short getShort(String columnLabel) throws InvalidResultSetAccessException { return getShort(findColumn(columnLabel)); } @@ -385,6 +411,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getString(int) */ + @Override public String getString(int columnIndex) throws InvalidResultSetAccessException { try { return this.resultSet.getString(columnIndex); @@ -397,6 +424,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getString(String) */ + @Override public String getString(String columnLabel) throws InvalidResultSetAccessException { return getString(findColumn(columnLabel)); } @@ -404,6 +432,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getTime(int) */ + @Override public Time getTime(int columnIndex) throws InvalidResultSetAccessException { try { return this.resultSet.getTime(columnIndex); @@ -416,6 +445,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getTime(String) */ + @Override public Time getTime(String columnLabel) throws InvalidResultSetAccessException { return getTime(findColumn(columnLabel)); } @@ -423,6 +453,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getTime(int, Calendar) */ + @Override public Time getTime(int columnIndex, Calendar cal) throws InvalidResultSetAccessException { try { return this.resultSet.getTime(columnIndex, cal); @@ -435,6 +466,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getTime(String, Calendar) */ + @Override public Time getTime(String columnLabel, Calendar cal) throws InvalidResultSetAccessException { return getTime(findColumn(columnLabel), cal); } @@ -442,6 +474,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getTimestamp(int) */ + @Override public Timestamp getTimestamp(int columnIndex) throws InvalidResultSetAccessException { try { return this.resultSet.getTimestamp(columnIndex); @@ -454,6 +487,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getTimestamp(String) */ + @Override public Timestamp getTimestamp(String columnLabel) throws InvalidResultSetAccessException { return getTimestamp(findColumn(columnLabel)); } @@ -461,6 +495,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getTimestamp(int, Calendar) */ + @Override public Timestamp getTimestamp(int columnIndex, Calendar cal) throws InvalidResultSetAccessException { try { return this.resultSet.getTimestamp(columnIndex, cal); @@ -473,6 +508,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getTimestamp(String, Calendar) */ + @Override public Timestamp getTimestamp(String columnLabel, Calendar cal) throws InvalidResultSetAccessException { return getTimestamp(findColumn(columnLabel), cal); } @@ -483,6 +519,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#absolute(int) */ + @Override public boolean absolute(int row) throws InvalidResultSetAccessException { try { return this.resultSet.absolute(row); @@ -495,6 +532,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#afterLast() */ + @Override public void afterLast() throws InvalidResultSetAccessException { try { this.resultSet.afterLast(); @@ -507,6 +545,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#beforeFirst() */ + @Override public void beforeFirst() throws InvalidResultSetAccessException { try { this.resultSet.beforeFirst(); @@ -519,6 +558,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#first() */ + @Override public boolean first() throws InvalidResultSetAccessException { try { return this.resultSet.first(); @@ -531,6 +571,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#getRow() */ + @Override public int getRow() throws InvalidResultSetAccessException { try { return this.resultSet.getRow(); @@ -543,6 +584,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#isAfterLast() */ + @Override public boolean isAfterLast() throws InvalidResultSetAccessException { try { return this.resultSet.isAfterLast(); @@ -555,6 +597,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#isBeforeFirst() */ + @Override public boolean isBeforeFirst() throws InvalidResultSetAccessException { try { return this.resultSet.isBeforeFirst(); @@ -567,6 +610,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#isFirst() */ + @Override public boolean isFirst() throws InvalidResultSetAccessException { try { return this.resultSet.isFirst(); @@ -579,6 +623,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#isLast() */ + @Override public boolean isLast() throws InvalidResultSetAccessException { try { return this.resultSet.isLast(); @@ -591,6 +636,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#last() */ + @Override public boolean last() throws InvalidResultSetAccessException { try { return this.resultSet.last(); @@ -603,6 +649,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#next() */ + @Override public boolean next() throws InvalidResultSetAccessException { try { return this.resultSet.next(); @@ -615,6 +662,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#previous() */ + @Override public boolean previous() throws InvalidResultSetAccessException { try { return this.resultSet.previous(); @@ -627,6 +675,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#relative(int) */ + @Override public boolean relative(int rows) throws InvalidResultSetAccessException { try { return this.resultSet.relative(rows); @@ -639,6 +688,7 @@ public class ResultSetWrappingSqlRowSet implements SqlRowSet { /** * @see java.sql.ResultSet#wasNull() */ + @Override public boolean wasNull() throws InvalidResultSetAccessException { try { return this.resultSet.wasNull(); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/rowset/ResultSetWrappingSqlRowSetMetaData.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/rowset/ResultSetWrappingSqlRowSetMetaData.java index ababa338..50f03695 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/rowset/ResultSetWrappingSqlRowSetMetaData.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/rowset/ResultSetWrappingSqlRowSetMetaData.java @@ -54,6 +54,7 @@ public class ResultSetWrappingSqlRowSetMetaData implements SqlRowSetMetaData { } + @Override public String getCatalogName(int column) throws InvalidResultSetAccessException { try { return this.resultSetMetaData.getCatalogName(column); @@ -63,6 +64,7 @@ public class ResultSetWrappingSqlRowSetMetaData implements SqlRowSetMetaData { } } + @Override public String getColumnClassName(int column) throws InvalidResultSetAccessException { try { return this.resultSetMetaData.getColumnClassName(column); @@ -72,6 +74,7 @@ public class ResultSetWrappingSqlRowSetMetaData implements SqlRowSetMetaData { } } + @Override public int getColumnCount() throws InvalidResultSetAccessException { try { return this.resultSetMetaData.getColumnCount(); @@ -81,6 +84,7 @@ public class ResultSetWrappingSqlRowSetMetaData implements SqlRowSetMetaData { } } + @Override public String[] getColumnNames() throws InvalidResultSetAccessException { if (this.columnNames == null) { this.columnNames = new String[getColumnCount()]; @@ -91,6 +95,7 @@ public class ResultSetWrappingSqlRowSetMetaData implements SqlRowSetMetaData { return this.columnNames; } + @Override public int getColumnDisplaySize(int column) throws InvalidResultSetAccessException { try { return this.resultSetMetaData.getColumnDisplaySize(column); @@ -100,6 +105,7 @@ public class ResultSetWrappingSqlRowSetMetaData implements SqlRowSetMetaData { } } + @Override public String getColumnLabel(int column) throws InvalidResultSetAccessException { try { return this.resultSetMetaData.getColumnLabel(column); @@ -109,6 +115,7 @@ public class ResultSetWrappingSqlRowSetMetaData implements SqlRowSetMetaData { } } + @Override public String getColumnName(int column) throws InvalidResultSetAccessException { try { return this.resultSetMetaData.getColumnName(column); @@ -118,6 +125,7 @@ public class ResultSetWrappingSqlRowSetMetaData implements SqlRowSetMetaData { } } + @Override public int getColumnType(int column) throws InvalidResultSetAccessException { try { return this.resultSetMetaData.getColumnType(column); @@ -127,6 +135,7 @@ public class ResultSetWrappingSqlRowSetMetaData implements SqlRowSetMetaData { } } + @Override public String getColumnTypeName(int column) throws InvalidResultSetAccessException { try { return this.resultSetMetaData.getColumnTypeName(column); @@ -136,6 +145,7 @@ public class ResultSetWrappingSqlRowSetMetaData implements SqlRowSetMetaData { } } + @Override public int getPrecision(int column) throws InvalidResultSetAccessException { try { return this.resultSetMetaData.getPrecision(column); @@ -145,6 +155,7 @@ public class ResultSetWrappingSqlRowSetMetaData implements SqlRowSetMetaData { } } + @Override public int getScale(int column) throws InvalidResultSetAccessException { try { return this.resultSetMetaData.getScale(column); @@ -154,6 +165,7 @@ public class ResultSetWrappingSqlRowSetMetaData implements SqlRowSetMetaData { } } + @Override public String getSchemaName(int column) throws InvalidResultSetAccessException { try { return this.resultSetMetaData.getSchemaName(column); @@ -163,6 +175,7 @@ public class ResultSetWrappingSqlRowSetMetaData implements SqlRowSetMetaData { } } + @Override public String getTableName(int column) throws InvalidResultSetAccessException { try { return this.resultSetMetaData.getTableName(column); @@ -172,6 +185,7 @@ public class ResultSetWrappingSqlRowSetMetaData implements SqlRowSetMetaData { } } + @Override public boolean isCaseSensitive(int column) throws InvalidResultSetAccessException { try { return this.resultSetMetaData.isCaseSensitive(column); @@ -181,6 +195,7 @@ public class ResultSetWrappingSqlRowSetMetaData implements SqlRowSetMetaData { } } + @Override public boolean isCurrency(int column) throws InvalidResultSetAccessException { try { return this.resultSetMetaData.isCurrency(column); @@ -190,6 +205,7 @@ public class ResultSetWrappingSqlRowSetMetaData implements SqlRowSetMetaData { } } + @Override public boolean isSigned(int column) throws InvalidResultSetAccessException { try { return this.resultSetMetaData.isSigned(column); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/xml/Jdbc4SqlXmlHandler.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/xml/Jdbc4SqlXmlHandler.java index 13f03633..247e5368 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/xml/Jdbc4SqlXmlHandler.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/xml/Jdbc4SqlXmlHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLXML; +import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.dom.DOMResult; import javax.xml.transform.dom.DOMSource; @@ -50,38 +51,46 @@ public class Jdbc4SqlXmlHandler implements SqlXmlHandler { // Convenience methods for accessing XML content //------------------------------------------------------------------------- + @Override public String getXmlAsString(ResultSet rs, String columnName) throws SQLException { return rs.getSQLXML(columnName).getString(); } + @Override public String getXmlAsString(ResultSet rs, int columnIndex) throws SQLException { return rs.getSQLXML(columnIndex).getString(); } + @Override public InputStream getXmlAsBinaryStream(ResultSet rs, String columnName) throws SQLException { return rs.getSQLXML(columnName).getBinaryStream(); } + @Override public InputStream getXmlAsBinaryStream(ResultSet rs, int columnIndex) throws SQLException { return rs.getSQLXML(columnIndex).getBinaryStream(); } + @Override public Reader getXmlAsCharacterStream(ResultSet rs, String columnName) throws SQLException { return rs.getSQLXML(columnName).getCharacterStream(); } + @Override public Reader getXmlAsCharacterStream(ResultSet rs, int columnIndex) throws SQLException { return rs.getSQLXML(columnIndex).getCharacterStream(); } - @SuppressWarnings("unchecked") - public Source getXmlAsSource(ResultSet rs, String columnName, Class sourceClass) throws SQLException { - return rs.getSQLXML(columnName).getSource(sourceClass != null ? sourceClass : DOMSource.class); + @Override + public Source getXmlAsSource(ResultSet rs, String columnName, Class<? extends Source> sourceClass) throws SQLException { + SQLXML xmlObject = rs.getSQLXML(columnName); + return (sourceClass != null ? xmlObject.getSource(sourceClass) : xmlObject.getSource(DOMSource.class)); } - @SuppressWarnings("unchecked") - public Source getXmlAsSource(ResultSet rs, int columnIndex, Class sourceClass) throws SQLException { - return rs.getSQLXML(columnIndex).getSource(sourceClass != null ? sourceClass : DOMSource.class); + @Override + public Source getXmlAsSource(ResultSet rs, int columnIndex, Class<? extends Source> sourceClass) throws SQLException { + SQLXML xmlObject = rs.getSQLXML(columnIndex); + return (sourceClass != null ? xmlObject.getSource(sourceClass) : xmlObject.getSource(DOMSource.class)); } @@ -89,6 +98,7 @@ public class Jdbc4SqlXmlHandler implements SqlXmlHandler { // Convenience methods for building XML content //------------------------------------------------------------------------- + @Override public SqlXmlValue newSqlXmlValue(final String value) { return new AbstractJdbc4SqlXmlValue() { @Override @@ -98,6 +108,7 @@ public class Jdbc4SqlXmlHandler implements SqlXmlHandler { }; } + @Override public SqlXmlValue newSqlXmlValue(final XmlBinaryStreamProvider provider) { return new AbstractJdbc4SqlXmlValue() { @Override @@ -107,6 +118,7 @@ public class Jdbc4SqlXmlHandler implements SqlXmlHandler { }; } + @Override public SqlXmlValue newSqlXmlValue(final XmlCharacterStreamProvider provider) { return new AbstractJdbc4SqlXmlValue() { @Override @@ -116,16 +128,17 @@ public class Jdbc4SqlXmlHandler implements SqlXmlHandler { }; } - public SqlXmlValue newSqlXmlValue(final Class resultClass, final XmlResultProvider provider) { + @Override + public SqlXmlValue newSqlXmlValue(final Class<? extends Result> resultClass, final XmlResultProvider provider) { return new AbstractJdbc4SqlXmlValue() { @Override - @SuppressWarnings("unchecked") protected void provideXml(SQLXML xmlObject) throws SQLException, IOException { provider.provideXml(xmlObject.setResult(resultClass)); } }; } + @Override public SqlXmlValue newSqlXmlValue(final Document document) { return new AbstractJdbc4SqlXmlValue() { @Override @@ -143,6 +156,7 @@ public class Jdbc4SqlXmlHandler implements SqlXmlHandler { private SQLXML xmlObject; + @Override public void setValue(PreparedStatement ps, int paramIndex) throws SQLException { this.xmlObject = ps.getConnection().createSQLXML(); try { @@ -154,6 +168,7 @@ public class Jdbc4SqlXmlHandler implements SqlXmlHandler { ps.setSQLXML(paramIndex, this.xmlObject); } + @Override public void cleanup() { try { this.xmlObject.free(); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/xml/SqlXmlHandler.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/xml/SqlXmlHandler.java index 2a702794..a7a59318 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/xml/SqlXmlHandler.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/xml/SqlXmlHandler.java @@ -21,6 +21,7 @@ import java.io.Reader; import java.sql.ResultSet; import java.sql.SQLException; +import javax.xml.transform.Result; import javax.xml.transform.Source; import org.w3c.dom.Document; @@ -146,7 +147,7 @@ public interface SqlXmlHandler { * @see java.sql.ResultSet#getSQLXML * @see java.sql.SQLXML#getSource */ - Source getXmlAsSource(ResultSet rs, String columnName, Class sourceClass) throws SQLException; + Source getXmlAsSource(ResultSet rs, String columnName, Class<? extends Source> sourceClass) throws SQLException; /** * Retrieve the given column as Source implemented using the specified source class @@ -161,7 +162,7 @@ public interface SqlXmlHandler { * @see java.sql.ResultSet#getSQLXML * @see java.sql.SQLXML#getSource */ - Source getXmlAsSource(ResultSet rs, int columnIndex, Class sourceClass) throws SQLException; + Source getXmlAsSource(ResultSet rs, int columnIndex, Class<? extends Source> sourceClass) throws SQLException; //------------------------------------------------------------------------- @@ -207,7 +208,7 @@ public interface SqlXmlHandler { * @see SqlXmlValue * @see java.sql.SQLXML#setResult(Class) */ - SqlXmlValue newSqlXmlValue(Class resultClass, XmlResultProvider provider); + SqlXmlValue newSqlXmlValue(Class<? extends Result> resultClass, XmlResultProvider provider); /** * Create a {@code SqlXmlValue} instance for the given XML data, diff --git a/spring-jdbc/src/main/resources/META-INF/spring.schemas b/spring-jdbc/src/main/resources/META-INF/spring.schemas index d6a730d3..82513e67 100644 --- a/spring-jdbc/src/main/resources/META-INF/spring.schemas +++ b/spring-jdbc/src/main/resources/META-INF/spring.schemas @@ -1,4 +1,5 @@ http\://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd=org/springframework/jdbc/config/spring-jdbc-3.0.xsd http\://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd=org/springframework/jdbc/config/spring-jdbc-3.1.xsd http\://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd=org/springframework/jdbc/config/spring-jdbc-3.2.xsd -http\://www.springframework.org/schema/jdbc/spring-jdbc.xsd=org/springframework/jdbc/config/spring-jdbc-3.2.xsd +http\://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd=org/springframework/jdbc/config/spring-jdbc-4.0.xsd +http\://www.springframework.org/schema/jdbc/spring-jdbc.xsd=org/springframework/jdbc/config/spring-jdbc-4.0.xsd diff --git a/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.0.xsd b/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.0.xsd index 72c89605..1b1ad19b 100644 --- a/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.0.xsd +++ b/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.0.xsd @@ -1,14 +1,15 @@ <?xml version="1.0" encoding="UTF-8" ?> + <xsd:schema xmlns="http://www.springframework.org/schema/jdbc" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" - xmlns:tool="http://www.springframework.org/schema/tool" - targetNamespace="http://www.springframework.org/schema/jdbc" - elementFormDefault="qualified" attributeFormDefault="unqualified"> + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:beans="http://www.springframework.org/schema/beans" + xmlns:tool="http://www.springframework.org/schema/tool" + targetNamespace="http://www.springframework.org/schema/jdbc" + elementFormDefault="qualified" + attributeFormDefault="unqualified"> - <xsd:import namespace="http://www.springframework.org/schema/beans" - schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" /> - <xsd:import namespace="http://www.springframework.org/schema/tool" - schemaLocation="http://www.springframework.org/schema/tool/spring-tool-3.0.xsd" /> + <xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" /> + <xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-3.0.xsd" /> <xsd:element name="embedded-database"> <xsd:annotation> diff --git a/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.1.xsd b/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.1.xsd index cc1fb608..9b8edee5 100644 --- a/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.1.xsd +++ b/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.1.xsd @@ -1,14 +1,15 @@ <?xml version="1.0" encoding="UTF-8" ?> + <xsd:schema xmlns="http://www.springframework.org/schema/jdbc" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" - xmlns:tool="http://www.springframework.org/schema/tool" - targetNamespace="http://www.springframework.org/schema/jdbc" - elementFormDefault="qualified" attributeFormDefault="unqualified"> + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:beans="http://www.springframework.org/schema/beans" + xmlns:tool="http://www.springframework.org/schema/tool" + targetNamespace="http://www.springframework.org/schema/jdbc" + elementFormDefault="qualified" + attributeFormDefault="unqualified"> - <xsd:import namespace="http://www.springframework.org/schema/beans" - schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.1.xsd" /> - <xsd:import namespace="http://www.springframework.org/schema/tool" - schemaLocation="http://www.springframework.org/schema/tool/spring-tool-3.1.xsd" /> + <xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"/> + <xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-3.1.xsd"/> <xsd:element name="embedded-database"> <xsd:annotation> diff --git a/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.2.xsd b/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.2.xsd index d88ac708..a6618a59 100644 --- a/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.2.xsd +++ b/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.2.xsd @@ -1,14 +1,15 @@ <?xml version="1.0" encoding="UTF-8" ?> + <xsd:schema xmlns="http://www.springframework.org/schema/jdbc" - xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" - xmlns:tool="http://www.springframework.org/schema/tool" - targetNamespace="http://www.springframework.org/schema/jdbc" - elementFormDefault="qualified" attributeFormDefault="unqualified"> + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:beans="http://www.springframework.org/schema/beans" + xmlns:tool="http://www.springframework.org/schema/tool" + targetNamespace="http://www.springframework.org/schema/jdbc" + elementFormDefault="qualified" + attributeFormDefault="unqualified"> - <xsd:import namespace="http://www.springframework.org/schema/beans" - schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.2.xsd" /> - <xsd:import namespace="http://www.springframework.org/schema/tool" - schemaLocation="http://www.springframework.org/schema/tool/spring-tool-3.2.xsd" /> + <xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"/> + <xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-3.2.xsd"/> <xsd:element name="embedded-database"> <xsd:annotation> diff --git a/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-4.0.xsd b/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-4.0.xsd new file mode 100644 index 00000000..7ff5db8b --- /dev/null +++ b/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-4.0.xsd @@ -0,0 +1,182 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<xsd:schema xmlns="http://www.springframework.org/schema/jdbc" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:beans="http://www.springframework.org/schema/beans" + xmlns:tool="http://www.springframework.org/schema/tool" + targetNamespace="http://www.springframework.org/schema/jdbc" + elementFormDefault="qualified" + attributeFormDefault="unqualified"> + + <xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"/> + <xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-4.0.xsd"/> + + <xsd:element name="embedded-database"> + <xsd:annotation> + <xsd:documentation source="java:org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactoryBean"><![CDATA[ + Creates an embedded database instance and makes it available to other beans as a javax.sql.DataSource. + ]]></xsd:documentation> + <xsd:appinfo> + <tool:annotation> + <tool:exports type="javax.sql.DataSource"/> + </tool:annotation> + </xsd:appinfo> + </xsd:annotation> + <xsd:complexType> + <xsd:complexContent> + <xsd:extension base="beans:identifiedType"> + <xsd:sequence> + <xsd:element name="script" type="scriptType" minOccurs="0" maxOccurs="unbounded"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + A SQL script to execute during embedded database initialization. + ]]></xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + <xsd:attribute name="type" type="databaseType" default="HSQL"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + The type of embedded database to create, such as HSQL, H2 or Derby. Defaults to HSQL. + ]]></xsd:documentation> + </xsd:annotation> + </xsd:attribute> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + </xsd:element> + + <xsd:element name="initialize-database"> + <xsd:annotation> + <xsd:documentation source="java:org.springframework.jdbc.datasource.init.DataSourceInitializer"><![CDATA[ + Initializes a database instance with SQL scripts provided in nested <script/> elements. + ]]></xsd:documentation> + </xsd:annotation> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="script" type="scriptType" minOccurs="1" maxOccurs="unbounded"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + A SQL script to execute during database initialization. + ]]></xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + <xsd:attribute name="data-source" type="xsd:string" default="dataSource"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + A reference to a data source that should be initialized. Defaults to "dataSource". + ]]></xsd:documentation> + <xsd:appinfo> + <tool:annotation kind="ref"/> + <tool:expected-type type="javax.sql.DataSource"/> + </xsd:appinfo> + </xsd:annotation> + </xsd:attribute> + <xsd:attribute name="enabled" type="xsd:string" use="optional" default="true"> + <xsd:annotation> + <xsd:documentation> + Is this bean "enabled", meaning the scripts will be executed? + Defaults to true, but can be used to switch on and off the initialization depending on the environment. + </xsd:documentation> + </xsd:annotation> + </xsd:attribute> + <xsd:attribute name="ignore-failures" use="optional" default="NONE"> + <xsd:annotation> + <xsd:documentation> + Should failed SQL statements be ignored during initialization? + </xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="NONE"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + Do not ignore failures (the default) + ]]></xsd:documentation> + </xsd:annotation> + </xsd:enumeration> + <xsd:enumeration value="DROPS"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + Ignore failed DROP statements + ]]></xsd:documentation> + </xsd:annotation> + </xsd:enumeration> + <xsd:enumeration value="ALL"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + Ignore all failures + ]]></xsd:documentation> + </xsd:annotation> + </xsd:enumeration> + </xsd:restriction> + </xsd:simpleType> + </xsd:attribute> + </xsd:complexType> + </xsd:element> + + <xsd:complexType name="scriptType"> + <xsd:attribute name="location" type="xsd:string"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + The resource location of an SQL script to execute. Can be a single script location or a pattern (e.g. classpath:/com/foo/sql/*-data.sql). + ]]></xsd:documentation> + </xsd:annotation> + </xsd:attribute> + <xsd:attribute name="encoding" type="xsd:string"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + The encoding for SQL scripts, if different from the platform encoding. + ]]></xsd:documentation> + </xsd:annotation> + </xsd:attribute> + <xsd:attribute name="separator" type="xsd:string"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + The statement separator in the script (the default is to use ';' if it is present in the script, or '\n' otherwise). + ]]></xsd:documentation> + </xsd:annotation> + </xsd:attribute> + <xsd:attribute name="execution"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + Indicate the timing of the execution of this script. Use INIT to execute on startup (as a bean initialization) and DESTROY to execute on shutdown (as a bean destruction callback). + ]]></xsd:documentation> + </xsd:annotation> + <xsd:simpleType> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="INIT"/> + <xsd:enumeration value="DESTROY"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:attribute> + </xsd:complexType> + + <xsd:simpleType name="databaseType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="HSQL"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + Hyper SQL Java Database Engine + ]]></xsd:documentation> + </xsd:annotation> + </xsd:enumeration> + <xsd:enumeration value="H2"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + H2 Java Database Engine + ]]></xsd:documentation> + </xsd:annotation> + </xsd:enumeration> + <xsd:enumeration value="DERBY"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + Derby Java Database Engine + ]]></xsd:documentation> + </xsd:annotation> + </xsd:enumeration> + </xsd:restriction> + </xsd:simpleType> + +</xsd:schema> diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/Customer.java b/spring-jdbc/src/test/java/org/springframework/jdbc/Customer.java index 7c804be1..46b646b0 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/Customer.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/Customer.java @@ -43,6 +43,7 @@ public class Customer { } + @Override public String toString() { return "Customer: id=" + id + "; forename=" + forename; } diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/config/JdbcNamespaceIntegrationTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/config/JdbcNamespaceIntegrationTests.java index c789afa3..396418b9 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/config/JdbcNamespaceIntegrationTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/config/JdbcNamespaceIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,68 +42,68 @@ import static org.junit.Assert.*; * @author Dave Syer * @author Juergen Hoeller * @author Chris Beams + * @author Sam Brannen */ public class JdbcNamespaceIntegrationTests { @Rule public ExpectedException expected = ExpectedException.none(); + @Test - public void testCreateEmbeddedDatabase() throws Exception { + public void createEmbeddedDatabase() throws Exception { Assume.group(TestGroup.LONG_RUNNING); - - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "org/springframework/jdbc/config/jdbc-config.xml"); - assertCorrectSetup(context, "dataSource", "h2DataSource", "derbyDataSource"); - context.close(); + assertCorrectSetup("jdbc-config.xml", "dataSource", "h2DataSource", "derbyDataSource"); } @Test - public void testCreateEmbeddedDatabaseAgain() throws Exception { + public void createEmbeddedDatabaseAgain() throws Exception { // If Derby isn't cleaned up properly this will fail... Assume.group(TestGroup.LONG_RUNNING); - - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "org/springframework/jdbc/config/jdbc-config.xml"); - assertCorrectSetup(context, "derbyDataSource"); - context.close(); + assertCorrectSetup("jdbc-config.xml", "derbyDataSource"); } @Test - public void testCreateWithResourcePattern() throws Exception { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "org/springframework/jdbc/config/jdbc-config-pattern.xml"); - assertCorrectSetup(context, "dataSource"); - context.close(); + public void createWithResourcePattern() throws Exception { + assertCorrectSetup("jdbc-config-pattern.xml", "dataSource"); } @Test - public void testCreateWithEndings() throws Exception { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "org/springframework/jdbc/config/jdbc-initialize-endings-config.xml"); - assertCorrectSetup(context, 2, "dataSource"); - context.close(); + public void createWithEndings() throws Exception { + assertCorrectSetupAndCloseContext("jdbc-initialize-endings-config.xml", 2, "dataSource"); } @Test - public void testCreateWithEndingsNested() throws Exception { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "org/springframework/jdbc/config/jdbc-initialize-endings-nested-config.xml"); - assertCorrectSetup(context, 2, "dataSource"); - context.close(); + public void createWithEndingsNested() throws Exception { + assertCorrectSetupAndCloseContext("jdbc-initialize-endings-nested-config.xml", 2, "dataSource"); } @Test - public void testCreateAndDestroy() throws Exception { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "org/springframework/jdbc/config/jdbc-destroy-config.xml"); + public void createAndDestroy() throws Exception { + ClassPathXmlApplicationContext context = context("jdbc-destroy-config.xml"); try { DataSource dataSource = context.getBean(DataSource.class); JdbcTemplate template = new JdbcTemplate(dataSource); - assertEquals(1, template.queryForInt("select count(*) from T_TEST")); + assertNumRowsInTestTable(template, 1); context.getBean(DataSourceInitializer.class).destroy(); expected.expect(BadSqlGrammarException.class); // Table has been dropped - assertEquals(1, template.queryForInt("select count(*) from T_TEST")); + assertNumRowsInTestTable(template, 1); + } + finally { + context.close(); + } + } + + @Test + public void createAndDestroyNestedWithHsql() throws Exception { + ClassPathXmlApplicationContext context = context("jdbc-destroy-nested-config.xml"); + try { + DataSource dataSource = context.getBean(DataSource.class); + JdbcTemplate template = new JdbcTemplate(dataSource); + assertNumRowsInTestTable(template, 1); + context.getBean(EmbeddedDatabaseFactoryBean.class).destroy(); + expected.expect(BadSqlGrammarException.class); // Table has been dropped + assertNumRowsInTestTable(template, 1); } finally { context.close(); @@ -111,16 +111,15 @@ public class JdbcNamespaceIntegrationTests { } @Test - public void testCreateAndDestroyNested() throws Exception { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "org/springframework/jdbc/config/jdbc-destroy-nested-config.xml"); + public void createAndDestroyNestedWithH2() throws Exception { + ClassPathXmlApplicationContext context = context("jdbc-destroy-nested-config-h2.xml"); try { DataSource dataSource = context.getBean(DataSource.class); JdbcTemplate template = new JdbcTemplate(dataSource); - assertEquals(1, template.queryForInt("select count(*) from T_TEST")); + assertNumRowsInTestTable(template, 1); context.getBean(EmbeddedDatabaseFactoryBean.class).destroy(); expected.expect(BadSqlGrammarException.class); // Table has been dropped - assertEquals(1, template.queryForInt("select count(*) from T_TEST")); + assertNumRowsInTestTable(template, 1); } finally { context.close(); @@ -128,14 +127,18 @@ public class JdbcNamespaceIntegrationTests { } @Test - public void testMultipleDataSourcesHaveDifferentDatabaseNames() throws Exception { + public void multipleDataSourcesHaveDifferentDatabaseNames() throws Exception { DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); new XmlBeanDefinitionReader(factory).loadBeanDefinitions(new ClassPathResource( - "org/springframework/jdbc/config/jdbc-config-multiple-datasources.xml")); + "jdbc-config-multiple-datasources.xml", getClass())); assertBeanPropertyValueOf("databaseName", "firstDataSource", factory); assertBeanPropertyValueOf("databaseName", "secondDataSource", factory); } + private ClassPathXmlApplicationContext context(String file) { + return new ClassPathXmlApplicationContext(file, getClass()); + } + private void assertBeanPropertyValueOf(String propertyName, String expected, DefaultListableBeanFactory factory) { BeanDefinition bean = factory.getBeanDefinition(expected); PropertyValue value = bean.getPropertyValues().getPropertyValue(propertyName); @@ -143,22 +146,26 @@ public class JdbcNamespaceIntegrationTests { assertThat(value.getValue().toString(), is(expected)); } - private void assertCorrectSetup(ConfigurableApplicationContext context, String... dataSources) { - assertCorrectSetup(context, 1, dataSources); + private void assertNumRowsInTestTable(JdbcTemplate template, int count) { + assertEquals(count, template.queryForObject("select count(*) from T_TEST", Integer.class).intValue()); } - private void assertCorrectSetup(ConfigurableApplicationContext context, int count, String... dataSources) { + private void assertCorrectSetup(String file, String... dataSources) { + assertCorrectSetupAndCloseContext(file, 1, dataSources); + } + + private void assertCorrectSetupAndCloseContext(String file, int count, String... dataSources) { + ConfigurableApplicationContext context = context(file); try { for (String dataSourceName : dataSources) { DataSource dataSource = context.getBean(dataSourceName, DataSource.class); JdbcTemplate template = new JdbcTemplate(dataSource); - assertEquals(count, template.queryForInt("select count(*) from T_TEST")); + assertNumRowsInTestTable(template, count); } } finally { context.close(); } - } } diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateTests.java index ffa2d74d..e8d9e19c 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateTests.java @@ -16,6 +16,7 @@ package org.springframework.jdbc.core; +import java.sql.BatchUpdateException; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DatabaseMetaData; @@ -459,6 +460,24 @@ public class JdbcTemplateTests { } @Test + public void testBatchUpdateWithBatchFailure() throws Exception { + final String[] sql = {"A", "B", "C", "D"}; + given(this.statement.executeBatch()).willThrow( + new BatchUpdateException(new int[] { 1, Statement.EXECUTE_FAILED, 1, + Statement.EXECUTE_FAILED })); + mockDatabaseMetaData(true); + given(this.connection.createStatement()).willReturn(this.statement); + + JdbcTemplate template = new JdbcTemplate(this.dataSource, false); + try { + template.batchUpdate(sql); + } + catch (UncategorizedSQLException ex) { + assertThat(ex.getSql(), equalTo("B; D")); + } + } + + @Test public void testBatchUpdateWithNoBatchSupport() throws Exception { final String[] sql = {"UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = 1", "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = 2"}; diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/core/RowMapperTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/core/RowMapperTests.java index a44686f3..c31d0809 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/core/RowMapperTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/core/RowMapperTests.java @@ -50,6 +50,7 @@ public class RowMapperTests extends TestCase { private List<TestBean> result; + @Override @Before public void setUp() throws SQLException { connection = mock(Connection.class); diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/core/StatementCreatorUtilsTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/core/StatementCreatorUtilsTests.java index d9d6dd15..88f1e510 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/core/StatementCreatorUtilsTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/core/StatementCreatorUtilsTests.java @@ -109,7 +109,7 @@ public class StatementCreatorUtilsTests { @Test public void testSetParameterValueWithNullAndGetParameterTypeWorkingButNotForOtherDriver() throws SQLException { StatementCreatorUtils.driversWithNoSupportForGetParameterType.clear(); - StatementCreatorUtils.driversWithNoSupportForGetParameterType.put("Oracle JDBC Driver", Boolean.TRUE); + StatementCreatorUtils.driversWithNoSupportForGetParameterType.add("Oracle JDBC Driver"); Connection con = mock(Connection.class); DatabaseMetaData dbmd = mock(DatabaseMetaData.class); ParameterMetaData pmd = mock(ParameterMetaData.class); diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/DelegatingDataSourceTest.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/DelegatingDataSourceTests.java index 05295b56..5782fc2e 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/DelegatingDataSourceTest.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/DelegatingDataSourceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,7 +22,6 @@ import java.sql.Connection; import javax.sql.DataSource; -import org.junit.Before; import org.junit.Test; import static org.hamcrest.Matchers.*; @@ -34,17 +33,11 @@ import static org.mockito.BDDMockito.*; * * @author Phillip Webb */ -public class DelegatingDataSourceTest { +public class DelegatingDataSourceTests { - private DataSource delegate; + private final DataSource delegate = mock(DataSource.class); - private DelegatingDataSource dataSource; - - @Before - public void setup() { - this.delegate = mock(DataSource.class); - this.dataSource = new DelegatingDataSource(delegate); - } + private DelegatingDataSource dataSource = new DelegatingDataSource(delegate); @Test public void shouldDelegateGetConnection() throws Exception { diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilderTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilderTests.java index 8ad40961..f3a43be8 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilderTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,65 +18,150 @@ package org.springframework.jdbc.datasource.embedded; import org.junit.Test; import org.springframework.core.io.ClassRelativeResourceLoader; -import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.init.CannotReadScriptException; -import org.springframework.tests.Assume; -import org.springframework.tests.TestGroup; import static org.junit.Assert.*; +import static org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType.*; /** + * Integration tests for {@link EmbeddedDatabaseBuilder}. + * * @author Keith Donald + * @author Sam Brannen */ public class EmbeddedDatabaseBuilderTests { + private final EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(new ClassRelativeResourceLoader( + getClass())); + + + @Test + public void addDefaultScripts() throws Exception { + doTwice(new Runnable() { + + @Override + public void run() { + EmbeddedDatabase db = new EmbeddedDatabaseBuilder()// + .addDefaultScripts()// + .build(); + assertDatabaseCreatedAndShutdown(db); + } + }); + } + + @Test(expected = CannotReadScriptException.class) + public void addScriptWithBogusFileName() { + new EmbeddedDatabaseBuilder().addScript("bogus.sql").build(); + } + + @Test + public void addScript() throws Exception { + doTwice(new Runnable() { + + @Override + public void run() { + EmbeddedDatabase db = builder// + .addScript("db-schema.sql")// + .addScript("db-test-data.sql")// + .build(); + assertDatabaseCreatedAndShutdown(db); + } + }); + } + @Test - public void testBuildDefaultScripts() { - EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); - EmbeddedDatabase db = builder.addDefaultScripts().build(); - assertDatabaseCreatedAndShutdown(db); + public void addScripts() throws Exception { + doTwice(new Runnable() { + + @Override + public void run() { + EmbeddedDatabase db = builder// + .addScripts("db-schema.sql", "db-test-data.sql")// + .build(); + assertDatabaseCreatedAndShutdown(db); + } + }); } @Test - public void testBuild() { - EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(new ClassRelativeResourceLoader(getClass())); - EmbeddedDatabase db = builder.addScript("db-schema.sql").addScript("db-test-data.sql").build(); - assertDatabaseCreatedAndShutdown(db); + public void addScriptsWithDefaultCommentPrefix() throws Exception { + doTwice(new Runnable() { + + @Override + public void run() { + EmbeddedDatabase db = builder// + .addScripts("db-schema-comments.sql", "db-test-data.sql")// + .build(); + assertDatabaseCreatedAndShutdown(db); + } + }); } @Test - public void testBuildWithComments() { - EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(new ClassRelativeResourceLoader(getClass())); - EmbeddedDatabase db = builder.addScript("db-schema-comments.sql").addScript("db-test-data.sql").build(); - assertDatabaseCreatedAndShutdown(db); + public void addScriptsWithCustomCommentPrefix() throws Exception { + doTwice(new Runnable() { + + @Override + public void run() { + EmbeddedDatabase db = builder// + .addScripts("db-schema-custom-comments.sql", "db-test-data.sql")// + .setCommentPrefix("~")// + .build(); + assertDatabaseCreatedAndShutdown(db); + } + }); } @Test - public void testBuildH2() { - EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(new ClassRelativeResourceLoader(getClass())); - EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.H2).addScript("db-schema.sql").addScript("db-test-data.sql").build(); - assertDatabaseCreatedAndShutdown(db); + public void addScriptsWithCustomBlockComments() throws Exception { + doTwice(new Runnable() { + + @Override + public void run() { + EmbeddedDatabase db = builder// + .addScripts("db-schema-block-comments.sql", "db-test-data.sql")// + .setBlockCommentStartDelimiter("{*")// + .setBlockCommentEndDelimiter("*}")// + .build(); + assertDatabaseCreatedAndShutdown(db); + } + }); } @Test - public void testBuildDerby() { - Assume.group(TestGroup.LONG_RUNNING); + public void setTypeToH2() throws Exception { + doTwice(new Runnable() { - EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(new ClassRelativeResourceLoader(getClass())); - EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.DERBY).addScript("db-schema-derby.sql").addScript("db-test-data.sql").build(); - assertDatabaseCreatedAndShutdown(db); + @Override + public void run() { + EmbeddedDatabase db = builder// + .setType(H2)// + .addScripts("db-schema.sql", "db-test-data.sql")// + .build(); + assertDatabaseCreatedAndShutdown(db); + } + }); } @Test - public void testBuildNoSuchScript() { - try { - new EmbeddedDatabaseBuilder().addScript("bogus.sql").build(); - fail("Should have failed"); - } - catch (DataAccessResourceFailureException ex) { - assertTrue(ex.getCause() instanceof CannotReadScriptException); - } + public void setTypeToDerbyAndIgnoreFailedDrops() throws Exception { + doTwice(new Runnable() { + + @Override + public void run() { + EmbeddedDatabase db = builder// + .setType(DERBY)// + .ignoreFailedDrops(true)// + .addScripts("db-schema-derby-with-drop.sql", "db-test-data.sql").build(); + assertDatabaseCreatedAndShutdown(db); + } + }); + } + + private void doTwice(Runnable test) { + test.run(); + test.run(); } private void assertDatabaseCreatedAndShutdown(EmbeddedDatabase db) { diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryBeanTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryBeanTests.java index 1ad8cbd8..8d9bf392 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryBeanTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryBeanTests.java @@ -1,25 +1,48 @@ -package org.springframework.jdbc.datasource.embedded; +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -import static org.junit.Assert.assertEquals; +package org.springframework.jdbc.datasource.embedded; import javax.sql.DataSource; import org.junit.Test; -import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.ClassRelativeResourceLoader; import org.springframework.core.io.Resource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; +import static org.junit.Assert.*; + +/** + * @author Keith Donald + */ public class EmbeddedDatabaseFactoryBeanTests { + private final ClassRelativeResourceLoader resourceLoader = new ClassRelativeResourceLoader(getClass()); + + + Resource resource(String path) { + return resourceLoader.getResource(path); + } + @Test public void testFactoryBeanLifecycle() throws Exception { EmbeddedDatabaseFactoryBean bean = new EmbeddedDatabaseFactoryBean(); - ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); - populator.setScripts(new Resource[] { - new ClassPathResource("db-schema.sql", getClass()), - new ClassPathResource("db-test-data.sql", getClass()) - }); + ResourceDatabasePopulator populator = new ResourceDatabasePopulator(resource("db-schema.sql"), + resource("db-test-data.sql")); bean.setDatabasePopulator(populator); bean.afterPropertiesSet(); DataSource ds = bean.getObject(); @@ -27,4 +50,5 @@ public class EmbeddedDatabaseFactoryBeanTests { assertEquals("Keith", template.queryForObject("select NAME from T_TEST", String.class)); bean.destroy(); } + } diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryTests.java index 77970dbe..ed585d50 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseFactoryTests.java @@ -1,16 +1,37 @@ -package org.springframework.jdbc.datasource.embedded; +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -import static org.junit.Assert.assertTrue; +package org.springframework.jdbc.datasource.embedded; import java.sql.Connection; import org.junit.Test; + import org.springframework.jdbc.datasource.init.DatabasePopulator; +import static org.junit.Assert.*; + +/** + * @author Keith Donald + */ public class EmbeddedDatabaseFactoryTests { private EmbeddedDatabaseFactory factory = new EmbeddedDatabaseFactory(); + @Test public void testGetDataSource() { StubDatabasePopulator populator = new StubDatabasePopulator(); @@ -20,6 +41,7 @@ public class EmbeddedDatabaseFactoryTests { db.shutdown(); } + private static class StubDatabasePopulator implements DatabasePopulator { private boolean populateCalled; @@ -28,6 +50,6 @@ public class EmbeddedDatabaseFactoryTests { public void populate(Connection connection) { this.populateCalled = true; } - } + } diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/AbstractDatabaseInitializationTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/AbstractDatabaseInitializationTests.java new file mode 100644 index 00000000..5be6e26d --- /dev/null +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/AbstractDatabaseInitializationTests.java @@ -0,0 +1,84 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jdbc.datasource.init; + +import org.junit.After; +import org.junit.Before; +import org.springframework.core.io.ClassRelativeResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +/** + * Abstract base class for integration tests involving database initialization. + * + * @author Sam Brannen + * @since 4.0.3 + */ +public abstract class AbstractDatabaseInitializationTests { + + private final ClassRelativeResourceLoader resourceLoader = new ClassRelativeResourceLoader(getClass()); + + EmbeddedDatabase db; + + JdbcTemplate jdbcTemplate; + + + @Before + public void setUp() { + db = new EmbeddedDatabaseBuilder().setType(getEmbeddedDatabaseType()).build(); + jdbcTemplate = new JdbcTemplate(db); + } + + @After + public void shutDown() { + if (TransactionSynchronizationManager.isSynchronizationActive()) { + TransactionSynchronizationManager.clear(); + TransactionSynchronizationManager.unbindResource(db); + } + db.shutdown(); + } + + abstract EmbeddedDatabaseType getEmbeddedDatabaseType(); + + Resource resource(String path) { + return resourceLoader.getResource(path); + } + + Resource defaultSchema() { + return resource("db-schema.sql"); + } + + Resource usersSchema() { + return resource("users-schema.sql"); + } + + void assertUsersDatabaseCreated(String... lastNames) { + for (String lastName : lastNames) { + assertThat("Did not find user with last name [" + lastName + "].", + jdbcTemplate.queryForObject("select count(0) from users where last_name = ?", Integer.class, lastName), + equalTo(1)); + } + } + +} diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/AbstractDatabasePopulatorTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/AbstractDatabasePopulatorTests.java new file mode 100644 index 00000000..82d8acfe --- /dev/null +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/AbstractDatabasePopulatorTests.java @@ -0,0 +1,202 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jdbc.datasource.init; + +import java.sql.Connection; +import java.sql.SQLException; + +import org.junit.Test; +import org.springframework.jdbc.datasource.DataSourceUtils; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +/** + * Abstract base class for integration tests for {@link ResourceDatabasePopulator} + * and {@link DatabasePopulatorUtils}. + * + * @author Dave Syer + * @author Sam Brannen + * @author Oliver Gierke + */ +public abstract class AbstractDatabasePopulatorTests extends AbstractDatabaseInitializationTests { + + private final ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); + + + @Test + public void buildWithCommentsAndFailedDrop() throws Exception { + databasePopulator.addScript(resource("db-schema-failed-drop-comments.sql")); + databasePopulator.addScript(resource("db-test-data.sql")); + databasePopulator.setIgnoreFailedDrops(true); + DatabasePopulatorUtils.execute(databasePopulator, db); + assertTestDatabaseCreated(); + } + + @Test + public void buildWithNormalEscapedLiteral() throws Exception { + databasePopulator.addScript(defaultSchema()); + databasePopulator.addScript(resource("db-test-data-escaped-literal.sql")); + DatabasePopulatorUtils.execute(databasePopulator, db); + assertTestDatabaseCreated("'Keith'"); + } + + @Test + public void buildWithMySQLEscapedLiteral() throws Exception { + databasePopulator.addScript(defaultSchema()); + databasePopulator.addScript(resource("db-test-data-mysql-escaped-literal.sql")); + DatabasePopulatorUtils.execute(databasePopulator, db); + assertTestDatabaseCreated("\\$Keith\\$"); + } + + @Test + public void buildWithMultipleStatements() throws Exception { + databasePopulator.addScript(defaultSchema()); + databasePopulator.addScript(resource("db-test-data-multiple.sql")); + DatabasePopulatorUtils.execute(databasePopulator, db); + assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class), + equalTo(1)); + assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class), + equalTo(1)); + } + + @Test + public void buildWithMultipleStatementsLongSeparator() throws Exception { + databasePopulator.addScript(defaultSchema()); + databasePopulator.addScript(resource("db-test-data-endings.sql")); + databasePopulator.setSeparator("@@"); + DatabasePopulatorUtils.execute(databasePopulator, db); + assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class), + equalTo(1)); + assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class), + equalTo(1)); + } + + @Test + public void buildWithMultipleStatementsWhitespaceSeparator() throws Exception { + databasePopulator.addScript(defaultSchema()); + databasePopulator.addScript(resource("db-test-data-whitespace.sql")); + databasePopulator.setSeparator("/\n"); + DatabasePopulatorUtils.execute(databasePopulator, db); + assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class), + equalTo(1)); + assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class), + equalTo(1)); + } + + @Test + public void buildWithMultipleStatementsNewlineSeparator() throws Exception { + databasePopulator.addScript(defaultSchema()); + databasePopulator.addScript(resource("db-test-data-newline.sql")); + DatabasePopulatorUtils.execute(databasePopulator, db); + assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class), + equalTo(1)); + assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class), + equalTo(1)); + } + + @Test + public void buildWithMultipleStatementsMultipleNewlineSeparator() throws Exception { + databasePopulator.addScript(defaultSchema()); + databasePopulator.addScript(resource("db-test-data-multi-newline.sql")); + databasePopulator.setSeparator("\n\n"); + DatabasePopulatorUtils.execute(databasePopulator, db); + assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class), + equalTo(1)); + assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class), + equalTo(1)); + } + + @Test + public void scriptWithEolBetweenTokens() throws Exception { + databasePopulator.addScript(usersSchema()); + databasePopulator.addScript(resource("users-data.sql")); + DatabasePopulatorUtils.execute(databasePopulator, db); + assertUsersDatabaseCreated("Brannen"); + } + + @Test + public void scriptWithCommentsWithinStatements() throws Exception { + databasePopulator.addScript(usersSchema()); + databasePopulator.addScript(resource("users-data-with-comments.sql")); + DatabasePopulatorUtils.execute(databasePopulator, db); + assertUsersDatabaseCreated("Brannen", "Hoeller"); + } + + @Test + public void scriptWithoutStatementSeparator() throws Exception { + databasePopulator.setSeparator(ScriptUtils.EOF_STATEMENT_SEPARATOR); + databasePopulator.addScript(resource("drop-users-schema.sql")); + databasePopulator.addScript(resource("users-schema-without-separator.sql")); + databasePopulator.addScript(resource("users-data.sql")); + DatabasePopulatorUtils.execute(databasePopulator, db); + + assertUsersDatabaseCreated("Brannen"); + } + + @Test + public void constructorWithMultipleScriptResources() throws Exception { + final ResourceDatabasePopulator populator = new ResourceDatabasePopulator(usersSchema(), + resource("users-data-with-comments.sql")); + DatabasePopulatorUtils.execute(populator, db); + assertUsersDatabaseCreated("Brannen", "Hoeller"); + } + + @Test + public void buildWithSelectStatements() throws Exception { + databasePopulator.addScript(defaultSchema()); + databasePopulator.addScript(resource("db-test-data-select.sql")); + DatabasePopulatorUtils.execute(databasePopulator, db); + assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Keith'", Integer.class), + equalTo(1)); + assertThat(jdbcTemplate.queryForObject("select COUNT(NAME) from T_TEST where NAME='Dave'", Integer.class), + equalTo(1)); + } + + /** + * See SPR-9457 + */ + @Test + public void usesBoundConnectionIfAvailable() throws SQLException { + TransactionSynchronizationManager.initSynchronization(); + Connection connection = DataSourceUtils.getConnection(db); + DatabasePopulator populator = mock(DatabasePopulator.class); + DatabasePopulatorUtils.execute(populator, db); + verify(populator).populate(connection); + } + + /** + * See SPR-9781 + */ + @Test(timeout = 1000) + public void executesHugeScriptInReasonableTime() throws SQLException { + databasePopulator.addScript(defaultSchema()); + databasePopulator.addScript(resource("db-test-data-huge.sql")); + DatabasePopulatorUtils.execute(databasePopulator, db); + } + + private void assertTestDatabaseCreated() { + assertTestDatabaseCreated("Keith"); + } + + private void assertTestDatabaseCreated(String name) { + assertEquals(name, jdbcTemplate.queryForObject("select NAME from T_TEST", String.class)); + } + +} diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/DatabasePopulatorTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/DatabasePopulatorTests.java deleted file mode 100644 index 64f09cc7..00000000 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/DatabasePopulatorTests.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.jdbc.datasource.init; - -import java.sql.Connection; -import java.sql.SQLException; - -import org.junit.After; -import org.junit.Test; -import org.springframework.core.io.ClassRelativeResourceLoader; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.datasource.DataSourceUtils; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; -import org.springframework.transaction.support.TransactionSynchronizationManager; - -import static org.junit.Assert.*; -import static org.mockito.BDDMockito.*; - -/** - * @author Dave Syer - * @author Sam Brannen - * @author Oliver Gierke - */ -public class DatabasePopulatorTests { - - private final EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); - - private final EmbeddedDatabase db = builder.build(); - - private final ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); - - private final ClassRelativeResourceLoader resourceLoader = new ClassRelativeResourceLoader(getClass()); - - private final JdbcTemplate jdbcTemplate = new JdbcTemplate(db); - - - private void assertTestDatabaseCreated() { - assertTestDatabaseCreated("Keith"); - } - - private void assertTestDatabaseCreated(String name) { - assertEquals(name, jdbcTemplate.queryForObject("select NAME from T_TEST", String.class)); - } - - private void assertUsersDatabaseCreated(String... lastNames) { - for (String lastName : lastNames) { - assertEquals("Did not find user with last name [" + lastName + "].", 1, - jdbcTemplate.queryForInt("select count(0) from users where last_name = ?", lastName)); - } - } - - @After - public void shutDown() { - if (TransactionSynchronizationManager.isSynchronizationActive()) { - TransactionSynchronizationManager.clear(); - TransactionSynchronizationManager.unbindResource(db); - } - db.shutdown(); - } - - @Test - public void testBuildWithCommentsAndFailedDrop() throws Exception { - databasePopulator.addScript(resourceLoader.getResource("db-schema-failed-drop-comments.sql")); - databasePopulator.addScript(resourceLoader.getResource("db-test-data.sql")); - databasePopulator.setIgnoreFailedDrops(true); - Connection connection = db.getConnection(); - try { - databasePopulator.populate(connection); - } - finally { - connection.close(); - } - - assertTestDatabaseCreated(); - } - - @Test - public void testBuildWithNormalEscapedLiteral() throws Exception { - databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); - databasePopulator.addScript(resourceLoader.getResource("db-test-data-escaped-literal.sql")); - Connection connection = db.getConnection(); - try { - databasePopulator.populate(connection); - } - finally { - connection.close(); - } - - assertTestDatabaseCreated("'Keith'"); - } - - @Test - public void testBuildWithMySQLEscapedLiteral() throws Exception { - databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); - databasePopulator.addScript(resourceLoader.getResource("db-test-data-mysql-escaped-literal.sql")); - Connection connection = db.getConnection(); - try { - databasePopulator.populate(connection); - } - finally { - connection.close(); - } - - assertTestDatabaseCreated("\\$Keith\\$"); - } - - @Test - public void testBuildWithMultipleStatements() throws Exception { - databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); - databasePopulator.addScript(resourceLoader.getResource("db-test-data-multiple.sql")); - Connection connection = db.getConnection(); - try { - databasePopulator.populate(connection); - } - finally { - connection.close(); - } - - assertEquals(1, jdbcTemplate.queryForInt("select COUNT(NAME) from T_TEST where NAME='Keith'")); - assertEquals(1, jdbcTemplate.queryForInt("select COUNT(NAME) from T_TEST where NAME='Dave'")); - } - - @Test - public void testBuildWithMultipleStatementsLongSeparator() throws Exception { - databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); - databasePopulator.addScript(resourceLoader.getResource("db-test-data-endings.sql")); - databasePopulator.setSeparator("@@"); - Connection connection = db.getConnection(); - try { - databasePopulator.populate(connection); - } - finally { - connection.close(); - } - - assertEquals(1, jdbcTemplate.queryForInt("select COUNT(NAME) from T_TEST where NAME='Keith'")); - assertEquals(1, jdbcTemplate.queryForInt("select COUNT(NAME) from T_TEST where NAME='Dave'")); - } - - @Test - public void testBuildWithMultipleStatementsWhitespaceSeparator() throws Exception { - databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); - databasePopulator.addScript(resourceLoader.getResource("db-test-data-whitespace.sql")); - databasePopulator.setSeparator("/\n"); - Connection connection = db.getConnection(); - try { - databasePopulator.populate(connection); - } - finally { - connection.close(); - } - - assertEquals(1, jdbcTemplate.queryForInt("select COUNT(NAME) from T_TEST where NAME='Keith'")); - assertEquals(1, jdbcTemplate.queryForInt("select COUNT(NAME) from T_TEST where NAME='Dave'")); - } - - @Test - public void testBuildWithMultipleStatementsNewlineSeparator() throws Exception { - databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); - databasePopulator.addScript(resourceLoader.getResource("db-test-data-newline.sql")); - Connection connection = db.getConnection(); - try { - databasePopulator.populate(connection); - } - finally { - connection.close(); - } - - assertEquals(1, jdbcTemplate.queryForInt("select COUNT(NAME) from T_TEST where NAME='Keith'")); - assertEquals(1, jdbcTemplate.queryForInt("select COUNT(NAME) from T_TEST where NAME='Dave'")); - } - - @Test - public void testBuildWithMultipleStatementsMultipleNewlineSeparator() throws Exception { - databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); - databasePopulator.addScript(resourceLoader.getResource("db-test-data-multi-newline.sql")); - databasePopulator.setSeparator("\n\n"); - Connection connection = db.getConnection(); - try { - databasePopulator.populate(connection); - } - finally { - connection.close(); - } - - assertEquals(1, jdbcTemplate.queryForInt("select COUNT(NAME) from T_TEST where NAME='Keith'")); - assertEquals(1, jdbcTemplate.queryForInt("select COUNT(NAME) from T_TEST where NAME='Dave'")); - } - - @Test - public void scriptWithEolBetweenTokens() throws Exception { - databasePopulator.addScript(resourceLoader.getResource("users-schema.sql")); - databasePopulator.addScript(resourceLoader.getResource("users-data.sql")); - Connection connection = db.getConnection(); - try { - databasePopulator.populate(connection); - } - finally { - connection.close(); - } - - assertUsersDatabaseCreated("Brannen"); - } - - @Test - public void scriptWithCommentsWithinStatements() throws Exception { - databasePopulator.addScript(resourceLoader.getResource("users-schema.sql")); - databasePopulator.addScript(resourceLoader.getResource("users-data-with-comments.sql")); - Connection connection = db.getConnection(); - try { - databasePopulator.populate(connection); - } - finally { - connection.close(); - } - - assertUsersDatabaseCreated("Brannen", "Hoeller"); - } - - @Test - public void testBuildWithSelectStatements() throws Exception { - databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); - databasePopulator.addScript(resourceLoader.getResource("db-test-data-select.sql")); - Connection connection = db.getConnection(); - try { - databasePopulator.populate(connection); - } - finally { - connection.close(); - } - - assertEquals(1, jdbcTemplate.queryForInt("select COUNT(NAME) from T_TEST where NAME='Keith'")); - assertEquals(1, jdbcTemplate.queryForInt("select COUNT(NAME) from T_TEST where NAME='Dave'")); - } - - /** - * See SPR-9457 - */ - @Test - public void usesBoundConnectionIfAvailable() throws SQLException { - TransactionSynchronizationManager.initSynchronization(); - Connection connection = DataSourceUtils.getConnection(db); - DatabasePopulator populator = mock(DatabasePopulator.class); - DatabasePopulatorUtils.execute(populator, db); - verify(populator).populate(connection); - } - - /** - * See SPR-9781 - */ - @Test(timeout = 1000) - public void executesHugeScriptInReasonableTime() throws SQLException { - databasePopulator.addScript(resourceLoader.getResource("db-schema.sql")); - databasePopulator.addScript(resourceLoader.getResource("db-test-data-huge.sql")); - - Connection connection = db.getConnection(); - try { - databasePopulator.populate(connection); - } - finally { - connection.close(); - } - } - -} diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/H2DatabasePopulatorTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/H2DatabasePopulatorTests.java new file mode 100644 index 00000000..699ea75b --- /dev/null +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/H2DatabasePopulatorTests.java @@ -0,0 +1,31 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jdbc.datasource.init; + +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; + +/** + * @author Sam Brannen + * @since 4.0.3 + */ +public class H2DatabasePopulatorTests extends AbstractDatabasePopulatorTests { + + protected EmbeddedDatabaseType getEmbeddedDatabaseType() { + return EmbeddedDatabaseType.H2; + } + +} diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/HsqlDatabasePopulatorTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/HsqlDatabasePopulatorTests.java new file mode 100644 index 00000000..9ab79b60 --- /dev/null +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/HsqlDatabasePopulatorTests.java @@ -0,0 +1,31 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jdbc.datasource.init; + +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; + +/** + * @author Sam Brannen + * @since 4.0.3 + */ +public class HsqlDatabasePopulatorTests extends AbstractDatabasePopulatorTests { + + protected EmbeddedDatabaseType getEmbeddedDatabaseType() { + return EmbeddedDatabaseType.HSQL; + } + +} diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsIntegrationTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsIntegrationTests.java new file mode 100644 index 00000000..76f03a93 --- /dev/null +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsIntegrationTests.java @@ -0,0 +1,47 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jdbc.datasource.init; + +import java.sql.SQLException; + +import org.junit.Test; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; + +import static org.springframework.jdbc.datasource.init.ScriptUtils.*; + +/** + * Integration tests for {@link ScriptUtils}. + * + * @author Sam Brannen + * @see ScriptUtilsUnitTests + * @since 4.0.3 + */ +public class ScriptUtilsIntegrationTests extends AbstractDatabaseInitializationTests { + + protected EmbeddedDatabaseType getEmbeddedDatabaseType() { + return EmbeddedDatabaseType.HSQL; + } + + @Test + public void executeSqlScriptContainingMuliLineComments() throws SQLException { + executeSqlScript(db.getConnection(), usersSchema()); + executeSqlScript(db.getConnection(), resource("test-data-with-multi-line-comments.sql")); + + assertUsersDatabaseCreated("Hoeller", "Brannen"); + } + +} diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsUnitTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsUnitTests.java new file mode 100644 index 00000000..6df2eb17 --- /dev/null +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/ScriptUtilsUnitTests.java @@ -0,0 +1,172 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jdbc.datasource.init; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.support.EncodedResource; + +import static org.junit.Assert.*; +import static org.springframework.jdbc.datasource.init.ScriptUtils.*; + +/** + * Unit tests for {@link ScriptUtils}. + * + * @author Thomas Risberg + * @author Sam Brannen + * @author Phillip Webb + * @author Chris Baldwin + * @see ScriptUtilsIntegrationTests + * @since 4.0.3 + */ +public class ScriptUtilsUnitTests { + + @Test + public void splitSqlScriptDelimitedWithSemicolon() { + String rawStatement1 = "insert into customer (id, name)\nvalues (1, 'Rod ; Johnson'), (2, 'Adrian \n Collier')"; + String cleanedStatement1 = "insert into customer (id, name) values (1, 'Rod ; Johnson'), (2, 'Adrian \n Collier')"; + String rawStatement2 = "insert into orders(id, order_date, customer_id)\nvalues (1, '2008-01-02', 2)"; + String cleanedStatement2 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)"; + String rawStatement3 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)"; + String cleanedStatement3 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)"; + char delim = ';'; + String script = rawStatement1 + delim + rawStatement2 + delim + rawStatement3 + delim; + List<String> statements = new ArrayList<String>(); + splitSqlScript(script, delim, statements); + assertEquals("wrong number of statements", 3, statements.size()); + assertEquals("statement 1 not split correctly", cleanedStatement1, statements.get(0)); + assertEquals("statement 2 not split correctly", cleanedStatement2, statements.get(1)); + assertEquals("statement 3 not split correctly", cleanedStatement3, statements.get(2)); + } + + @Test + public void splitSqlScriptDelimitedWithNewLine() { + String statement1 = "insert into customer (id, name) values (1, 'Rod ; Johnson'), (2, 'Adrian \n Collier')"; + String statement2 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)"; + String statement3 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)"; + char delim = '\n'; + String script = statement1 + delim + statement2 + delim + statement3 + delim; + List<String> statements = new ArrayList<String>(); + splitSqlScript(script, delim, statements); + assertEquals("wrong number of statements", 3, statements.size()); + assertEquals("statement 1 not split correctly", statement1, statements.get(0)); + assertEquals("statement 2 not split correctly", statement2, statements.get(1)); + assertEquals("statement 3 not split correctly", statement3, statements.get(2)); + } + + @Test + public void splitSqlScriptDelimitedWithNewLineButDefaultDelimiterSpecified() { + String statement1 = "do something"; + String statement2 = "do something else"; + char delim = '\n'; + String script = statement1 + delim + statement2 + delim; + List<String> statements = new ArrayList<String>(); + splitSqlScript(script, DEFAULT_STATEMENT_SEPARATOR, statements); + assertEquals("wrong number of statements", 1, statements.size()); + assertEquals("script should have been 'stripped' but not actually 'split'", script.replace('\n', ' '), + statements.get(0)); + } + + /** + * See <a href="https://jira.spring.io/browse/SPR-11560">SPR-11560</a> + */ + @Test + public void readAndSplitScriptWithMultipleNewlinesAsSeparator() throws Exception { + String script = readScript("db-test-data-multi-newline.sql"); + List<String> statements = new ArrayList<String>(); + splitSqlScript(script, "\n\n", statements); + + String statement1 = "insert into T_TEST (NAME) values ('Keith')"; + String statement2 = "insert into T_TEST (NAME) values ('Dave')"; + + assertEquals("wrong number of statements", 2, statements.size()); + assertEquals("statement 1 not split correctly", statement1, statements.get(0)); + assertEquals("statement 2 not split correctly", statement2, statements.get(1)); + } + + @Test + public void readAndSplitScriptContainingComments() throws Exception { + String script = readScript("test-data-with-comments.sql"); + List<String> statements = new ArrayList<String>(); + splitSqlScript(script, ';', statements); + + String statement1 = "insert into customer (id, name) values (1, 'Rod; Johnson'), (2, 'Adrian Collier')"; + String statement2 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)"; + String statement3 = "insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2)"; + // Statement 4 addresses the error described in SPR-9982. + String statement4 = "INSERT INTO persons( person_id , name) VALUES( 1 , 'Name' )"; + + assertEquals("wrong number of statements", 4, statements.size()); + assertEquals("statement 1 not split correctly", statement1, statements.get(0)); + assertEquals("statement 2 not split correctly", statement2, statements.get(1)); + assertEquals("statement 3 not split correctly", statement3, statements.get(2)); + assertEquals("statement 4 not split correctly", statement4, statements.get(3)); + } + + /** + * See <a href="https://jira.spring.io/browse/SPR-10330">SPR-10330</a> + */ + @Test + public void readAndSplitScriptContainingCommentsWithLeadingTabs() throws Exception { + String script = readScript("test-data-with-comments-and-leading-tabs.sql"); + List<String> statements = new ArrayList<String>(); + splitSqlScript(script, ';', statements); + + String statement1 = "insert into customer (id, name) values (1, 'Sam Brannen')"; + String statement2 = "insert into orders(id, order_date, customer_id) values (1, '2013-06-08', 1)"; + String statement3 = "insert into orders(id, order_date, customer_id) values (2, '2013-06-08', 1)"; + + assertEquals("wrong number of statements", 3, statements.size()); + assertEquals("statement 1 not split correctly", statement1, statements.get(0)); + assertEquals("statement 2 not split correctly", statement2, statements.get(1)); + assertEquals("statement 3 not split correctly", statement3, statements.get(2)); + } + + /** + * See <a href="https://jira.spring.io/browse/SPR-9531">SPR-9531</a> + */ + @Test + public void readAndSplitScriptContainingMuliLineComments() throws Exception { + String script = readScript("test-data-with-multi-line-comments.sql"); + List<String> statements = new ArrayList<String>(); + splitSqlScript(script, ';', statements); + + String statement1 = "INSERT INTO users(first_name, last_name) VALUES('Juergen', 'Hoeller')"; + String statement2 = "INSERT INTO users(first_name, last_name) VALUES( 'Sam' , 'Brannen' )"; + + assertEquals("wrong number of statements", 2, statements.size()); + assertEquals("statement 1 not split correctly", statement1, statements.get(0)); + assertEquals("statement 2 not split correctly", statement2, statements.get(1)); + } + + @Test + public void containsDelimiters() { + assertTrue("test with ';' is wrong", !containsSqlScriptDelimiters("select 1\n select ';'", ";")); + assertTrue("test with delimiter ; is wrong", containsSqlScriptDelimiters("select 1; select 2", ";")); + assertTrue("test with '\\n' is wrong", !containsSqlScriptDelimiters("select 1; select '\\n\n';", "\n")); + assertTrue("test with delimiter \\n is wrong", containsSqlScriptDelimiters("select 1\n select 2", "\n")); + } + + private String readScript(String path) throws Exception { + EncodedResource resource = new EncodedResource(new ClassPathResource(path, getClass())); + return ScriptUtils.readScript(resource); + } + +} diff --git a/spring-jdbc/src/test/resources/log4j.properties b/spring-jdbc/src/test/resources/log4j.properties new file mode 100644 index 00000000..2cfb3bbe --- /dev/null +++ b/spring-jdbc/src/test/resources/log4j.properties @@ -0,0 +1,10 @@ +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern=%d{HH:mm:ss,SSS} [%c] - %m%n + +log4j.rootCategory=WARN, console +log4j.logger.org.springframework.beans=WARN +log4j.logger.org.springframework.binding=DEBUG + +#log4j.logger.org.springframework.jdbc=TRACE + diff --git a/spring-jdbc/src/test/resources/log4j.xml b/spring-jdbc/src/test/resources/log4j.xml deleted file mode 100644 index 767b96d6..00000000 --- a/spring-jdbc/src/test/resources/log4j.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> - -<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> - - <!-- Appenders --> - <appender name="console" class="org.apache.log4j.ConsoleAppender"> - <param name="Target" value="System.out" /> - <layout class="org.apache.log4j.PatternLayout"> - <param name="ConversionPattern" value="%-5p: %c - %m%n" /> - </layout> - </appender> - - <logger name="org.springframework.beans"> - <level value="warn" /> - </logger> - - <logger name="org.springframework.binding"> - <level value="debug" /> - </logger> - - <!-- Root Logger --> - <root> - <priority value="warn" /> - <appender-ref ref="console" /> - </root> - -</log4j:configuration>
\ No newline at end of file diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/config/jdbc-destroy-nested-config-h2.xml b/spring-jdbc/src/test/resources/org/springframework/jdbc/config/jdbc-destroy-nested-config-h2.xml new file mode 100644 index 00000000..bbea98e9 --- /dev/null +++ b/spring-jdbc/src/test/resources/org/springframework/jdbc/config/jdbc-destroy-nested-config-h2.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:jdbc="http://www.springframework.org/schema/jdbc" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd"> + + <jdbc:embedded-database id="dataSource" type="H2"> + <jdbc:script location="classpath:org/springframework/jdbc/config/db-schema.sql" execution="INIT"/> + <jdbc:script location="classpath:org/springframework/jdbc/config/db-test-data.sql" execution="INIT"/> + <jdbc:script location="classpath:org/springframework/jdbc/config/db-drops.sql" execution="DESTROY"/> + </jdbc:embedded-database> + +</beans> diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema-block-comments.sql b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema-block-comments.sql new file mode 100644 index 00000000..b0a89733 --- /dev/null +++ b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema-block-comments.sql @@ -0,0 +1,9 @@ +{* + these are custom block comments +*} +drop table T_TEST if exists; + +{* + these are custom block comments +*} +create table T_TEST (NAME varchar(50) not null);
\ No newline at end of file diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema-custom-comments.sql b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema-custom-comments.sql new file mode 100644 index 00000000..cff0cc72 --- /dev/null +++ b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema-custom-comments.sql @@ -0,0 +1,5 @@ +~ Failed DROP can be ignored if necessary +drop table T_TEST if exists; + +~ Create the test table +create table T_TEST (NAME varchar(50) not null);
\ No newline at end of file diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema-derby-with-drop.sql b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema-derby-with-drop.sql new file mode 100644 index 00000000..ffae4802 --- /dev/null +++ b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema-derby-with-drop.sql @@ -0,0 +1,3 @@ +drop table T_TEST; + +create table T_TEST (NAME varchar(50) not null);
\ No newline at end of file diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema-derby.sql b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema-derby.sql deleted file mode 100644 index 9b2e14d7..00000000 --- a/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema-derby.sql +++ /dev/null @@ -1 +0,0 @@ -create table T_TEST (NAME varchar(50) not null);
\ No newline at end of file diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/drop-users-schema.sql b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/drop-users-schema.sql new file mode 100644 index 00000000..cf1647ac --- /dev/null +++ b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/drop-users-schema.sql @@ -0,0 +1 @@ +DROP TABLE users IF EXISTS
\ No newline at end of file diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-comments-and-leading-tabs.sql b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-comments-and-leading-tabs.sql new file mode 100644 index 00000000..8f54e9eb --- /dev/null +++ b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-comments-and-leading-tabs.sql @@ -0,0 +1,9 @@ +-- The next comment line starts with a tab. + -- x, y, z... + +insert into customer (id, name) +values (1, 'Sam Brannen'); + -- This is also a comment with a leading tab. +insert into orders(id, order_date, customer_id) values (1, '2013-06-08', 1); + -- This is also a comment with a leading tab, a space, and a tab. +insert into orders(id, order_date, customer_id) values (2, '2013-06-08', 1); diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-comments.sql b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-comments.sql new file mode 100644 index 00000000..82483ca4 --- /dev/null +++ b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-comments.sql @@ -0,0 +1,16 @@ +-- The next comment line has no text after the '--' prefix. +-- +-- The next comment line starts with a space. + -- x, y, z... + +insert into customer (id, name) +values (1, 'Rod; Johnson'), (2, 'Adrian Collier'); +-- This is also a comment. +insert into orders(id, order_date, customer_id) +values (1, '2008-01-02', 2); +insert into orders(id, order_date, customer_id) values (1, '2008-01-02', 2); +INSERT INTO persons( person_id-- + , name) +VALUES( 1 -- person_id + , 'Name' --name +);--
\ No newline at end of file diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-multi-line-comments.sql b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-multi-line-comments.sql new file mode 100644 index 00000000..5886bd00 --- /dev/null +++ b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/test-data-with-multi-line-comments.sql @@ -0,0 +1,17 @@ +/* This is a multi line comment + * The next comment line has no text + + * The next comment line starts with a space. + * x, y, z... + */ + +INSERT INTO users(first_name, last_name) VALUES('Juergen', 'Hoeller'); +-- This is also a comment. +/* + * Let's add another comment + * that covers multiple lines + */INSERT INTO +users(first_name, last_name) +VALUES( 'Sam' -- first_name + , 'Brannen' -- last_name +);--
\ No newline at end of file diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/users-data-without-separator.sql b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/users-data-without-separator.sql new file mode 100644 index 00000000..33bf3b41 --- /dev/null +++ b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/users-data-without-separator.sql @@ -0,0 +1,3 @@ +INSERT INTO +users(first_name, last_name) +values('Sam', 'Brannen')
\ No newline at end of file diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/users-schema-without-separator.sql b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/users-schema-without-separator.sql new file mode 100644 index 00000000..4a4dc97f --- /dev/null +++ b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/users-schema-without-separator.sql @@ -0,0 +1,5 @@ +CREATE TABLE users ( + id INTEGER NOT NULL IDENTITY, + first_name VARCHAR(50) NOT NULL, + last_name VARCHAR(50) NOT NULL +)
\ No newline at end of file diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/users-schema.sql b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/users-schema.sql index 73975e92..80ffe23d 100644 --- a/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/users-schema.sql +++ b/spring-jdbc/src/test/resources/org/springframework/jdbc/datasource/init/users-schema.sql @@ -1,7 +1,7 @@ DROP TABLE users IF EXISTS; CREATE TABLE users ( - id INTEGER NOT NULL IDENTITY PRIMARY KEY, + id INTEGER NOT NULL IDENTITY, first_name VARCHAR(50) NOT NULL, last_name VARCHAR(50) NOT NULL ); |