From 7d96dc7969d01fe01b8944c93dc41c605b429f07 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Sun, 12 May 2013 21:00:39 +0300 Subject: [PATCH] INT-2865: Stored Procedure SqlReturnType support JIRA: https://jira.springsource.org/browse/INT-2865 --- .../jdbc/config/StoredProcParserUtils.java | 41 ++++-- .../config/spring-integration-jdbc-3.0.xsd | 32 ++++- ...atewayWithSpelIntegrationTests-context.xml | 23 ++++ ...tboundGatewayWithSpelIntegrationTests.java | 45 +++++++ .../config/StoredProcInvalidConfigsTests.java | 119 ++++++++++++++++++ .../stored-proc-invalid-configs.properties | 26 ++++ .../jdbc/storedproc/ClobSqlReturnType.java | 36 ++++++ .../derby/DerbyStoredProcedures.java | 16 ++- .../src/test/resources/.svnignore | 0 .../derby-stored-procedures-drops.sql | 2 + .../resources/derby-stored-procedures.sql | 4 +- .../drop-derby-stored-procedures.sql | 4 - src/reference/docbook/jdbc.xml | 28 ++++- src/reference/docbook/whats-new.xml | 17 ++- 14 files changed, 364 insertions(+), 29 deletions(-) create mode 100644 spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcInvalidConfigsTests.java create mode 100644 spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/stored-proc-invalid-configs.properties create mode 100644 spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/ClobSqlReturnType.java delete mode 100644 spring-integration-jdbc/src/test/resources/.svnignore delete mode 100644 spring-integration-jdbc/src/test/resources/drop-derby-stored-procedures.sql diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcParserUtils.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcParserUtils.java index 5f6d713b8d..3591326382 100644 --- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcParserUtils.java +++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcParserUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +42,7 @@ import org.w3c.dom.Element; /** * @author Gunnar Hillert + * @author Artem Bilan * @since 2.1 */ public final class StoredProcParserUtils { @@ -68,6 +69,18 @@ public final class StoredProcParserUtils { String sqlType = childElement.getAttribute("type"); String direction = childElement.getAttribute("direction"); String scale = childElement.getAttribute("scale"); + String typeName = childElement.getAttribute("type-name"); + String returnType = childElement.getAttribute("return-type"); + + if (StringUtils.hasText(typeName) && StringUtils.hasText(scale)) { + parserContext.getReaderContext().error("'type-name' and 'scale' attributes are mutually exclusive " + + "for 'sql-parameter-definition' element.", storedProcComponent); + } + + if (StringUtils.hasText(returnType) && StringUtils.hasText(scale)) { + parserContext.getReaderContext().error("'returnType' and 'scale' attributes are mutually exclusive " + + "for 'sql-parameter-definition' element.", storedProcComponent); + } final BeanDefinitionBuilder parameterBuilder; @@ -79,6 +92,10 @@ public final class StoredProcParserUtils { } else { parameterBuilder = BeanDefinitionBuilder.genericBeanDefinition(SqlParameter.class); + if (StringUtils.hasText(returnType)) { + parserContext.getReaderContext().error("'return-type' attribute can't be provided " + + "for IN 'sql-parameter-definition' element.", storedProcComponent); + } } if (StringUtils.hasText(name)) { @@ -105,9 +122,19 @@ public final class StoredProcParserUtils { parameterBuilder.addConstructorArgValue(Types.VARCHAR); } - if (StringUtils.hasText(scale)) { + if (StringUtils.hasText(typeName)) { + parameterBuilder.addConstructorArgValue(typeName); + } + else if (StringUtils.hasText(scale)) { parameterBuilder.addConstructorArgValue(new TypedStringValue(scale, Integer.class)); } + else { + parameterBuilder.addConstructorArgValue(null); + } + + if (StringUtils.hasText(returnType)) { + parameterBuilder.addConstructorArgReference(returnType); + } sqlParameterList.add(parameterBuilder.getBeanDefinition()); } @@ -188,16 +215,6 @@ public final class StoredProcParserUtils { String name = childElement.getAttribute("name"); String rowMapperAsString = childElement.getAttribute("row-mapper"); - if (!StringUtils.hasText(name)) { - parserContext.getReaderContext().error( - "The 'name' attribute must be set for the 'returning-resultset' element.", storedProcComponent); - } - - if (!StringUtils.hasText(rowMapperAsString)) { - parserContext.getReaderContext().error( - "The 'row-mapper' attribute must be set for the 'returning-resultset' element.", storedProcComponent); - } - BeanDefinitionBuilder rowMapperBuilder = BeanDefinitionBuilder.genericBeanDefinition(rowMapperAsString); returningResultsetMap.put(name, rowMapperBuilder.getBeanDefinition()); diff --git a/spring-integration-jdbc/src/main/resources/org/springframework/integration/jdbc/config/spring-integration-jdbc-3.0.xsd b/spring-integration-jdbc/src/main/resources/org/springframework/integration/jdbc/config/spring-integration-jdbc-3.0.xsd index 8bb7f26567..1282510588 100644 --- a/spring-integration-jdbc/src/main/resources/org/springframework/integration/jdbc/config/spring-integration-jdbc-3.0.xsd +++ b/spring-integration-jdbc/src/main/resources/org/springframework/integration/jdbc/config/spring-integration-jdbc-3.0.xsd @@ -1296,12 +1296,32 @@ - - - + + + + + + + + + + + + + + + Reference to a custom value handler for complex type. + + + + + diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithSpelIntegrationTests-context.xml b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithSpelIntegrationTests-context.xml index f4ca71213f..174d3325d3 100644 --- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithSpelIntegrationTests-context.xml +++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithSpelIntegrationTests-context.xml @@ -38,8 +38,31 @@ + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithSpelIntegrationTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithSpelIntegrationTests.java index 2cd84c7021..161822281b 100644 --- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithSpelIntegrationTests.java +++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/StoredProcOutboundGatewayWithSpelIntegrationTests.java @@ -16,9 +16,11 @@ package org.springframework.integration.jdbc; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import java.sql.CallableStatement; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -31,6 +33,7 @@ import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.support.AbstractApplicationContext; @@ -38,14 +41,23 @@ import org.springframework.integration.Message; import org.springframework.integration.MessageHandlingException; import org.springframework.integration.annotation.ServiceActivator; import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.core.PollableChannel; +import org.springframework.integration.jdbc.config.JdbcTypesEnum; import org.springframework.integration.jdbc.storedproc.User; +import org.springframework.integration.json.JsonInboundMessageMapper; +import org.springframework.integration.json.JsonOutboundMessageMapper; +import org.springframework.integration.message.GenericMessage; import org.springframework.integration.support.MessageBuilder; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.SqlReturnType; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; /** * @author Gunnar Hillert + * @author Artem Bilan */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) @@ -61,6 +73,18 @@ public class StoredProcOutboundGatewayWithSpelIntegrationTests { @Qualifier("startChannel") DirectChannel channel; + @Autowired + DirectChannel getMessageChannel; + + @Autowired + PollableChannel output2Channel; + + @Autowired + JdbcTemplate jdbcTemplate; + + @Autowired + SqlReturnType clobSqlReturnType; + @Test @DirtiesContext public void executeStoredProcedureWithMessageHeader() throws Exception { @@ -121,6 +145,27 @@ public class StoredProcOutboundGatewayWithSpelIntegrationTests { } + @Test + @Transactional + public void testInt2865SqlReturnType() throws Exception { + Message testMessage = MessageBuilder.withPayload("TEST").setHeader("FOO", "BAR").build(); + String messageId = testMessage.getHeaders().getId().toString(); + String jsonMessage = new JsonOutboundMessageMapper().fromMessage(testMessage); + + this.jdbcTemplate.update("INSERT INTO json_message VALUES (?,?)", messageId, jsonMessage); + + this.getMessageChannel.send(new GenericMessage(messageId)); + Message resultMessage = this.output2Channel.receive(1000); + assertNotNull(resultMessage); + Object resultPayload = resultMessage.getPayload(); + assertTrue(resultPayload instanceof String); + Message message = new JsonInboundMessageMapper(String.class).toMessage((String) resultPayload); + assertEquals(testMessage.getPayload(), message.getPayload()); + assertEquals(testMessage.getHeaders().get("FOO"), message.getHeaders().get("FOO")); + Mockito.verify(clobSqlReturnType).getTypeValue(Mockito.any(CallableStatement.class), + Mockito.eq(2), Mockito.eq(JdbcTypesEnum.CLOB.getCode()), Mockito.eq((String) null)); + } + static class Counter { private final AtomicInteger count = new AtomicInteger(); diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcInvalidConfigsTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcInvalidConfigsTests.java new file mode 100644 index 0000000000..eaa958f93d --- /dev/null +++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcInvalidConfigsTests.java @@ -0,0 +1,119 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package org.springframework.integration.jdbc.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.ByteArrayInputStream; +import java.sql.Types; +import java.util.List; +import java.util.Properties; + +import org.junit.After; +import org.junit.Test; +import org.springframework.beans.DirectFieldAccessor; +import org.springframework.beans.factory.config.PropertiesFactoryBean; +import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.InputStreamResource; +import org.springframework.expression.Expression; +import org.springframework.integration.Message; +import org.springframework.integration.core.MessageHandler; +import org.springframework.integration.endpoint.EventDrivenConsumer; +import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice; +import org.springframework.integration.jdbc.storedproc.ProcedureParameter; +import org.springframework.integration.message.GenericMessage; +import org.springframework.integration.test.util.TestUtils; +import org.springframework.jdbc.core.SqlInOutParameter; +import org.springframework.jdbc.core.SqlOutParameter; +import org.springframework.jdbc.core.SqlParameter; + +/** + * @author Artem Bilan + * @since 3.0 + */ +public class StoredProcInvalidConfigsTests { + + @Test + public void testProcedureNameAndExpressionExclusivity() throws Exception { + try { + this.bootStrap("nameAndExpressionExclusivity"); + fail("Expected a BeanDefinitionParsingException to be thrown."); + } + catch (BeanDefinitionParsingException e) { + assertTrue(e.getMessage().contains("Exactly one of 'stored-procedure-name' or 'stored-procedure-name-expression' is required")); + } + } + + @Test + public void testReturnTypeForInParameter() throws Exception { + try { + this.bootStrap("returnTypeForInParameter"); + fail("Expected a BeanDefinitionParsingException to be thrown."); + } + catch (BeanDefinitionParsingException e) { + assertTrue(e.getMessage().contains("'return-type' attribute can't be provided for IN 'sql-parameter-definition' element.")); + } + } + + @Test + public void testTypeNameAndScaleExclusivity() throws Exception { + try { + this.bootStrap("typeNameAndScaleExclusivity"); + fail("Expected a BeanDefinitionParsingException to be thrown."); + } + catch (BeanDefinitionParsingException e) { + assertTrue(e.getMessage().contains("'type-name' and 'scale' attributes are mutually exclusive " + + "for 'sql-parameter-definition' element.")); + } + } + + @Test + public void testReturnTypeAndScaleExclusivity() throws Exception { + try { + this.bootStrap("returnTypeAndScaleExclusivity"); + fail("Expected a BeanDefinitionParsingException to be thrown."); + } + catch (BeanDefinitionParsingException e) { + assertTrue(e.getMessage().contains("'returnType' and 'scale' attributes are mutually exclusive " + + "for 'sql-parameter-definition' element.")); + } + } + + private ApplicationContext bootStrap(String configProperty) throws Exception { + PropertiesFactoryBean pfb = new PropertiesFactoryBean(); + pfb.setLocation(new ClassPathResource("org/springframework/integration/jdbc/config/stored-proc-invalid-configs.properties")); + pfb.afterPropertiesSet(); + Properties prop = pfb.getObject(); + StringBuilder buffer = new StringBuilder(); + buffer.append(prop.getProperty("xmlheaders")).append(prop.getProperty(configProperty)).append(prop.getProperty("xmlfooter")); + ByteArrayInputStream stream = new ByteArrayInputStream(buffer.toString().getBytes()); + GenericApplicationContext ac = new GenericApplicationContext(); + XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(ac); + reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD); + reader.loadBeanDefinitions(new InputStreamResource(stream)); + ac.refresh(); + return ac; + } + +} diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/stored-proc-invalid-configs.properties b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/stored-proc-invalid-configs.properties new file mode 100644 index 0000000000..c2695d9bd3 --- /dev/null +++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/stored-proc-invalid-configs.properties @@ -0,0 +1,26 @@ +xmlheaders=\ + \ + +xmlfooter= + +nameAndExpressionExclusivity= + +returnTypeForInParameter=\ + \ + + +typeNameAndScaleExclusivity=\ + \ + + +returnTypeAndScaleExclusivity=\ + \ + diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/ClobSqlReturnType.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/ClobSqlReturnType.java new file mode 100644 index 0000000000..43046b4ddd --- /dev/null +++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/ClobSqlReturnType.java @@ -0,0 +1,36 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.jdbc.storedproc; + +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.SQLException; + +import org.springframework.jdbc.core.SqlReturnType; + +/** + * @author Artem Bilan + * @since 3.0 + */ +public class ClobSqlReturnType implements SqlReturnType { + + @Override + public Object getTypeValue(CallableStatement cs, int paramIndex, int sqlType, String typeName) throws SQLException { + Clob clob = cs.getClob(paramIndex); + return clob != null ? clob.getSubString(1, (int) clob.length()) : null; + } +} diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/derby/DerbyStoredProcedures.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/derby/DerbyStoredProcedures.java index ff293b1058..3774021ab4 100644 --- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/derby/DerbyStoredProcedures.java +++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/storedproc/derby/DerbyStoredProcedures.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ package org.springframework.integration.jdbc.storedproc.derby; +import java.sql.Clob; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; @@ -26,6 +27,7 @@ import org.springframework.jdbc.support.JdbcUtils; /** * * @author Gunnar Hillert + * @author Artem Bilan * */ public final class DerbyStoredProcedures { @@ -74,4 +76,16 @@ public final class DerbyStoredProcedures { } + public static void getMessage(String messageId, Clob[] returnedData) throws SQLException { + + Connection conn = DriverManager.getConnection("jdbc:default:connection"); + + PreparedStatement stmt = conn.prepareStatement("select MESSAGE_JSON from JSON_MESSAGE where MESSAGE_ID = ?"); + stmt.setString( 1, messageId); + ResultSet results = stmt.executeQuery(); + if (results.next()) { + returnedData[0] = results.getClob(1); + } + } + } diff --git a/spring-integration-jdbc/src/test/resources/.svnignore b/spring-integration-jdbc/src/test/resources/.svnignore deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/spring-integration-jdbc/src/test/resources/derby-stored-procedures-drops.sql b/spring-integration-jdbc/src/test/resources/derby-stored-procedures-drops.sql index a6f98b4504..1fd2685100 100644 --- a/spring-integration-jdbc/src/test/resources/derby-stored-procedures-drops.sql +++ b/spring-integration-jdbc/src/test/resources/derby-stored-procedures-drops.sql @@ -2,3 +2,5 @@ DROP FUNCTION CONVERT_STRING_TO_UPPER_CASE; DROP TABLE USERS; DROP PROCEDURE CREATE_USER; DROP PROCEDURE CREATE_USER_RETURN_ALL; +DROP TABLE JSON_MESSAGE; +DROP PROCEDURE GET_MESSAGE; diff --git a/spring-integration-jdbc/src/test/resources/derby-stored-procedures.sql b/spring-integration-jdbc/src/test/resources/derby-stored-procedures.sql index 9d7ee63f2a..9936023ada 100644 --- a/spring-integration-jdbc/src/test/resources/derby-stored-procedures.sql +++ b/spring-integration-jdbc/src/test/resources/derby-stored-procedures.sql @@ -1,4 +1,6 @@ CREATE FUNCTION CONVERT_STRING_TO_UPPER_CASE (invalue VARCHAR(50)) RETURNS VARCHAR(50) PARAMETER STYLE JAVA LANGUAGE JAVA EXTERNAL NAME 'org.springframework.integration.jdbc.storedproc.derby.DerbyFunctions.convertStringToUpperCase'; create table USERS(USERNAME varchar(100),PASSWORD varchar(100), EMAIL varchar(100)); CREATE PROCEDURE CREATE_USER( IN username VARCHAR(100), IN password VARCHAR(100), IN email VARCHAR(100) ) PARAMETER STYLE JAVA LANGUAGE JAVA EXTERNAL NAME 'org.springframework.integration.jdbc.storedproc.derby.DerbyStoredProcedures.createUser'; -CREATE PROCEDURE CREATE_USER_RETURN_ALL(IN username VARCHAR(100), IN password VARCHAR(100), IN email VARCHAR(100)) PARAMETER STYLE JAVA LANGUAGE JAVA MODIFIES SQL DATA DYNAMIC RESULT SETS 1 EXTERNAL NAME 'org.springframework.integration.jdbc.storedproc.derby.DerbyStoredProcedures.createUserAndReturnAll'; \ No newline at end of file +CREATE PROCEDURE CREATE_USER_RETURN_ALL(IN username VARCHAR(100), IN password VARCHAR(100), IN email VARCHAR(100)) PARAMETER STYLE JAVA LANGUAGE JAVA MODIFIES SQL DATA DYNAMIC RESULT SETS 1 EXTERNAL NAME 'org.springframework.integration.jdbc.storedproc.derby.DerbyStoredProcedures.createUserAndReturnAll'; +create table JSON_MESSAGE(MESSAGE_ID CHAR(36), MESSAGE_JSON CLOB); +CREATE PROCEDURE GET_MESSAGE(IN MESSAGE_ID CHAR(36), OUT MESSAGE_JSON CLOB) PARAMETER STYLE JAVA LANGUAGE JAVA EXTERNAL NAME 'org.springframework.integration.jdbc.storedproc.derby.DerbyStoredProcedures.getMessage'; diff --git a/spring-integration-jdbc/src/test/resources/drop-derby-stored-procedures.sql b/spring-integration-jdbc/src/test/resources/drop-derby-stored-procedures.sql deleted file mode 100644 index a6a4c5db96..0000000000 --- a/spring-integration-jdbc/src/test/resources/drop-derby-stored-procedures.sql +++ /dev/null @@ -1,4 +0,0 @@ -DROP FUNCTION CONVERT_STRING_TO_UPPER_CASE; -DROP TABLE USERS; -DROP PROCEDURE CREATE_USER; -DROP PROCEDURE CREATE_USER_RETURN_ALL; \ No newline at end of file diff --git a/src/reference/docbook/jdbc.xml b/src/reference/docbook/jdbc.xml index 8ff1cb9361..e01bed77ec 100644 --- a/src/reference/docbook/jdbc.xml +++ b/src/reference/docbook/jdbc.xml @@ -810,10 +810,13 @@ attribute. - ]]> + ]]> @@ -850,6 +853,23 @@ Optional. + + + The typeName for types that are user-named like: STRUCT, DISTINCT, JAVA_OBJECT, named array types. + This attribute is mutually exclusive with the scale attribute. + Optional. + + + + + The reference to a custom value handler for complex types. An implementation of + SqlReturnType. + This attribute is mutually exclusive with the scale attribute + and is applicable for OUT(INOUT)-parameters only. + Optional. + + diff --git a/src/reference/docbook/whats-new.xml b/src/reference/docbook/whats-new.xml index b6c8d80064..478e0ef08f 100644 --- a/src/reference/docbook/whats-new.xml +++ b/src/reference/docbook/whats-new.xml @@ -191,6 +191,21 @@ For more information see . - +
+ SqlReturnType support for Stored Procedure components + + For more complex database-specific types, not supported by the standard + CallableStatement.getObject method, 2 new additional + attributes were introduced to the <sql-parameter-definition/> + element with OUT-direction: + + + type-name + return-type + + + For more information see . + +