Oracle 存储过程因复杂类型的 clob 而失败,并带有 ORA-22922

Posted

技术标签:

【中文标题】Oracle 存储过程因复杂类型的 clob 而失败,并带有 ORA-22922【英文标题】:Oracle stored procedure fails with clob in complex type with ORA-22922 【发布时间】:2021-10-25 14:21:50 【问题描述】:

我有一个包含存储过程和类型定义的包:

CREATE OR REPLACE package sample_pkg
authid definer
as

  type r_file_info_type is record
  (
    id number,
    file_data clob
  );

  procedure clob_test_complex_out
  (
    i_char_num in number,
    o_file_info out sample_pkg.r_file_info_type
  );

end;



CREATE OR REPLACE package body sample_pkg
as

  procedure clob_test_complex_out
  (
    i_char_num in number,
    o_file_info out sample_pkg.r_file_info_type
  )
  as
  begin
      o_file_info.id := i_char_num;
      o_file_info.file_data := 'ABCD';
  end;

end;

我试图从 Spring Boot 应用程序中调用它

package hu.sample.service

import org.springframework.jdbc.`object`.StoredProcedure
import org.springframework.jdbc.core.SqlOutParameter
import org.springframework.jdbc.core.SqlParameter
import org.springframework.stereotype.Repository
import java.math.BigDecimal
import java.sql.CallableStatement
import java.sql.SQLData
import java.sql.SQLInput
import java.sql.SQLOutput
import java.sql.Types
import javax.sql.DataSource
  
data class FileWithData(
    var id: BigDecimal? = null,
    var fileData: ByteArray? = null,
)

class FileWithDataWrapper() : SQLData 

    val file: FileWithData = FileWithData()

    override fun getSQLTypeName(): String = "SAMPLE_PKG.R_FILE_INFO_TYPE"

    override fun readSQL(input: SQLInput?, p1: String?) 
        file.id = input?.readBigDecimal()
        val clob = input?.readClob()
        clob?.getSubString(1, clob.length().toInt())
    

    override fun writeSQL(output: SQLOutput) 
        output.writeBigDecimal(file.id)
        output.writeClob(null)
    



@Repository
class ReproduceClobProblem(ds:  DataSource) : StoredProcedure(ds, "SAMPLE_PKG.CLOB_TEST_COMPLEX_OUTt") 

    init 
        sql = """ 
                 |call SAMPLE_PKG.CLOB_TEST_COMPLEX_OUT(
                 |I_CHAR_NUM => :I_CHAR_NUM, 
                 |O_FILE_INFO => :O_FILE_INFO
                 |) 
                 |""".trimMargin()
        isSqlReadyForUse = true

        declareParameter(SqlParameter("I_CHAR_NUM", Types.NUMERIC))
        declareParameter(SqlOutParameter("O_FILE_INFO", Types.STRUCT, "SAMPLE_PKG.R_FILE_INFO_TYPE")  statement: CallableStatement, paramIndex: Int, sqlType: Int, typeName: String? ->
            statement
                .connection
                .typeMap["SAMPLE_PKG.R_FILE_INFO_TYPE"] = FileWithDataWrapper::class.java
            statement.getObject(paramIndex)
        )
    

    fun clobTest(charNum: BigDecimal): String 

        val result = execute  connection ->
            mapOf(
                "I_CHAR_NUM" to charNum
            )
        
        return String((result["O_DATA"] as FileWithDataWrapper).file.fileData ?: ByteArray(0))
    


但它失败并出现 ORA-22922 不存在的 LOB 值错误:

