开发者

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

目录
  • 问题
  • 原因
  • 解决办法
    • 如果是存储过程
  • 总结

    问题

    myBATis有如下代码获取序列作为主键

    IdMapper编程客栈.Java

        @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("编程客栈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考,也希望大家多多支持编程客栈(www.devze.com)。

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