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

 更新时间:2025年09月24日 15:42:26   作者:Meta39  
MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,需在需要动态数据(如Oracle序列、存储过程主键)时禁用缓存,避免缓存干扰查询结果

问题

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">
    {call 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 = false, flushCache = Options.FlushCachePolicy.TRUE)
    String getId();

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java中接口和抽象类的区别与相同之处

    Java中接口和抽象类的区别与相同之处

    这篇文章主要介绍了Java中接口和抽象类的区别与相同之处,本文讲解了抽象类的概念、接口的概念、接口和抽象类的区别与联系等内容,需要的朋友可以参考下
    2015-06-06
  • 浅谈Java中的interface应用与面向接口编程

    浅谈Java中的interface应用与面向接口编程

    这篇文章主要介绍了浅谈Java中的interface应用与面向接口编程,Java的关键字interface应用,一个接口,多个实现类,面向接口编程,把业务逻辑线提取出来作为接口,具体的业务实现通过该接口的实现类来完成,需要的朋友可以参考下
    2023-10-10
  • SpringBoot处理JSON数据方法详解

    SpringBoot处理JSON数据方法详解

    这篇文章主要介绍了SpringBoot整合Web开发中Json数据处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-10-10
  • Spring监听器及定时任务实现方法详解

    Spring监听器及定时任务实现方法详解

    这篇文章主要介绍了Spring监听器及定时任务实现方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • Java学习之缓冲流的原理详解

    Java学习之缓冲流的原理详解

    为了提高其数据的读写效率,Java中又定义了四种缓冲流,分别是:字节缓冲输入流、字节缓冲输出流、字符缓冲输入流和字符缓冲输出流。本文主要来和大家聊聊这些缓冲流的原理,希望对大家有所帮助
    2023-01-01
  • SpringMVC框架post提交数据库出现乱码解决方案

    SpringMVC框架post提交数据库出现乱码解决方案

    这篇文章主要介绍了SpringMVC框架post提交数据库出现乱码解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • Java:

    Java:"失效"的private修饰符

    本文主要介绍Java 失效的private修饰符,这里整理了相关资料说明private 修饰符的作用,如何使用并与C++ 做比较,有兴趣的小伙伴可以参考下
    2016-08-08
  • Mybatis中where标签与if标签结合使用详细说明

    Mybatis中where标签与if标签结合使用详细说明

    mybatis中if和where用于动态sql的条件拼接,在查询语句中如果缺失某个条件,通过if和where标签可以动态的改变查询条件,下面这篇文章主要给大家介绍了关于Mybatis中where标签与if标签结合使用的详细说明,需要的朋友可以参考下
    2023-03-03
  • 基于重定向RedirectAttributes的用法解析

    基于重定向RedirectAttributes的用法解析

    这篇文章主要介绍了基于重定向RedirectAttributes的用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Spring Data JPA 关键字Exists的用法说明

    Spring Data JPA 关键字Exists的用法说明

    这篇文章主要介绍了Spring Data JPA 关键字Exists的用法说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06

最新评论