org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [ 
call SAMPLE_PKG.CLOB_TEST_COMPLEX_OUT(
I_CHAR_NUM => :I_CHAR_NUM, 
O_FILE_INFO => :O_FILE_INFO
) 
]; SQL state [99999]; error code [22922]; ORA-22922: nem létező LOB érték
; nested exception is java.sql.SQLException: ORA-22922: nem létező LOB érték

    at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1542) ~[spring-jdbc-5.3.9.jar:5.3.9]
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1206) ~[spring-jdbc-5.3.9.jar:5.3.9]
    at org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1245) ~[spring-jdbc-5.3.9.jar:5.3.9]
    at org.springframework.jdbc.object.StoredProcedure.execute(StoredProcedure.java:159) ~[spring-jdbc-5.3.9.jar:5.3.9]
    at hu.sample.service.ReproduceClobProblem.clobTest(ReproduceClobProblem.kt:66) ~[main/:na]
    at hu.sample.service.ReproduceClobProblem$$FastClassBySpringCGLIB$$d22f2772.invoke(<generated>) ~[main/:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.9.jar:5.3.9]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) ~[spring-aop-5.3.9.jar:5.3.9]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.9.jar:5.3.9]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.9.jar:5.3.9]
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-5.3.9.jar:5.3.9]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.9.jar:5.3.9]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.9.jar:5.3.9]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) ~[spring-aop-5.3.9.jar:5.3.9]
    at hu.sample.service.ReproduceClobProblem$$EnhancerBySpringCGLIB$$a09500e1.clobTest(<generated>) ~[main/:na]
    at hu.sample.controller.SampleController.reproduceProblem(SampleController.java:236) ~[main/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.9.jar:5.3.9]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.9.jar:5.3.9]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.9.jar:5.3.9]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.9.jar:5.3.9]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.9.jar:5.3.9]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.9.jar:5.3.9]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1064) ~[spring-webmvc-5.3.9.jar:5.3.9]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.9.jar:5.3.9]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.9.jar:5.3.9]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.9.jar:5.3.9]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:497) ~[jakarta.servlet-api-4.0.4.jar:4.0.4]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.9.jar:5.3.9]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:584) ~[jakarta.servlet-api-4.0.4.jar:4.0.4]
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at org.zalando.logbook.servlet.LogbookFilter.doFilter(LogbookFilter.java:71) ~[logbook-servlet-2.4.2.jar:na]
    at org.zalando.logbook.servlet.HttpFilter.doFilter(HttpFilter.java:31) ~[logbook-servlet-2.4.2.jar:na]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:121) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:105) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:218) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) ~[spring-web-5.3.9.jar:5.3.9]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.9.jar:5.3.9]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.9.jar:5.3.9]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.9.jar:5.3.9]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183) ~[spring-security-web-5.5.1.jar:5.5.1]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) ~[spring-web-5.3.9.jar:5.3.9]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) ~[spring-web-5.3.9.jar:5.3.9]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.9.jar:5.3.9]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.9.jar:5.3.9]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.9.jar:5.3.9]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.9.jar:5.3.9]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at org.zalando.logbook.servlet.LogbookFilter.doFilter(LogbookFilter.java:71) ~[logbook-servlet-2.4.2.jar:na]
    at org.zalando.logbook.servlet.SecureLogbookFilter.doFilter(SecureLogbookFilter.java:32) ~[logbook-servlet-2.4.2.jar:na]
    at org.zalando.logbook.servlet.HttpFilter.doFilter(HttpFilter.java:31) ~[logbook-servlet-2.4.2.jar:na]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96) ~[spring-boot-actuator-2.5.3.jar:2.5.3]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.9.jar:5.3.9]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.9.jar:5.3.9]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.9.jar:5.3.9]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:117) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) ~[undertow-core-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) ~[undertow-core-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) ~[undertow-core-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.SendErrorPageHandler.handleRequest(SendErrorPageHandler.java:52) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:280) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:79) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:134) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:131) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:260) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:79) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:100) ~[undertow-servlet-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:387) ~[undertow-core-2.2.9.Final.jar:2.2.9.Final]
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:852) ~[undertow-core-2.2.9.Final.jar:2.2.9.Final]
    at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]
    at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1558) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1423) ~[jboss-threads-3.1.0.Final.jar:3.1.0.Final]
    at org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1280) ~[xnio-api-3.8.4.Final.jar:3.8.4.Final]
    at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]
