如何使用高级Oracle类型IN参数实现Spring集成int-jdbc:stored-proc-outbound-gateway

时间:2014-11-14 06:49:14

标签: oracle oracle11g spring-integration

我正在尝试实现一个int-jdbc:stored-proc-outbound-gateway,它使用高级oracle类型IN参数执行oracle存储过程。

我不清楚如何为IN参数声明高级类型。

代码和配置如下所示。

create or replace PROCEDURE POC2 
(
D_LIST IN MOVE_AUDIT,
DB_RESPONSE OUT VARCHAR2)
IS
BEGIN
.....
END POC2;

create or replace TYPE MOVE_AUDIT IS OBJECT
(
 MOVE_ID  VARCHAR2(50),
 MESSAGE  VARCHAR2(50)
);
create or replace TYPE MOVE_AUDIT_TAB IS TABLE OF MOVE_AUDIT;

stored-proc-outbound-gateway配置:

<int-jdbc:stored-proc-outbound-gateway
        id="inParamStorprocGateway" data-source="dataSource"
        request-channel="requestChannel" is-function="false"
        reply-channel="replyChannel" stored-procedure-name="POC2"
        expect-single-result="false" ignore-column-meta-data="true">
        <int-jdbc:sql-parameter-definition
            name="D_LIST" direction="IN" type="STRUCT" type-name="MOVE_AUDIT_TAB" return-type="sqlReturnStruct"/>
        <int-jdbc:sql-parameter-definition name="DB_RESPONSE" direction="OUT" type="VARCHAR"/>
        <int-jdbc:parameter name="D_LIST" expression="payload"/>
</int-jdbc:stored-proc-outbound-gateway>

<bean id="sqlReturnStructArrayConfirmPutway"    class="org.springframework.data.jdbc.support.oracle.SqlReturnStructArray">
    <constructor-arg name="mapper" ref="confirmPutawayStructMapper"/>
</bean>
<bean id="confirmPutawayStructMapper" class="com.test.mapper.ConfirmDomainStructMapper"/>

Bellow是结构Mapper:

public class ConfirmDomainStructMapper implements StructMapper<ConfirmDomain> {

  public STRUCT toStruct(ConfirmDomain oDemoDomainObject, Connection conn, String typeName)
      throws SQLException {
    StructDescriptor descriptor = new StructDescriptor(typeName, conn);
    Object[] values = new Object[2];
    values[0] = oDemoDomainObject.getId();
    values[1] = oDemoDomainObject.getName();
    return new STRUCT(descriptor, conn, values);
  }

  public ConfirmDomain fromStruct(STRUCT struct) throws SQLException {
    ConfirmDomain oDemoDomainObject=null;
    if(null!=struct){
      oDemoDomainObject=new ConfirmDomain();
      Datum[] resArray=struct.getOracleAttributes();
      oDemoDomainObject.setId(resArray[0].stringValue());
      oDemoDomainObject.setName(resArray[1].stringValue());
    }
    return oDemoDomainObject;
  }

}

我尝试并调试了这段代码,但它没有调用StructMapper的toStruct方法。

从日志中我得到的D_LIST传递为NULL

2 个答案:

答案 0 :(得分:1)

首先,由于以下原因,我根本不了解您的应用运行情况:

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);
    }
}

因此,return-type只能为OUT参数指定。

proc定义的另一个问题。我猜它应该有D_LIST IN TYPE MOVE_AUDIT_TAB,因为,我认为,你将同时存储几个对象。

所以,忘掉return-type和那个ConfirmDomainStructMapper,当你想阅读OUT参数时,它就会出现。

只有当您的<int-jdbc:parameter name="D_LIST" value="payload"/>确实是该自定义Oralce类型的对象时,此payload才会生效。

从Java角度来看,IS TABLE OF类型称为ARRAY。所以你真的应该使用一些Oracle JDBC本机代码来创建它。

我曾经这样做过,看起来像是:

<transformer expression="@oracleArrayCreator.create(payload, '${scheme.name}.MOVE_AUDIT_TAB', '${scheme.name}.MOVE_AUDIT')"/>

请注意,这些类型必须在任何包装之外。否则Oracle JDBC驱动程序无法解决它们。

@Service
@org.springframework.context.annotation.Lazy
class OracleArrayCreator {

    @Autowired
    DataSource dataSource

    @Autowired
    Properties internalProperties

    ARRAY create(List<Map> data, String tableName, String recordName) {
        def recordKeys = internalProperties.getProperty(recordName.replaceFirst(/.*\./, '')).split(',')
        def connection = nativeConnection
        def structDescriptor = StructDescriptor.createDescriptor(recordName, connection)

        def dataArray = []

        data.each { recordMap ->
            def record = []
            if (recordMap) {
                recordKeys.each {
                    record << recordMap[it]
                }
                dataArray << new STRUCT(structDescriptor, connection, record.toArray())
            }
        }

        new ARRAY(ArrayDescriptor.createDescriptor(tableName, connection), connection, dataArray.toArray())
    }


    ARRAY create(Map data, String tableName, String recordName) {
        create([data], tableName, recordName)
    }

    CLOB convertToClob(String value) {
        CLOB c = CLOB.createTemporary(nativeConnection, false, CLOB.DURATION_SESSION)
        c.setString(1L, value)
        return c
    }

    Connection getNativeConnection() {
        DataSourceUtils.getConnection(dataSource).metaData.connection
    }

}

(抱歉Groovy代码)。

并将<transformer>放在<int-jdbc:stored-proc-outbound-gateway>之前。当然,您可以将它们都包装到<chain>

是的,type="ARRAY"应该是D_LIST param。

答案 1 :(得分:0)

  

频繁阻塞线程

     

要获得连接,我正在使用

Connection conn=DataSourceUtils.getConnection(datasource);

  

并发布:   最后一个块中的DataSourceUtils.releaseConnection(conn);

一个线程。

http-/0.0.0.0:8081-73
oracle.sql.TypeDescriptor.getName(TypeDescriptor.java:682)
oracle.jdbc.oracore.OracleTypeCOLLECTION.isInHierarchyOf(OracleTypeCOLLECTION.java:149)
oracle.jdbc.driver.OraclePreparedStatement.processCompletedBindRow(OraclePreparedStatement.java:2063)
oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3579)
oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:3685)
oracle.jdbc.driver.OracleCallableStatement.execute(OracleCallableStatement.java:4714)
oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1376)
sun.reflect.GeneratedMethodAccessor96.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:606)
net.bull.javamelody.JdbcWrapper.doExecute(JdbcWrapper.java:403)
net.bull.javamelody.JdbcWrapper$StatementInvocationHandler.invoke(JdbcWrapper.java:128)
net.bull.javamelody.JdbcWrapper$DelegatingInvocationHandler.invoke(JdbcWrapper.java:285)
com.sun.proxy.$Proxy64.execute(Unknown Source)
  

另一个

http-/0.0.0.0:8081-71
oracle.sql.ARRAY.toBytes(ARRAY.java:675)
oracle.jdbc.driver.OraclePreparedStatement.setArrayCritical(OraclePreparedStatement.java:5985)
oracle.jdbc.driver.OraclePreparedStatement.setARRAYInternal(OraclePreparedStatement.java:5944)
oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:8782)
oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8278)
oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8877)
oracle.jdbc.driver.OracleCallableStatement.setObject(OracleCallableStatement.java:4992)
oracle.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:240)
sun.reflect.GeneratedMethodAccessor105.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:606)