diff options
Diffstat (limited to 'spring-jdbc')
30 files changed, 653 insertions, 87 deletions
diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/config/DatabasePopulatorConfigUtils.java b/spring-jdbc/src/main/java/org/springframework/jdbc/config/DatabasePopulatorConfigUtils.java index eca9a2fd..384cb0c8 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/config/DatabasePopulatorConfigUtils.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/config/DatabasePopulatorConfigUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2016 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. @@ -32,6 +32,7 @@ import org.springframework.util.xml.DomUtils; /** * @author Juergen Hoeller + * @author Stephane Nicoll * @since 3.1 */ class DatabasePopulatorConfigUtils { @@ -70,8 +71,9 @@ class DatabasePopulatorConfigUtils { if (StringUtils.hasLength(scriptElement.getAttribute("encoding"))) { delegate.addPropertyValue("sqlScriptEncoding", new TypedStringValue(scriptElement.getAttribute("encoding"))); } - if (StringUtils.hasLength(scriptElement.getAttribute("separator"))) { - delegate.addPropertyValue("separator", new TypedStringValue(scriptElement.getAttribute("separator"))); + String separator = getSeparator(element, scriptElement); + if (separator != null) { + delegate.addPropertyValue("separator", new TypedStringValue(separator)); } delegates.add(delegate.getBeanDefinition()); } @@ -80,4 +82,16 @@ class DatabasePopulatorConfigUtils { return builder.getBeanDefinition(); } + private static String getSeparator(Element element, Element scriptElement) { + String scriptSeparator = scriptElement.getAttribute("separator"); + if (StringUtils.hasLength(scriptSeparator)) { + return scriptSeparator; + } + String elementSeparator = element.getAttribute("separator"); + if (StringUtils.hasLength(elementSeparator)) { + return elementSeparator; + } + return null; + } + } 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 88baff51..fb280e86 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -34,6 +34,8 @@ import org.springframework.beans.BeanWrapper; import org.springframework.beans.NotWritablePropertyException; import org.springframework.beans.PropertyAccessorFactory; import org.springframework.beans.TypeMismatchException; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.jdbc.support.JdbcUtils; @@ -58,7 +60,7 @@ import org.springframework.util.StringUtils; * <p>To facilitate mapping between columns and fields that don't have matching names, * try using column aliases in the SQL statement like "select fname as first_name from customer". * - * <p>For 'null' values read from the databasem, we will attempt to call the setter, but in the case of + * <p>For 'null' values read from the database, we will attempt to call the setter, but in the case of * Java primitives, this causes a TypeMismatchException. This class can be configured (using the * primitivesDefaultedForNullValue property) to trap this exception and use the primitives default value. * Be aware that if you use the values from the generated bean to update the database the primitive value @@ -85,6 +87,9 @@ public class BeanPropertyRowMapper<T> implements RowMapper<T> { /** Whether we're defaulting primitives when mapping a null value */ private boolean primitivesDefaultedForNullValue = false; + /** ConversionService for binding JDBC values to bean properties */ + private ConversionService conversionService = new DefaultConversionService(); + /** Map of the fields we provide mapping for */ private Map<String, PropertyDescriptor> mappedFields; @@ -179,6 +184,27 @@ public class BeanPropertyRowMapper<T> implements RowMapper<T> { return this.primitivesDefaultedForNullValue; } + /** + * Set a {@link ConversionService} for binding JDBC values to bean properties, + * or {@code null} for none. + * <p>Default is a {@link DefaultConversionService}, as of Spring 4.3. This + * provides support for {@code java.time} conversion and other special types. + * @since 4.3 + * @see #initBeanWrapper(BeanWrapper) + */ + public void setConversionService(ConversionService conversionService) { + this.conversionService = conversionService; + } + + /** + * Return a {@link ConversionService} for binding JDBC values to bean properties, + * or {@code null} if none. + * @since 4.3 + */ + public ConversionService getConversionService() { + return this.conversionService; + } + /** * Initialize the mapping metadata for the given class. @@ -248,7 +274,7 @@ public class BeanPropertyRowMapper<T> implements RowMapper<T> { @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); + T mappedObject = BeanUtils.instantiateClass(this.mappedClass); BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(mappedObject); initBeanWrapper(bw); @@ -313,10 +339,17 @@ public class BeanPropertyRowMapper<T> implements RowMapper<T> { /** * Initialize the given BeanWrapper to be used for row mapping. * To be called for each row. - * <p>The default implementation is empty. Can be overridden in subclasses. + * <p>The default implementation applies the configured {@link ConversionService}, + * if any. Can be overridden in subclasses. * @param bw the BeanWrapper to initialize + * @see #getConversionService() + * @see BeanWrapper#setConversionService */ protected void initBeanWrapper(BeanWrapper bw) { + ConversionService cs = getConversionService(); + if (cs != null) { + bw.setConversionService(cs); + } } /** 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 6d236c02..ec716dd5 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 @@ -219,12 +219,14 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { } /** - * Set the fetch size for this JdbcTemplate. This is important for processing - * large result sets: Setting this higher than the default value will increase - * processing speed at the cost of memory consumption; setting this lower can - * avoid transferring row data that will never be read by the application. - * <p>Default is -1, indicating to use the JDBC driver's default - * (i.e. to not pass a specific fetch size setting on the driver). + * Set the fetch size for this JdbcTemplate. This is important for processing large + * result sets: Setting this higher than the default value will increase processing + * speed at the cost of memory consumption; setting this lower can avoid transferring + * row data that will never be read by the application. + * <p>Default is -1, indicating to use the JDBC driver's default configuration + * (i.e. to not pass a specific fetch size setting on to the driver). + * <p>Note: As of 4.3, negative values other than -1 will get passed on to the + * driver, since e.g. MySQL supports special behavior for {@code Integer.MIN_VALUE}. * @see java.sql.Statement#setFetchSize */ public void setFetchSize(int fetchSize) { @@ -239,13 +241,15 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { } /** - * Set the maximum number of rows for this JdbcTemplate. This is important - * for processing subsets of large result sets, avoiding to read and hold - * the entire result set in the database or in the JDBC driver if we're - * never interested in the entire result in the first place (for example, - * when performing searches that might return a large number of matches). - * <p>Default is -1, indicating to use the JDBC driver's default - * (i.e. to not pass a specific max rows setting on the driver). + * Set the maximum number of rows for this JdbcTemplate. This is important for + * processing subsets of large result sets, avoiding to read and hold the entire + * result set in the database or in the JDBC driver if we're never interested in + * the entire result in the first place (for example, when performing searches + * that might return a large number of matches). + * <p>Default is -1, indicating to use the JDBC driver's default configuration + * (i.e. to not pass a specific max rows setting on to the driver). + * <p>Note: As of 4.3, negative values other than -1 will get passed on to the + * driver, in sync with {@link #setFetchSize}'s support for special MySQL values. * @see java.sql.Statement#setMaxRows */ public void setMaxRows(int maxRows) { @@ -1349,11 +1353,11 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { */ protected void applyStatementSettings(Statement stmt) throws SQLException { int fetchSize = getFetchSize(); - if (fetchSize >= 0) { + if (fetchSize != -1) { stmt.setFetchSize(fetchSize); } int maxRows = getMaxRows(); - if (maxRows >= 0) { + if (maxRows != -1) { stmt.setMaxRows(maxRows); } DataSourceUtils.applyTimeout(stmt, getDataSource(), getQueryTimeout()); diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataContext.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataContext.java index 63ea39ec..0a2e6d63 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataContext.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataContext.java @@ -47,13 +47,13 @@ public class TableMetaDataContext { /** Logger available to subclasses */ protected final Log logger = LogFactory.getLog(getClass()); - /** name of procedure to call **/ + /** name of table for this context **/ private String tableName; - /** name of catalog for call **/ + /** name of catalog for this context **/ private String catalogName; - /** name of schema for call **/ + /** name of schema for this context **/ private String schemaName; /** List of columns objects to be used in this context */ 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 3af9f463..3d7c25f1 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -542,6 +542,7 @@ public abstract class AbstractJdbcInsert { * @param batch array of Maps with parameter names and values to be used in batch insert * @return array of number of rows affected */ + @SuppressWarnings("unchecked") protected int[] doExecuteBatch(Map<String, ?>... batch) { checkCompiled(); List<List<Object>> batchValues = new ArrayList<List<Object>>(batch.length); 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 d178cc61..41742350 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -32,7 +32,7 @@ import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor; * name of the table and a Map containing the column names and the column values. * * <p>The meta data processing is based on the DatabaseMetaData provided by the - * JDBC driver. As long as the JBDC driver can provide the names of the columns + * JDBC driver. As long as the JDBC driver can provide the names of the columns * for a specified table than we can rely on this auto-detection feature. If that * is not the case, then the column names must be specified explicitly. * @@ -148,6 +148,7 @@ public class SimpleJdbcInsert extends AbstractJdbcInsert implements SimpleJdbcIn } @Override + @SuppressWarnings("unchecked") public int[] executeBatch(Map<String, ?>... batch) { return doExecuteBatch(batch); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcInsertOperations.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcInsertOperations.java index 0e1dd15c..645a2a97 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcInsertOperations.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcInsertOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -152,6 +152,7 @@ public interface SimpleJdbcInsertOperations { * @param batch an array of Maps containing a batch of column names and corresponding value * @return the array of number of rows affected as returned by the JDBC driver */ + @SuppressWarnings("unchecked") int[] executeBatch(Map<String, ?>... batch); /** 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 0a2808fe..e5be5182 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2016 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,6 +20,7 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; +import org.springframework.lang.UsesJava7; import org.springframework.util.Assert; /** @@ -39,6 +40,10 @@ public abstract class AbstractDriverBasedDataSource extends AbstractDataSource { private String password; + private String catalog; + + private String schema; + private Properties connectionProperties; @@ -89,6 +94,40 @@ public abstract class AbstractDriverBasedDataSource extends AbstractDataSource { } /** + * Specify a database catalog to be applied to each Connection. + * @since 4.3.2 + * @see Connection#setCatalog + */ + public void setCatalog(String catalog) { + this.catalog = catalog; + } + + /** + * Return the database catalog to be applied to each Connection, if any. + * @since 4.3.2 + */ + public String getCatalog() { + return this.catalog; + } + + /** + * Specify a database schema to be applied to each Connection. + * @since 4.3.2 + * @see Connection#setSchema + */ + public void setSchema(String schema) { + this.schema = schema; + } + + /** + * Return the database schema to be applied to each Connection, if any. + * @since 4.3.2 + */ + public String getSchema() { + return this.schema; + } + + /** * Specify arbitrary connection properties as key/value pairs, * to be passed to the Driver. * <p>Can also contain "user" and "password" properties. However, @@ -140,6 +179,7 @@ public abstract class AbstractDriverBasedDataSource extends AbstractDataSource { * @throws SQLException in case of failure * @see java.sql.Driver#connect(String, java.util.Properties) */ + @UsesJava7 protected Connection getConnectionFromDriver(String username, String password) throws SQLException { Properties mergedProps = new Properties(); Properties connProps = getConnectionProperties(); @@ -152,7 +192,15 @@ public abstract class AbstractDriverBasedDataSource extends AbstractDataSource { if (password != null) { mergedProps.setProperty("password", password); } - return getConnectionFromDriver(mergedProps); + + Connection con = getConnectionFromDriver(mergedProps); + if (this.catalog != null) { + con.setCatalog(this.catalog); + } + if (this.schema != null) { + con.setSchema(this.schema); + } + return con; } /** 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 2343aef4..7b361385 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-2014 the original author or authors. + * Copyright 2002-2016 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,7 +26,7 @@ import java.sql.Connection; * @since 1.1 * @see SimpleConnectionHandle * @see ConnectionHolder - * @see org.springframework.orm.jdo.JpaDialect#getJdbcConnection + * @see org.springframework.orm.jpa.JpaDialect#getJdbcConnection * @see org.springframework.orm.jdo.JdoDialect#getJdbcConnection */ public interface ConnectionHandle { diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/ConnectionHolder.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/ConnectionHolder.java index 6ed77ef0..95447490 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/ConnectionHolder.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/ConnectionHolder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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. @@ -161,9 +161,9 @@ public class ConnectionHolder extends ResourceHolderSupport { */ public boolean supportsSavepoints() throws SQLException { if (this.savepointsSupported == null) { - this.savepointsSupported = new Boolean(getConnection().getMetaData().supportsSavepoints()); + this.savepointsSupported = getConnection().getMetaData().supportsSavepoints(); } - return this.savepointsSupported.booleanValue(); + return this.savepointsSupported; } /** diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/UserCredentialsDataSourceAdapter.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/UserCredentialsDataSourceAdapter.java index cfcaca4d..14021771 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/UserCredentialsDataSourceAdapter.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/UserCredentialsDataSourceAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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,6 +20,7 @@ import java.sql.Connection; import java.sql.SQLException; import org.springframework.core.NamedThreadLocal; +import org.springframework.lang.UsesJava7; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -65,6 +66,10 @@ public class UserCredentialsDataSourceAdapter extends DelegatingDataSource { private String password; + private String catalog; + + private String schema; + private final ThreadLocal<JdbcUserCredentials> threadBoundCredentials = new NamedThreadLocal<JdbcUserCredentials>("Current JDBC user credentials"); @@ -93,6 +98,24 @@ public class UserCredentialsDataSourceAdapter extends DelegatingDataSource { this.password = password; } + /** + * Specify a database catalog to be applied to each retrieved Connection. + * @since 4.3.2 + * @see Connection#setCatalog + */ + public void setCatalog(String catalog) { + this.catalog = catalog; + } + + /** + * Specify a database schema to be applied to each retrieved Connection. + * @since 4.3.2 + * @see Connection#setSchema + */ + public void setSchema(String schema) { + this.schema = schema; + } + /** * Set user credententials for this proxy and the current thread. @@ -126,14 +149,20 @@ public class UserCredentialsDataSourceAdapter extends DelegatingDataSource { * determined credentials as parameters. */ @Override + @UsesJava7 public Connection getConnection() throws SQLException { JdbcUserCredentials threadCredentials = this.threadBoundCredentials.get(); - if (threadCredentials != null) { - return doGetConnection(threadCredentials.username, threadCredentials.password); + Connection con = (threadCredentials != null ? + doGetConnection(threadCredentials.username, threadCredentials.password) : + doGetConnection(this.username, this.password)); + + if (this.catalog != null) { + con.setCatalog(this.catalog); } - else { - return doGetConnection(this.username, this.password); + if (this.schema != null) { + con.setSchema(this.schema); } + return con; } /** 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 b8924624..0ae78488 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 @@ -20,6 +20,7 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.List; /** @@ -29,6 +30,7 @@ import java.util.List; * @author Dave Syer * @author Juergen Hoeller * @author Sam Brannen + * @author Kazuki Shimizu * @since 3.1 */ public class CompositeDatabasePopulator implements DatabasePopulator { @@ -37,6 +39,33 @@ public class CompositeDatabasePopulator implements DatabasePopulator { /** + * Create an empty {@code CompositeDatabasePopulator}. + * @see #setPopulators + * @see #addPopulators + */ + public CompositeDatabasePopulator() { + } + + /** + * Create a {@code CompositeDatabasePopulator} with the given populators. + * @param populators one or more populators to delegate to + * @since 4.3 + */ + public CompositeDatabasePopulator(Collection<DatabasePopulator> populators) { + this.populators.addAll(populators); + } + + /** + * Create a {@code CompositeDatabasePopulator} with the given populators. + * @param populators one or more populators to delegate to + * @since 4.3 + */ + public CompositeDatabasePopulator(DatabasePopulator... populators) { + this.populators.addAll(Arrays.asList(populators)); + } + + + /** * Specify one or more populators to delegate to. */ public void setPopulators(DatabasePopulator... populators) { 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 d2af6281..dbbfd5c1 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 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,43 +18,57 @@ package org.springframework.jdbc.object; import java.util.Map; -import org.springframework.dao.InvalidDataAccessResourceUsageException; +import org.springframework.beans.BeanUtils; import org.springframework.jdbc.core.RowMapper; import org.springframework.util.Assert; +/** + * A concrete variant of {@link SqlQuery} which can be configured + * with a {@link RowMapper}. + * + * @author Thomas Risberg + * @author Juergen Hoeller + * @since 3.0 + * @see #setRowMapper + * @see #setRowMapperClass + */ public class GenericSqlQuery<T> extends SqlQuery<T> { - Class<?> rowMapperClass; + private RowMapper<T> rowMapper; + + @SuppressWarnings("rawtypes") + private Class<? extends RowMapper> rowMapperClass; + - RowMapper<?> rowMapper; + /** + * Set a specific {@link RowMapper} instance to use for this query. + * @since 4.3.2 + */ + public void setRowMapper(RowMapper<T> rowMapper) { + this.rowMapper = rowMapper; + } + /** + * Set a {@link RowMapper} class for this query, creating a fresh + * {@link RowMapper} instance per execution. + */ @SuppressWarnings("rawtypes") - public void setRowMapperClass(Class<? extends RowMapper> rowMapperClass) - throws IllegalAccessException, InstantiationException { + public void setRowMapperClass(Class<? extends RowMapper> rowMapperClass) { this.rowMapperClass = rowMapperClass; - if (!RowMapper.class.isAssignableFrom(rowMapperClass)) - throw new IllegalStateException("The specified class '" + - rowMapperClass.getName() + " is not a sub class of " + - "'org.springframework.jdbc.core.RowMapper'"); } @Override public void afterPropertiesSet() { super.afterPropertiesSet(); - Assert.notNull(rowMapperClass, "The 'rowMapperClass' property is required"); + Assert.isTrue(this.rowMapper != null || this.rowMapperClass != null, + "'rowMapper' or 'rowMapperClass' is required"); } + @Override @SuppressWarnings("unchecked") protected RowMapper<T> newRowMapper(Object[] parameters, Map<?, ?> context) { - try { - return (RowMapper<T>) rowMapperClass.newInstance(); - } - catch (InstantiationException e) { - throw new InvalidDataAccessResourceUsageException("Unable to instantiate RowMapper", e); - } - catch (IllegalAccessException e) { - throw new InvalidDataAccessResourceUsageException("Unable to instantiate RowMapper", e); - } + return (this.rowMapper != null ? this.rowMapper : BeanUtils.instantiateClass(this.rowMapperClass)); } + } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodes.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodes.java index 7a9c1399..826b9db6 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodes.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodes.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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. @@ -192,7 +192,7 @@ public class SQLErrorCodes { try { this.customSqlExceptionTranslator = customTranslatorClass.newInstance(); } - catch (Exception ex) { + catch (Throwable ex) { throw new IllegalStateException("Unable to instantiate custom translator", ex); } } 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 57aad967..b63c4e2b 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 @@ -207,7 +207,6 @@ public class DefaultLobHandler extends AbstractLobHandler { } @Override - @SuppressWarnings("resource") public LobCreator getLobCreator() { return (this.createTemporaryLob ? new TemporaryLobCreator() : new DefaultLobCreator()); } diff --git a/spring-jdbc/src/main/resources/META-INF/spring.schemas b/spring-jdbc/src/main/resources/META-INF/spring.schemas index 44835b63..d0396fe1 100644 --- a/spring-jdbc/src/main/resources/META-INF/spring.schemas +++ b/spring-jdbc/src/main/resources/META-INF/spring.schemas @@ -4,4 +4,5 @@ http\://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd=org/springframew 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-4.1.xsd=org/springframework/jdbc/config/spring-jdbc-4.1.xsd http\://www.springframework.org/schema/jdbc/spring-jdbc-4.2.xsd=org/springframework/jdbc/config/spring-jdbc-4.2.xsd -http\://www.springframework.org/schema/jdbc/spring-jdbc.xsd=org/springframework/jdbc/config/spring-jdbc-4.2.xsd +http\://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd=org/springframework/jdbc/config/spring-jdbc-4.3.xsd +http\://www.springframework.org/schema/jdbc/spring-jdbc.xsd=org/springframework/jdbc/config/spring-jdbc-4.3.xsd diff --git a/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-4.3.xsd b/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-4.3.xsd new file mode 100644 index 00000000..ab76e90f --- /dev/null +++ b/spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-4.3.xsd @@ -0,0 +1,223 @@ +<?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.3.xsd"/> + <xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-4.3.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[ + An SQL script to execute to populate, initialize, or clean up an embedded database. + ]]></xsd:documentation> + </xsd:annotation> + </xsd:element> + </xsd:sequence> + <xsd:attribute name="database-name" type="xsd:string" default=""> + <xsd:annotation> + <xsd:documentation><![CDATA[ + The name to assign to the embedded database. Note that this is not the + bean name but rather the name of the embedded database as used in the JDBC + connection URL for the database. Defaults to "testdb" if an explicit bean + 'id' has not been provided. + ]]></xsd:documentation> + </xsd:annotation> + </xsd:attribute> + <xsd:attribute name="generate-name" type="xsd:string" use="optional" default="false"> + <xsd:annotation> + <xsd:documentation> + If set to "true", a pseudo-random unique name will be generated for the embedded + database, overriding any implicit name provided via the 'id' attribute or any + explicit name provided via the 'database-name' attribute. + Note that this is not the bean name but rather the name of the embedded database + as used in the JDBC connection URL for the database. + </xsd:documentation> + </xsd:annotation> + </xsd:attribute> + <xsd:attribute name="separator" type="xsd:string"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + The default statement separator to use (the default is to use ';' if it is present + in the script, or '\n' otherwise). + ]]></xsd:documentation> + </xsd:annotation> + </xsd:attribute> + <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[ + An SQL script to execute to populate, initialize, or clean up a database. + ]]></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 script execution + 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 execution? + </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:attribute name="separator" type="xsd:string"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + The default statement separator to use (the default is to use ';' if it is present + in the script, or '\n' otherwise). + ]]></xsd:documentation> + </xsd:annotation> + </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 execution phase of this script. Use INIT to execute on startup (as a + bean initialization) or 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[ + HyperSQL DataBase Engine + ]]></xsd:documentation> + </xsd:annotation> + </xsd:enumeration> + <xsd:enumeration value="H2"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + H2 Database Engine + ]]></xsd:documentation> + </xsd:annotation> + </xsd:enumeration> + <xsd:enumeration value="DERBY"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + Apache Derby Database Engine + ]]></xsd:documentation> + </xsd:annotation> + </xsd:enumeration> + </xsd:restriction> + </xsd:simpleType> + +</xsd:schema> diff --git a/spring-jdbc/src/main/resources/org/springframework/jdbc/support/sql-error-codes.xml b/spring-jdbc/src/main/resources/org/springframework/jdbc/support/sql-error-codes.xml index 3fe34efe..c0278d59 100644 --- a/spring-jdbc/src/main/resources/org/springframework/jdbc/support/sql-error-codes.xml +++ b/spring-jdbc/src/main/resources/org/springframework/jdbc/support/sql-error-codes.xml @@ -250,8 +250,11 @@ <!-- http://help.sap.com/saphelp_hanaplatform/helpdata/en/20/a78d3275191014b41bae7c4a46d835/content.htm --> <bean id="Hana" class="org.springframework.jdbc.support.SQLErrorCodes"> - <property name="databaseProductName"> - <value>SAP DB</value> + <property name="databaseProductNames"> + <list> + <value>SAP DB</value> + <value>HDB</value> + </list> </property> <property name="badSqlGrammarCodes"> <value> 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 6615c885..d15f94b4 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-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -48,6 +48,7 @@ import static org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFacto * @author Juergen Hoeller * @author Chris Beams * @author Sam Brannen + * @author Stephane Nicoll */ public class JdbcNamespaceIntegrationTests { @@ -165,6 +166,16 @@ public class JdbcNamespaceIntegrationTests { assertBeanPropertyValueOf("databaseName", "secondDataSource", factory); } + @Test + public void initializeWithCustomSeparator() throws Exception { + assertCorrectSetupAndCloseContext("jdbc-initialize-custom-separator.xml", 2, "dataSource"); + } + + @Test + public void embeddedWithCustomSeparator() throws Exception { + assertCorrectSetupAndCloseContext("jdbc-config-custom-separator.xml", 2, "dataSource"); + } + private ClassPathXmlApplicationContext context(String file) { return new ClassPathXmlApplicationContext(file, getClass()); } diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateQueryTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateQueryTests.java index bbcc5657..f8fc598b 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateQueryTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateQueryTests.java @@ -150,7 +150,8 @@ public class JdbcTemplateQueryTests { this.thrown.expect(IncorrectResultSizeDataAccessException.class); try { this.template.queryForObject(sql, String.class); - } finally { + } + finally { verify(this.resultSet).close(); verify(this.statement).close(); } diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/DataSourceJtaTransactionTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/DataSourceJtaTransactionTests.java index c5247749..3cda75ea 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/DataSourceJtaTransactionTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/DataSourceJtaTransactionTests.java @@ -292,13 +292,14 @@ public class DataSourceJtaTransactionTests { assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); verify(userTransaction, times(6)).begin(); verify(transactionManager, times(5)).resume(transaction); - if(rollback) { + if (rollback) { verify(userTransaction, times(5)).commit(); verify(userTransaction).rollback(); - } else { + } + else { verify(userTransaction, times(6)).commit(); } - if(accessAfterResume && !openOuterConnection) { + if (accessAfterResume && !openOuterConnection) { verify(connection, times(7)).close(); } else { @@ -528,7 +529,7 @@ public class DataSourceJtaTransactionTests { assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive()); verify(userTransaction).begin(); - if(suspendException) { + if (suspendException) { verify(userTransaction).rollback(); } diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/DataSourceTransactionManagerTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/DataSourceTransactionManagerTests.java index e4ecd2fc..211445a1 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/DataSourceTransactionManagerTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/DataSourceTransactionManagerTests.java @@ -152,7 +152,7 @@ public class DataSourceTransactionManagerTests { assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(dsToUse)); assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive()); - if(autoCommit && (!lazyConnection || createStatement)) { + if (autoCommit && (!lazyConnection || createStatement)) { InOrder ordered = inOrder(con); ordered.verify(con).setAutoCommit(false); ordered.verify(con).commit(); @@ -244,7 +244,7 @@ public class DataSourceTransactionManagerTests { assertTrue("Hasn't thread connection", !TransactionSynchronizationManager.hasResource(ds)); assertTrue("Synchronization not active", !TransactionSynchronizationManager.isSynchronizationActive()); - if(autoCommit && (!lazyConnection || createStatement)) { + if (autoCommit && (!lazyConnection || createStatement)) { InOrder ordered = inOrder(con); ordered.verify(con).setAutoCommit(false); ordered.verify(con).rollback(); diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/CompositeDatabasePopulatorTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/CompositeDatabasePopulatorTests.java new file mode 100644 index 00000000..d3c3b7f7 --- /dev/null +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/CompositeDatabasePopulatorTests.java @@ -0,0 +1,92 @@ +/* + * Copyright 2002-2016 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 java.util.LinkedHashSet; +import java.util.Set; + +import org.junit.Test; + +import static org.mockito.Mockito.*; + +/** + * Unit tests for {@link CompositeDatabasePopulator}. + * + * @author Kazuki Shimizu + * @author Juergen Hoeller + * @since 4.3 + */ +public class CompositeDatabasePopulatorTests { + + private final Connection mockedConnection = mock(Connection.class); + + private final DatabasePopulator mockedDatabasePopulator1 = mock(DatabasePopulator.class); + + private final DatabasePopulator mockedDatabasePopulator2 = mock(DatabasePopulator.class); + + + @Test + public void addPopulators() throws SQLException { + CompositeDatabasePopulator populator = new CompositeDatabasePopulator(); + populator.addPopulators(mockedDatabasePopulator1, mockedDatabasePopulator2); + populator.populate(mockedConnection); + verify(mockedDatabasePopulator1,times(1)).populate(mockedConnection); + verify(mockedDatabasePopulator2, times(1)).populate(mockedConnection); + } + + @Test + public void setPopulatorsWithMultiple() throws SQLException { + CompositeDatabasePopulator populator = new CompositeDatabasePopulator(); + populator.setPopulators(mockedDatabasePopulator1, mockedDatabasePopulator2); // multiple + populator.populate(mockedConnection); + verify(mockedDatabasePopulator1, times(1)).populate(mockedConnection); + verify(mockedDatabasePopulator2, times(1)).populate(mockedConnection); + } + + @Test + public void setPopulatorsForOverride() throws SQLException { + CompositeDatabasePopulator populator = new CompositeDatabasePopulator(); + populator.setPopulators(mockedDatabasePopulator1); + populator.setPopulators(mockedDatabasePopulator2); // override + populator.populate(mockedConnection); + verify(mockedDatabasePopulator1, times(0)).populate(mockedConnection); + verify(mockedDatabasePopulator2, times(1)).populate(mockedConnection); + } + + @Test + public void constructWithVarargs() throws SQLException { + CompositeDatabasePopulator populator = + new CompositeDatabasePopulator(mockedDatabasePopulator1, mockedDatabasePopulator2); + populator.populate(mockedConnection); + verify(mockedDatabasePopulator1, times(1)).populate(mockedConnection); + verify(mockedDatabasePopulator2, times(1)).populate(mockedConnection); + } + + @Test + public void constructWithCollection() throws SQLException { + Set<DatabasePopulator> populators = new LinkedHashSet<>(); + populators.add(mockedDatabasePopulator1); + populators.add(mockedDatabasePopulator2); + CompositeDatabasePopulator populator = new CompositeDatabasePopulator(populators); + populator.populate(mockedConnection); + verify(mockedDatabasePopulator1, times(1)).populate(mockedConnection); + verify(mockedDatabasePopulator2, times(1)).populate(mockedConnection); + } + +} diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/lookup/BeanFactoryDataSourceLookupTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/lookup/BeanFactoryDataSourceLookupTests.java index a1b19afa..3cef22b8 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/lookup/BeanFactoryDataSourceLookupTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/lookup/BeanFactoryDataSourceLookupTests.java @@ -63,10 +63,11 @@ public class BeanFactoryDataSourceLookupTests { BeanFactoryDataSourceLookup lookup = new BeanFactoryDataSourceLookup(beanFactory); lookup.getDataSource(DATASOURCE_BEAN_NAME); fail("should have thrown DataSourceLookupFailureException"); - } catch (DataSourceLookupFailureException ex) { /* expected */ } + } + catch (DataSourceLookupFailureException ex) { /* expected */ } } - @Test(expected=IllegalStateException.class) + @Test(expected = IllegalStateException.class) public void testLookupWhereBeanFactoryHasNotBeenSupplied() throws Exception { BeanFactoryDataSourceLookup lookup = new BeanFactoryDataSourceLookup(); lookup.getDataSource(DATASOURCE_BEAN_NAME); diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/object/GenericSqlQueryTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/object/GenericSqlQueryTests.java index ed32b628..5a90e703 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/object/GenericSqlQueryTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/object/GenericSqlQueryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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,7 +16,6 @@ package org.springframework.jdbc.object; - import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -43,11 +42,12 @@ import static org.mockito.BDDMockito.*; /** * @author Thomas Risberg + * @author Juergen Hoeller */ public class GenericSqlQueryTests { private static final String SELECT_ID_FORENAME_NAMED_PARAMETERS_PARSED = - "select id, forename from custmr where id = ? and country = ?"; + "select id, forename from custmr where id = ? and country = ?"; private BeanFactory beanFactory; @@ -57,6 +57,7 @@ public class GenericSqlQueryTests { private ResultSet resultSet; + @Before public void setUp() throws Exception { this.beanFactory = new DefaultListableBeanFactory(); @@ -72,17 +73,23 @@ public class GenericSqlQueryTests { } @Test - public void testPlaceHoldersCustomerQuery() throws SQLException { - SqlQuery<?> query = (SqlQuery<?>) beanFactory.getBean("queryWithPlaceHolders"); + public void testCustomerQueryWithPlaceholders() throws SQLException { + SqlQuery<?> query = (SqlQuery<?>) beanFactory.getBean("queryWithPlaceholders"); doTestCustomerQuery(query, false); } @Test - public void testNamedParameterCustomerQuery() throws SQLException { + public void testCustomerQueryWithNamedParameters() throws SQLException { SqlQuery<?> query = (SqlQuery<?>) beanFactory.getBean("queryWithNamedParameters"); doTestCustomerQuery(query, true); } + @Test + public void testCustomerQueryWithRowMapperInstance() throws SQLException { + SqlQuery<?> query = (SqlQuery<?>) beanFactory.getBean("queryWithRowMapperBean"); + doTestCustomerQuery(query, true); + } + private void doTestCustomerQuery(SqlQuery<?> query, boolean namedParameters) throws SQLException { given(resultSet.next()).willReturn(true); given(resultSet.getInt("id")).willReturn(1); diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/object/StoredProcedureTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/object/StoredProcedureTests.java index 73427778..4c40aa99 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/object/StoredProcedureTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/object/StoredProcedureTests.java @@ -81,7 +81,7 @@ public class StoredProcedureTests { @After public void verifyClosed() throws Exception { - if(verifyClosedAfter) { + if (verifyClosedAfter) { verify(callableStatement).close(); verify(connection, atLeastOnce()).close(); } @@ -189,7 +189,7 @@ public class StoredProcedureTests { TestJdbcTemplate t = new TestJdbcTemplate(); t.setDataSource(dataSource); // Will fail without the following, because we're not able to get a connection - // from the DataSource here if we need to to create an ExceptionTranslator + // from the DataSource here if we need to create an ExceptionTranslator t.setExceptionTranslator(new SQLStateSQLExceptionTranslator()); StoredProcedureConfiguredViaJdbcTemplate sp = new StoredProcedureConfiguredViaJdbcTemplate(t); diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/support/rowset/ResultSetWrappingRowSetTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/support/rowset/ResultSetWrappingRowSetTests.java index 1637764d..0b048d08 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/support/rowset/ResultSetWrappingRowSetTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/support/rowset/ResultSetWrappingRowSetTests.java @@ -205,7 +205,8 @@ public class ResultSetWrappingRowSetTests { if (arg instanceof String) { given(rset.findColumn((String) arg)).willReturn(1); given(rsetMethod.invoke(rset, 1)).willReturn(ret).willThrow(new SQLException("test")); - } else { + } + else { given(rsetMethod.invoke(rset, arg)).willReturn(ret).willThrow(new SQLException("test")); } rowsetMethod.invoke(rowset, arg); diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/config/jdbc-config-custom-separator.xml b/spring-jdbc/src/test/resources/org/springframework/jdbc/config/jdbc-config-custom-separator.xml new file mode 100644 index 00000000..7f9479e3 --- /dev/null +++ b/spring-jdbc/src/test/resources/org/springframework/jdbc/config/jdbc-config-custom-separator.xml @@ -0,0 +1,13 @@ +<?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-4.3.xsd"> + + <jdbc:embedded-database id="dataSource" type="HSQL" separator="@@"> + <jdbc:script location="classpath:org/springframework/jdbc/config/db-schema.sql" separator=";"/> + <jdbc:script location="classpath:org/springframework/jdbc/config/db-test-data-endings.sql"/> + </jdbc:embedded-database> + +</beans> diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/config/jdbc-initialize-custom-separator.xml b/spring-jdbc/src/test/resources/org/springframework/jdbc/config/jdbc-initialize-custom-separator.xml new file mode 100644 index 00000000..8a2ea731 --- /dev/null +++ b/spring-jdbc/src/test/resources/org/springframework/jdbc/config/jdbc-initialize-custom-separator.xml @@ -0,0 +1,15 @@ +<?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-4.3.xsd"> + + <jdbc:embedded-database id="dataSource" type="HSQL"/> + + <jdbc:initialize-database data-source="dataSource" separator="@@"> + <jdbc:script location="classpath:org/springframework/jdbc/config/db-schema.sql" separator=";" encoding="ISO-8859-1"/> + <jdbc:script location="classpath:org/springframework/jdbc/config/db-test-data-endings.sql"/> + </jdbc:initialize-database> + +</beans> diff --git a/spring-jdbc/src/test/resources/org/springframework/jdbc/object/GenericSqlQueryTests-context.xml b/spring-jdbc/src/test/resources/org/springframework/jdbc/object/GenericSqlQueryTests-context.xml index 908653e3..71950206 100644 --- a/spring-jdbc/src/test/resources/org/springframework/jdbc/object/GenericSqlQueryTests-context.xml +++ b/spring-jdbc/src/test/resources/org/springframework/jdbc/object/GenericSqlQueryTests-context.xml @@ -6,7 +6,7 @@ <bean id="dataSource" class="org.springframework.jdbc.datasource.TestDataSourceWrapper"/> - <bean id="queryWithPlaceHolders" class="org.springframework.jdbc.object.GenericSqlQuery"> + <bean id="queryWithPlaceholders" class="org.springframework.jdbc.object.GenericSqlQuery"> <property name="dataSource" ref="dataSource"/> <property name="sql" value="select id, forename from custmr where id = ? and country = ?"/> <property name="parameters"> @@ -50,4 +50,28 @@ <property name="rowMapperClass" value="org.springframework.jdbc.object.CustomerMapper"/> </bean> + <bean id="queryWithRowMapperBean" class="org.springframework.jdbc.object.GenericSqlQuery"> + <property name="dataSource" ref="dataSource"/> + <property name="sql" value="select id, forename from custmr where id = :id and country = :country"/> + <property name="parameters"> + <list> + <bean class="org.springframework.jdbc.core.SqlParameter"> + <constructor-arg index="0" value="id"/> + <constructor-arg index="1"> + <util:constant static-field="java.sql.Types.INTEGER"/> + </constructor-arg> + </bean> + <bean class="org.springframework.jdbc.core.SqlParameter"> + <constructor-arg index="0" value="country"/> + <constructor-arg index="1"> + <util:constant static-field="java.sql.Types.VARCHAR"/> + </constructor-arg> + </bean> + </list> + </property> + <property name="rowMapper"> + <bean class="org.springframework.jdbc.object.CustomerMapper"/> + </property> + </bean> + </beans>
\ No newline at end of file |