Caused by: java.sql.SQLException: ORA-22922: nem létező LOB érték 

    at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:628) ~[ojdbc8-21.1.0.0.jar:21.1.0.0.0]
    at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:557) ~[ojdbc8-21.1.0.0.jar:21.1.0.0.0]
    at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:552) ~[ojdbc8-21.1.0.0.jar:21.1.0.0.0]
    at oracle.jdbc.driver.T4C8TTILob.processError(T4C8TTILob.java:914) ~[ojdbc8-21.1.0.0.jar:21.1.0.0.0]
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:726) ~[ojdbc8-21.1.0.0.jar:21.1.0.0.0]
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:291) ~[ojdbc8-21.1.0.0.jar:21.1.0.0.0]
    at oracle.jdbc.driver.T4C8TTILob.getLength(T4C8TTILob.java:234) ~[ojdbc8-21.1.0.0.jar:21.1.0.0.0]
    at oracle.jdbc.driver.T4CConnection.length(T4CConnection.java:5330) ~[ojdbc8-21.1.0.0.jar:21.1.0.0.0]
    at oracle.jdbc.driver.OracleClob.lengthInternal(OracleClob.java:302) ~[ojdbc8-21.1.0.0.jar:21.1.0.0.0]
    at oracle.jdbc.driver.OracleClob.length(OracleClob.java:270) ~[ojdbc8-21.1.0.0.jar:21.1.0.0.0]
    at oracle.sql.CLOB.length(CLOB.java:345) ~[ojdbc8-21.1.0.0.jar:21.1.0.0.0]
    at hu.sample.service.FileWithDataWrapper.readSQL(ReproduceClobProblem.kt:33) ~[main/:na]
    at oracle.sql.STRUCT.toClass(STRUCT.java:630) ~[ojdbc8-21.1.0.0.jar:21.1.0.0.0]
    at oracle.sql.STRUCT.toJdbc(STRUCT.java:581) ~[ojdbc8-21.1.0.0.jar:21.1.0.0.0]
    at oracle.jdbc.driver.NamedTypeAccessor.getObject(NamedTypeAccessor.java:197) ~[ojdbc8-21.1.0.0.jar:21.1.0.0.0]
    at oracle.jdbc.driver.NamedTypeAccessor.getObject(NamedTypeAccessor.java:135) ~[ojdbc8-21.1.0.0.jar:21.1.0.0.0]
    at oracle.jdbc.driver.OracleCallableStatement.getObject(OracleCallableStatement.java:1783) ~[ojdbc8-21.1.0.0.jar:21.1.0.0.0]
    at oracle.jdbc.driver.OracleCallableStatementWrapper.getObject(OracleCallableStatementWrapper.java:679) ~[ojdbc8-21.1.0.0.jar:21.1.0.0.0]
    at com.zaxxer.hikari.pool.HikariProxyCallableStatement.getObject(HikariProxyCallableStatement.java) ~[HikariCP-4.0.3.jar:na]
    at hu.sample.service.ReproduceClobProblem._init_$lambda-0(ReproduceClobProblem.kt:60) ~[main/:na]
    at org.springframework.jdbc.core.JdbcTemplate.extractOutputParameters(JdbcTemplate.java:1345) ~[spring-jdbc-5.3.9.jar:5.3.9]
    at org.springframework.jdbc.core.JdbcTemplate.lambda$call$6(JdbcTemplate.java:1256) ~[spring-jdbc-5.3.9.jar:5.3.9]
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1190) ~[spring-jdbc-5.3.9.jar:5.3.9]
    ... 132 common frames omitted

如何在 Spring Boot 中从 Struct 中获取 Oracle Clob 值?

我已经用 Oracle 19c 试过了。

【问题讨论】:

你能显示packagetype的定义吗?你发了两次package body.... 我已经添加了缺少的包头(包和类型定义) 【参考方案1】:

