0
点赞
收藏
分享

微信扫一扫

mybatis连接Oracle执行begin..end批量操作返回行数问题

西曲风 2022-07-12 阅读 58

如下是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: 无效字符

mybatis连接Oracle执行begin..end批量操作返回行数问题_java

mybatis连接Oracle执行begin..end批量操作返回行数问题_mybatis_02

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操作,未返回实际影响行数。本次曲线救国,具体原因日后还需再分析和定位。

举报

相关推荐

0 条评论