mybatis連接Oracle執行begin..end批量操作返回行數問題


如下是mapper文件里的sql代碼

<update id="updateByTransBatchIdAndBankId"  parameterType="java.util.List">
    <foreach collection="list" item="item" index="index" open="begin" close=";end;" separator=";">
        update T_PLAT_ORDER  set STATE = 1
        where ORDER_ID = #{item.orderId,jdbcType=VARCHAR} and state in (0,11)
    </foreach>
</update>

如下是Dao接口方法

package com.cn.yft.ora.dao;

public interface TPlatOrderDAO {
    /**
     * 根據訂單流水號更新交易狀態為0或4的訂單狀態為1
     * @param list
     * @return
     */
    int updateByTransBatchIdAndBankId(List<TBankOrder> list);
}

程序運行時,發現有坑。不管實際更新幾條,包括0條,mybatis並不打印執行行數。通過程序打印出來,發現結果始終是一個固定的值。而且,生產與本地還不一樣。生產打印出來都是-1, 本地環境打印出來都是1,在Navicat里連接本地Oracle數據庫里執行結果也是1。

 

程序中的jdbc配置

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
<!--        <property name="minIdle" value="${jdbc.minIdle}"/>-->
<!--        <property name="maxIdle" value="${jdbc.maxIdle}"/>-->
    </bean>
    
    <bean id="sqlSessionFactoryDb" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- 自動掃描entity目錄, 省掉Configuration.xml里的手工配置 -->
        <property name="mapperLocations" value="classpath*:com/cn/yft/ora/mapper/*.xml"/>
    </bean>
    
    <!-- 定義事務管理配置 -->
    <bean id="txManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

 

 

怎么發現的這個坑呢? 由於程序要根據這個批量操作數據的影響行數,來判斷是否進行后續邏輯處理。卻發現后續邏輯竟然一直不處理。通過添加log,這才發現,原來這個影響行數並不是我們的預期結果。

 

mybatis執行begin..end語句 為什么不返回影響行數呢?
原因未暫查出來。

那么,問題還得修復呀。


我的臨時解決辦法,是不用begin..end。

 

像下面這樣,直接干掉begin..end行不行呢?

<update id="updateByTransBatchIdAndBankId"  parameterType="java.util.List">
    <foreach collection="list" item="item" index="index" close=";" separator=";">
        update T_PLAT_ORDER  set STATE = 1
        where ORDER_ID = 'ddd' and state in (0,11)
    </foreach>
</update>

 

經過測試,直接干到begin..end是有些草率的。當入參List里只有一條數據時執行沒問題,畢竟,這只是執行了一個單條update語句,顯然不會有問題。而一旦存在多條update語句時,就會遇到包含Oracle錯誤碼的java.sql.SQLSyntaxErrorException: ORA-00911: 無效字符

2022-02-21 10:35:21,397 DEBUG [main] jdbc.BaseJdbcLogger (com.cn.yft.ora.dao.TPlatOrderDAO.updateByTransBatchIdAndBankId:145) - ==>  Preparing: update T_PLAT_ORDER set STATE = 1 where ORDER_ID = 'ddd' and state in (0,11) ; update T_PLAT_ORDER set STATE = 1 where ORDER_ID = 'ddd' and state in (0,11) ; 
2022-02-21 10:35:21,397 DEBUG [main] jdbc.BaseJdbcLogger (com.cn.yft.ora.dao.TPlatOrderDAO.updateByTransBatchIdAndBankId:145) - ==> Parameters: 
2022-02-21 10:35:21,437 INFO  [main] xml.XmlBeanDefinitionReader (org.springframework.beans.factory.xml.XmlBeanDefinitionReader:317) - Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]
2022-02-21 10:35:21,484 INFO  [main] support.SQLErrorCodesFactory (org.springframework.jdbc.support.SQLErrorCodesFactory:126) - SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase, Hana]

org.springframework.jdbc.BadSqlGrammarException: 
### Error updating database.  Cause: java.sql.SQLSyntaxErrorException: ORA-00911: 無效字符

### The error may involve com.cn.yft.ora.dao.TPlatOrderDAO.updateByTransBatchIdAndBankId-Inline
### The error occurred while setting parameters
### SQL: update T_PLAT_ORDER  set STATE = 1         where ORDER_ID = 'ddd' and state in (0,11)      ;       update T_PLAT_ORDER  set STATE = 1         where ORDER_ID = 'ddd' and state in (0,11)      ;
### Cause: java.sql.SQLSyntaxErrorException: ORA-00911: 無效字符

; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: ORA-00911: 無效字符


    at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:91)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
    at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:75)
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:447)
    at com.sun.proxy.$Proxy32.update(Unknown Source)
    at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:295)
    at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:62)
    at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:53)
    at com.sun.proxy.$Proxy33.updateByTransBatchIdAndBankId(Unknown Source)
    at com.cn.yft.ora.dao.TPlatOrderDAOTest.updateByTransBatchIdAndBankId(TPlatOrderDAOTest.java:39)
    ...
Caused by: java.sql.SQLSyntaxErrorException: ORA-00911: 無效字符
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399)
    at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059)
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522)
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)
    at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587)
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:225)
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:53)
    at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:943)
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1150)
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:4798)
    at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:4901)
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1385)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:172)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:172)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:59)
    at com.sun.proxy.$Proxy36.execute(Unknown Source)
    at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:46)
    at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74)
    at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:50)
    at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
    at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:434)
    ... 34 more
View Code

 

 

接下來,依然沿着干掉begin..end的方針,這次呢,我們轉變sql,改成in操作。因為我們這個批處理操作的場景用in完全可以,這樣也不用糾結多條update部分成功怎么辦的情況。ok,問題暫時解決。

<update id="updateByTransBatchIdAndBankId"  parameterType="java.util.List">
    update T_PLAT_ORDER  set STATE = 1
    where ORDER_ID in
    <foreach collection="list" item="item" index="index"  close=")" open="(" separator=",">
      #{item.orderId,jdbcType=VARCHAR}
    </foreach>
     and state in (0,11)
</update>

 


2022-02-21 10:55:02,732 DEBUG [main] jdbc.BaseJdbcLogger (com.cn.yft.ora.dao.TPlatOrderDAO.updateByTransBatchIdAndBankId:145) - ==> Preparing: update T_PLAT_ORDER set STATE = 1 where ORDER_ID in ( ? , ? , ? ) and state in (0,11)
2022-02-21 10:55:02,734 DEBUG [main] jdbc.BaseJdbcLogger (com.cn.yft.ora.dao.TPlatOrderDAO.updateByTransBatchIdAndBankId:145) - ==> Parameters: 3f12bcd8-3afe-4743-ae14-c5d53fbc1a76(String), 2022020911335800504754(String), 2022021817531700189078(String)
2022-02-21 10:55:02,744 DEBUG [main] jdbc.BaseJdbcLogger (com.cn.yft.ora.dao.TPlatOrderDAO.updateByTransBatchIdAndBankId:145) - <== Updates: 2

 

 

后續:mybatis連接Oracle執行begin..end批量update操作,未返回實際影響行數。本次曲線救國,具體原因日后還需再分析和定位。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM