如何在jdbc中实现Spring集成:带有高级Oracle-type-IN参数的存储过程出站网关

如何在jdbc中实现Spring集成:带有高级Oracle-type-IN参数的存储过程出站网关,oracle,oracle11g,spring-integration,Oracle,Oracle11g,Spring Integration,我试图实现一个intjdbc:storageproc出站网关,它使用高级oracle type-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 (

我试图实现一个intjdbc:storageproc出站网关,它使用高级oracle type-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;
存储过程出站网关配置:

<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"/>

下面是结构映射器:

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

}
公共类ConfirmDomainStructMapper实现StructMapper{
公共结构toStruct(确认域oDemoDomainObject、连接连接、字符串类型名)
抛出SQLException{
StructDescriptor描述符=新的StructDescriptor(类型名,conn);
对象[]值=新对象[2];
值[0]=oDemoDomainObject.getId();
值[1]=oDemoDomainObject.getName();
返回新结构(描述符、连接、值);
}
public ConfirmDomain fromStruct(STRUCT STRUCT)引发SQLException{
ConfirmDomain oDemoDomainObject=null;
if(null!=struct){
oDemoDomainObject=new ConfirmDomain();
Datum[]resArray=struct.getOracleAttribute();
setId(resArray[0].stringValue());
setName(resArray[1].stringValue());
}
返回oDemoDomainObject;
}
}
我尝试并调试了这段代码,但它没有调用StructMapper的toStruct方法


从日志中,我得到的D_列表为空

首先,我根本不了解你的应用程序是如何运行的,因为:

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);
    }
}
因此,
返回类型
只能为
OUT
参数指定

proc定义的另一个问题。我猜它应该在类型MOVE\u AUDIT\u TAB中有
D\u列表,因为我认为,您将同时存储多个对象

因此,忘记
返回类型
ConfirmDomainStructMapper
,因为当您想读取
参数时,它会起作用

只有当您的
有效负载
确实是该自定义Oralce类型的对象时,此
才会生效

从Java的角度来看,
是名为
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
    }

}
@服务
@org.springframework.context.annotation.Lazy
类创建器{
@自动连线
数据源数据源
@自动连线
属性内部属性
数组创建(列表数据、字符串表名、字符串记录名){
def recordKeys=internalProperties.getProperty(recordName.replaceFirst(/.*\./,'').split(','))
def连接=本地连接
def structDescriptor=structDescriptor.createDescriptor(记录名,连接)
def dataArray=[]
data.each{recordMap->
def记录=[]
if(记录地图){
记录键。每个{
记录
获取频繁的线程阻塞

为了获得连接,我正在使用

Connection conn=DataSourceUtils.getConnection(datasource);

并发布:
DataSourceUtils.releaseConnection(conn);
在finally块中

一块螺纹

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)
另一个


@Artem Bilan你能帮忙吗嗨!我知道问题了。我今天会尝试回答。顺便说一句,我知道你也不知道如何正确提及SO用户:-)@ArtemBilan现在我知道了如何提及SO用户…谢谢:)是的,同意。现在我收到了你的消息。谢谢。现在我也知道怎么做:-)谢谢@ArtemBilan。它工作得很好。。发布最新的配置和转换器java代码。太好了!让我们接受我的回答,以确保我在帮助您方面做得很好;-)您好@ArtemBilan请查看下面的帖子。我们经常遇到死锁。@Artem Billan任何建议。您应该与您的DBA谈谈,以调查在这种情况下Oracle方面发生了什么。好的哎呀,我帮不上忙司机代码。从另一个角度看,这似乎是一个新的SO问题。
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)