本文主要是介绍MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,...
问题
myBATis有如下代码获取序列作为主键
@Select("SELECT TABLE.NEXTVAL FROM DUAL") String getId();
同一事务循环调用查询伪代码
@Transactional(rollbackFor = Exception.class) public QueryMedicalFeeRes queryMedicalFee(QueryMedicalFeeReq req) { for (Obj o : objs) { Long id = idMapper.getId(); log.info("id{}",id); } }
输出如下:id都是1
id1
id1
id1
id1
原因
因为MyBatis的一级缓存导致的。而且MyBatis默认开启一级缓存,这样就会导致循环调用查询方法的时候,直接从缓存获取,不会查询数据库,从而获取到的数据都是缓存数据。
但请注意,并不是所有查询都不使用一级缓存!而是当你需要查询的内容是需要变化的时候才要禁用一级缓存。如:查询oracle的序列、查询存储过程获取主键值等情况才需要禁用一级缓存。
解决办法
禁用一级缓存
<select id="getId" resultType="java.lang.Long" useCache="false" flushCache="true"> SELECT TABLE.NEXTVAL AS ID FROM DUAL </select>
@Select("编程China编程SELECT TABLE.NEXTVAL FROM DUAL") @Options(useCache = false, flushCache = Options.FlushCachePolicy.TRUE) String getId();
如果是存储过程
<select id="getId" resultType="java.lang.Long" statementType="CALLABLE" useCache="false" flushCache="true"> {c编程all GET_NEXT_ID(#{identity,mode=IN,jdbcType=VARCHAR},#{tableName,mode=IN,jdbcType=VARCHAR},#{count,mode=IN,jdbcType=INTEGER},#{currentNo,mode=OUT,jdbcType=INTEGER})} </select>
```java @Select("{call GET_NEXT_ID(#{identity,mode=IN,jdbcType=VARCHAR},#{tableName,mode=IN,jdbcType=VARCHAR},#{count,mode=IN,jdbcType=INTEGER},#{currentNo,mode=OUT,jdbcType=INTEGER})}") @Options(statementType = StatementType.CALLABLE, useCache = falsphpe, flushCache = Options.FlushCachePolicy.TRUE) String getId();
总结
以上为个人经验,希望能给大家一个参javascript考,也希望大家多多支持China编程(www.chinasem.cn)。
这篇关于MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!