Browse Source

Allow parameter name binding for SimpleJdbcCall

Update SimpleJdbcCall to offer a way to use named parameters binding
instead of the simple `?` binding it offers thus far.

Issue: SPR-12801
pull/799/head
Stephane Nicoll 10 years ago
parent
commit
8dec8823fb
  1. 34
      spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java
  2. 17
      spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/AbstractJdbcCall.java
  3. 9
      spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcCall.java
  4. 9
      spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcCallOperations.java
  5. 40
      spring-jdbc/src/test/java/org/springframework/jdbc/core/simple/SimpleJdbcCallTests.java

34
spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@ -46,6 +46,7 @@ import org.springframework.util.StringUtils; @@ -46,6 +46,7 @@ import org.springframework.util.StringUtils;
*
* @author Thomas Risberg
* @author Juergen Hoeller
* @author Kiril Nugmanov
* @since 2.5
*/
public class CallMetaDataContext {
@ -83,6 +84,9 @@ public class CallMetaDataContext { @@ -83,6 +84,9 @@ public class CallMetaDataContext {
/** Should we access call parameter meta data info or not */
private boolean accessCallParameterMetaData = true;
/** Should we bind parameter by name **/
private boolean namedBinding;
/** The provider of call meta data */
private CallMetaDataProvider metaDataProvider;
@ -213,6 +217,19 @@ public class CallMetaDataContext { @@ -213,6 +217,19 @@ public class CallMetaDataContext {
return this.accessCallParameterMetaData;
}
/**
* Specify whether parameters should be bound by name.
*/
public void setNamedBinding(boolean namedBinding) {
this.namedBinding = namedBinding;
}
/**
* Check whether parameters should be bound by name.
*/
public boolean isNamedBinding() {
return namedBinding;
}
/**
* Create a ReturnResultSetParameter/SqlOutParameter depending on the support provided
@ -595,7 +612,7 @@ public class CallMetaDataContext { @@ -595,7 +612,7 @@ public class CallMetaDataContext {
callString += ", ";
}
if (parameterCount >= 0) {
callString += "?";
callString += createParameterBinding(parameter);
}
parameterCount++;
}
@ -605,4 +622,17 @@ public class CallMetaDataContext { @@ -605,4 +622,17 @@ public class CallMetaDataContext {
return callString;
}
/**
* Build the parameter binding fragment.
* @param parameter call parameter
* @return parameter binding fragment
*/
protected String createParameterBinding(SqlParameter parameter) {
if (isNamedBinding()) {
return parameter.getName() + " => ?";
} else {
return "?";
}
}
}

17
spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/AbstractJdbcCall.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@ -198,6 +198,21 @@ public abstract class AbstractJdbcCall { @@ -198,6 +198,21 @@ public abstract class AbstractJdbcCall {
this.callMetaDataContext.setAccessCallParameterMetaData(accessCallParameterMetaData);
}
/**
* Does parameters should be bound by name?
*/
public boolean isNamedBinding() {
return this.callMetaDataContext.isNamedBinding();
}
/**
* Specify whether parameters should be bound by name.
* The default is {@code false}.
*/
public void setNamedBinding(boolean namedBinding) {
this.callMetaDataContext.setNamedBinding(namedBinding);
}
/**
* Get the call string that should be used based on parameters and meta data.
*/

9
spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcCall.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@ -53,6 +53,7 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource; @@ -53,6 +53,7 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource;
* to provide the ability to chain multiple ones together in a "fluent" interface style.
*
* @author Thomas Risberg
* @author Stephane Nicoll
* @since 2.5
* @see java.sql.DatabaseMetaData
* @see org.springframework.jdbc.core.JdbcTemplate
@ -139,6 +140,12 @@ public class SimpleJdbcCall extends AbstractJdbcCall implements SimpleJdbcCallOp @@ -139,6 +140,12 @@ public class SimpleJdbcCall extends AbstractJdbcCall implements SimpleJdbcCallOp
return this;
}
@Override
public SimpleJdbcCall withNamedBinding() {
setNamedBinding(true);
return this;
}
@Override
@SuppressWarnings("unchecked")
public <T> T executeFunction(Class<T> returnType, Object... args) {

9
spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/SimpleJdbcCallOperations.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@ -28,6 +28,7 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource; @@ -28,6 +28,7 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource;
* as it can easily be mocked or stubbed.
*
* @author Thomas Risberg
* @author Stephane Nicoll
* @since 2.5
*/
public interface SimpleJdbcCallOperations {
@ -100,6 +101,12 @@ public interface SimpleJdbcCallOperations { @@ -100,6 +101,12 @@ public interface SimpleJdbcCallOperations {
*/
SimpleJdbcCallOperations withoutProcedureColumnMetaDataAccess();
/**
* Indicates that parameters should be bound by name.
* @return the instance of this SimpleJdbcCall
*/
SimpleJdbcCallOperations withNamedBinding();
/**
* Execute the stored function and return the results obtained as an Object of the

40
spring-jdbc/src/test/java/org/springframework/jdbc/core/simple/SimpleJdbcCallTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@ -24,6 +24,7 @@ import java.sql.SQLException; @@ -24,6 +24,7 @@ import java.sql.SQLException;
import java.sql.Types;
import javax.sql.DataSource;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@ -41,9 +42,10 @@ import static org.mockito.BDDMockito.*; @@ -41,9 +42,10 @@ import static org.mockito.BDDMockito.*;
import static org.springframework.tests.Matchers.*;
/**
* Mock object based tests for SimpleJdbcCall.
* Tests for {@link SimpleJdbcCall}.
*
* @author Thomas Risberg
* @author Kiril Nugmanov
*/
public class SimpleJdbcCallTests {
@ -193,7 +195,8 @@ public class SimpleJdbcCallTests { @@ -193,7 +195,8 @@ public class SimpleJdbcCallTests {
}
@Test public void testAddInvoiceFuncWithMetaDataUsingArrayParams() throws Exception {
@Test
public void testAddInvoiceFuncWithMetaDataUsingArrayParams() throws Exception {
initializeAddInvoiceWithMetaData(true);
SimpleJdbcCall adder = new SimpleJdbcCall(dataSource).withFunctionName("add_invoice");
Number newId = adder.executeFunction(Number.class, 1103, 3);
@ -203,6 +206,34 @@ public class SimpleJdbcCallTests { @@ -203,6 +206,34 @@ public class SimpleJdbcCallTests {
}
@Test
public void testCorrectFunctionStatement() throws Exception {
initializeAddInvoiceWithMetaData(true);
SimpleJdbcCall adder = new SimpleJdbcCall(dataSource).withFunctionName("add_invoice");
adder.compile();
verifyStatement(adder, "{? = call ADD_INVOICE(?, ?)}");
}
@Test
public void testCorrectFunctionStatementNamed() throws Exception {
initializeAddInvoiceWithMetaData(true);
SimpleJdbcCall adder = new SimpleJdbcCall(dataSource).withNamedBinding().withFunctionName("add_invoice");
adder.compile();
verifyStatement(adder, "{? = call ADD_INVOICE(AMOUNT => ?, CUSTID => ?)}");
}
@Test
public void testCorrectProcedureStatementNamed() throws Exception {
initializeAddInvoiceWithMetaData(false);
SimpleJdbcCall adder = new SimpleJdbcCall(dataSource).withNamedBinding().withProcedureName("add_invoice");
adder.compile();
verifyStatement(adder, "{call ADD_INVOICE(AMOUNT => ?, CUSTID => ?, NEWID => ?)}");
}
private void verifyStatement(SimpleJdbcCall adder, String expected) {
Assert.assertEquals("Incorrect call statement", expected, adder.getCallString());
}
private void initializeAddInvoiceWithoutMetaData(boolean isFunction)
throws SQLException {
given(databaseMetaData.getDatabaseProductName()).willReturn("MyDB");
@ -281,6 +312,5 @@ public class SimpleJdbcCallTests { @@ -281,6 +312,5 @@ public class SimpleJdbcCallTests {
verify(callableStatement).close();
verify(proceduresResultSet).close();
verify(procedureColumnsResultSet).close();
}
}
}

Loading…
Cancel
Save