当我尝试使用SQLXML代替XMLType作为Oracle函数的输出类型时出现SQLException

问题描述

我正在尝试重构SpringBoot应用程序,并使用XMLType代替java.sql.sqlXML,因为与XMLType相关的某些方法已被弃用,我想重写它。

我在文档中发现应该-而不是不推荐使用:

Document doc = xmltype.getDocument();

使用:

DOMSource domSource = sqlxml.getSource (DOMSource.class);
Document document = (Document) domSource.getNode();

但是我对此有疑问。当我尝试执行此操作时,出现异常。

这是我的代码片段:

            String xmlInStr;  
            XMLType xmlIn = null;  
            XMLType xmlOut = null;  
            sqlXML sqlxmlIn = null;  
            sqlXML sqlxmlOut = null;  
            OracleConnection conn = null;  
            Connection hikariConn = null;  
    (...)  
            try {  
                hikariConn = jdbcTemplate.getDataSource().getConnection();  
                sqlxmlIn = hikariConn.createsqlXML();  
                sqlxmlIn.setString(xmlInStr);  
                logger.debug("Input xml has been set.");  
                // input params  
                SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)  
      
                    .withFunctionName("getQuestionnaireByType")  
                    .withReturnValue()  
                    .withoutProcedureColumnMetaDataAccess()  
                    .declareParameters(  
                            new sqlOutParameter("RETURN",OracleTypes.sqlXML),new sqlParameter("vLang",OracleTypes.VARCHAR),new sqlParameter("vRefId",new sqlParameter("vSrcId",new sqlParameter("vUserId",new sqlParameter("vQueType",new sqlParameter("vXmlDataIn",OracleTypes.sqlXML)  
                    )  
                ;  
                jdbcCall.setAccessCallParameterMetaData(false);  
                jdbcCall.setReturnValuerequired(true);  
                jdbcCall.withSchemaName("atr_adap");  
      
                sqlParameterSource in = new MapsqlParameterSource()  
                        .addValue("vLang",rhData.getLocale().getLanguage())  
                        .addValue("vRefId",rhData.getRequestId())  
                        .addValue("vSrcId",rhData.getSrcId())  
                        .addValue("vUserId",rhData.getUserId())  
                        .addValue("vQueType",queType)  
                        .addValue("vXmlDataIn",sqlxmlIn);  
                          
                // calling db (with XMLType)  
                xmlOut = jdbcCall.executeFunction(XMLType.class,in);  
                  
                logger.debug("Stored Procedure {} executed (XMLType)",jdbcCall.getProcedureName());  
                String xmlOutStr = null;  
                xmlOutStr = xmlOut.getString();  
                logger.info("xml out (XMLType)\r\n{}",xmlOutStr);  
                doc = xmlOut.getDocument(); // everything ok (but getDocument deprecated ...)  
                  
                // calling db (with sqlXML)  
                sqlxmlOut = jdbcCall.executeFunction(java.sql.sqlXML.class,in);  
                logger.debug("Stored Procedure {} executed (sqlXML)",jdbcCall.getProcedureName());  
                xmlOutStr = sqlxmlOut.getString();  
                logger.info("xml out (sqlXML)\r\n{}",xmlOutStr); // everything ok  
                DOMSource domSource = sqlxmlOut.getSource(DOMSource.class); // the following exception is throwing from here  
                doc = (Document) domSource.getNode();   
(...) 
java.sql.sqlException: Attempt to read a sqlXML that is not readable. 
    at oracle.xdb.XMLType.getSource(XMLType.java:5159)
    at my.package.JdbcQuestionnairesRepository.findByType(JdbcQuestionnairesRepository.java:239)
    at my.package.JdbcQuestionnairesRepository$$FastClassBySpringcglib$$a9555145.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.cglibAopProxy$cglibMethodInvocation.invokeJoinpoint(cglibAopProxy.java:746)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.framework.cglibAopProxy$DynamicAdvisedInterceptor.intercept(cglibAopProxy.java:688)
    at my.package.JdbcQuestionnairesRepository$$EnhancerBySpringcglib$$a184900c.findByType(<generated>)
    at my.package.QuestionnairesService.getQuestionnaireByType(QuestionnairesService.java:48)
(...)   

我做错了什么?

最好的问候,
科利

解决方法

问题似乎出在xmlOutStr = sqlxmlOut.getString();行。删除该行,并将xmlOutStr写到日志的行,您的代码应该可以工作。

JavaDoc for the JDBC SQLXML interface还提到以下内容:

一旦free()或调用任何读取API:getBinaryStream(),getCharacterStream(),getSource()和getString(),状态就会从可读变为不可读。

我不能说为什么XMLType.getDocument()即使在调用.getString()之后也没有引发异常。