我可以用普通的JDBC 重现相同的异常

18c Express Edition Release 18.0.0.0.0  and
DriverVersion 12.1.0.2.0

这里是最小的例子

def type_name = "TEST_CLOB_RECORD.R_CLOB_TYPE"
CallableStatement stmt = null

stmt = con.prepareCall(" call TEST_CLOB_RECORD.GET_CLOB_RECORD(?) ") 
stmt.registerOutParameter(1, Types.STRUCT, type_name)
stmt.execute()
Struct outStruct = stmt.getObject(1) 
println outStruct.class.name
println outStruct.dump()

到这里 OK - getObject 返回 oracle.sql.STRUCT 类,dump()

name = TEST_CLOB_RECORD.R_CLOB_TYPE
length = 1
TXT = oracle.sql.CLOB@6df20ade

getAttributes() 返回CLOB 的副本,但对内容的任何访问都会导致ORA-22922

clob = outStruct.getAttributes()[0]
println clob.dump()
println clob.getSubString(1, (int) clob.length())

给予

<oracle.sql.CLOB@4287d447 dbaccess=oracle.jdbc.driver.T4CConnection@22b53226 dbChunkSize=-1 csform=1 isFree=false fromObject=true cachedLengthOfClobInChars=-1 prefetchData=null prefetchDataSize=0 activePrefetch=false dilCharacterSet=null acProxy=null physicalConnection=oracle.jdbc.driver.T4CConnection@22b53226 data=[0, 38, 0, 0, 66, 8, -128, 0, 0, 2, 4, -101, 0, 0, 1, 10, 0, 0, 0, 1, 3, 105, 0, 12, 0, 0, 0, 0, 0, 2, -100, -78, -69, -106, 0, 0, 0, 0, 0, 0]>
Caught: java.sql.SQLException: ORA-22922: Nonexistent LOB Value

所以在这里我建议联系 Oracle 支持并询问解释...(请参阅下面的简化 PL/SQL 代码)

确实有效虽然非常基本的解决方法是在 PL/SQL 块中获取 record 并将 CLOB 作为(附加)返回值传递 -这里的相关人员剪断了

stmt = con.prepareCall("""declare
  v_clob_type  test_clob_record.r_clob_type;
begin
  test_clob_record.get_clob_record(o_clob_type => v_clob_type);
  ? := v_clob_type.txt;
end;""") 
stmt.registerOutParameter(1, OracleTypes.CLOB)
stmt.execute()
def clob = stmt.getClob(1) 

PL/SQL 代码

CREATE OR REPLACE package test_clob_record
as
  type r_clob_type is record
  (
    txt clob
  );

  procedure get_clob_record
  (
    o_clob_type out test_clob_record.r_clob_type
  );
end;
/

CREATE OR REPLACE package body test_clob_record
as
  procedure get_clob_record
  (
    o_clob_type out test_clob_record.r_clob_type
  )
  as
  begin
      o_clob_type.txt := cast ('ABCD' as CLOB);
  end;  
end;
/

【讨论】:

我之前尝试过这种解决方案,但这并不是我真正想要的。我编写了一个生成此代码的工具,因此结构可以位于数组或其他复杂结构中,因此我不能使用这种解决方法。我的同事找到了其他解决方案,如果数据来自表 clob 字段,它似乎正在工作。

以上是关于Oracle 存储过程因复杂类型的 clob 而失败,并带有 ORA-22922的主要内容,如果未能解决你的问题,请参考以下文章

oracle存储过程clob类型参数为null问题

oracle如何导出具有clob字段类型的sql?

oracle中LOBSEGMENT类型存储的clob的内容过大,如何清除clob字段内容。释放表空间!

Oracle中的BLOB和CLOB字段类型的区别

php操作达梦数据库示例代码(包括绑定变量,存储过程调用,clob类型操作等)

Java 存储和读取 oracle CLOB 类型字段的实用方法