summaryrefslogtreecommitdiff
path: root/spring-jdbc
diff options
context:
space:
mode:
Diffstat (limited to 'spring-jdbc')
-rw-r--r--spring-jdbc/src/main/java/org/springframework/jdbc/config/DatabasePopulatorConfigUtils.java20
-rw-r--r--spring-jdbc/src/main/java/org/springframework/jdbc/core/BeanPropertyRowMapper.java41
-rw-r--r--spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java34
-rw-r--r--spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataContext.java6
-rw-r--r--spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/AbstractJdbcInsert.java3
-rw-r--r--spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcInsert.java5
-rw-r--r--spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcInsertOperations.java3
-rw-r--r--spring-jdbc/src/main/java/org/springframework/jdbc/datasource/AbstractDriverBasedDataSource.java52
-rw-r--r--spring-jdbc/src/main/java/org/springframework/jdbc/datasource/ConnectionHandle.java4
-rw-r--r--spring-jdbc/src/main/java/org/springframework/jdbc/datasource/ConnectionHolder.java6
-rw-r--r--spring-jdbc/src/main/java/org/springframework/jdbc/datasource/UserCredentialsDataSourceAdapter.java39
-rw-r--r--spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/CompositeDatabasePopulator.java29
-rw-r--r--spring-jdbc/src/main/java/org/springframework/jdbc/object/GenericSqlQuery.java54
-rw-r--r--spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodes.java4
-rw-r--r--spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/DefaultLobHandler.java1
-rw-r--r--spring-jdbc/src/main/resources/META-INF/spring.schemas3
-rw-r--r--spring-jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-4.3.xsd223
-rw-r--r--spring-jdbc/src/main/resources/org/springframework/jdbc/support/sql-error-codes.xml7
-rw-r--r--spring-jdbc/src/test/java/org/springframework/jdbc/config/JdbcNamespaceIntegrationTests.java13
-rw-r--r--spring-jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateQueryTests.java3
-rw-r--r--spring-jdbc/src/test/java/org/springframework/jdbc/datasource/DataSourceJtaTransactionTests.java9
-rw-r--r--spring-jdbc/src/test/java/org/springframework/jdbc/datasource/DataSourceTransactionManagerTests.java4
-rw-r--r--spring-jdbc/src/test/java/org/springframework/jdbc/datasource/init/CompositeDatabasePopulatorTests.java92
-rw-r--r--spring-jdbc/src/test/java/org/springframework/jdbc/datasource/lookup/BeanFactoryDataSourceLookupTests.java5
-rw-r--r--spring-jdbc/src/test/java/org/springframework/jdbc/object/GenericSqlQueryTests.java19
-rw-r--r--spring-jdbc/src/test/java/org/springframework/jdbc/object/StoredProcedureTests.java4
-rw-r--r--spring-jdbc/src/test/java/org/springframework/jdbc/support/rowset/ResultSetWrappingRowSetTests.java3
-rw-r--r--spring-jdbc/src/test/resources/org/springframework/jdbc/config/jdbc-config-custom-separator.xml13
-rw-r--r--spring-jdbc/src/test/resources/org/springframework/jdbc/config/jdbc-initialize-custom-separator.xml15
-rw-r--r--spring-jdbc/src/test/resources/org/springframework/jdbc/object/GenericSqlQueryTests-context.xml26
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