MySQL+Mybatis插入数据后如何正确获取自增ID?keyProperty避坑指南

MySQL+Mybatis插入数据后如何正确获取自增ID?keyProperty避坑指南

最近在做一个订单系统的开发,遇到一个挺有意思的问题。我们有个需求,用户下单后需要立刻生成一个唯一的订单号,并且后续的支付、物流环节都要用这个ID来关联。团队里一个刚毕业不久的小伙伴,在Mybatis的Mapper里配置了useGeneratedKeys,满心欢喜地以为执行完insert方法,返回值就是那个自增的主键ID。结果呢?日志里打印出来的永远是“1”。他挠着头来找我:“哥,这数据库是不是坏了?怎么每次插进去都返回1,ID不应该是个很大的数字吗?”

我一看就乐了,这场景太经典了。很多刚开始用Mybatis的朋友,尤其是从一些其他ORM框架转过来的,很容易在这个点上踩坑。那个返回值“1”其实代表的是影响的行数,而真正的自增ID,早就悄无声息地“溜”进了你传入的那个实体对象里。今天我们就来彻底搞明白useGeneratedKeyskeyProperty这对搭档是怎么工作的,以及如何避开那些常见的“坑”。

1. 理解Mybatis的“返回值”陷阱:为什么你拿到的是1?

我们先从最让人困惑的地方说起。当你调用Mybatis的插入方法,比如int insert(Order order),这个方法执行完毕后返回的int值,永远代表的是该条SQL语句影响数据库的行数。对于单条INSERT语句,成功插入就是1,失败或异常就是0。这是JDBC规范定义的,Mybatis只是忠实地传递了这个结果。

那么自增ID去哪了?这就引出了JDBC的Statement.getGeneratedKeys()方法。支持自增主键的数据库(如MySQL、SQL Server),在执行插入语句后,可以通过这个接口拿到数据库内部生成的主键值。Mybatis的useGeneratedKeys功能,本质上就是帮你调用了这个方法,并且将取到的值,设置(回填)到你传入的Java实体对象的指定属性里

关键理解useGeneratedKeys机制是一个“副作用”操作。它不改变Mapper接口方法的返回值,而是修改了你传入的那个参数对象的状态。

我们来看一个典型的错误代码和正确理解的对比:

// Service层 - 错误的理解和用法
public Long createOrder(OrderDTO dto) {
    Order order = convertToEntity(dto);
    // 错误:以为insert方法的返回值就是新生成的ID
    Long generatedId = orderMapper.insert(order);
    return generatedId; // 这里返回的永远是 1!
}

// Service层 - 正确的理解和用法
public Long createOrder(OrderDTO dto) {
    Order order = convertToEntity(dto);
    // 正确:insert方法执行后,自增ID已经被注入到order对象的id属性中
    orderMapper.insert(order);
    // 从原对象中获取被回填的ID
    return order.getId();
}

这个“返回值是影响行数,ID回填到参数对象”的设计,其实有它的合理性。它保证了Mapper接口方法签名的一致性(int表示操作结果),同时通过参数引用的方式隐式地返回了额外的生成数据。但对于不熟悉机制的人来说,这确实是个容易掉进去的坑。

2. useGeneratedKeys与keyProperty的配置三叉戟

知道了原理,我们来看看怎么配置。Mybatis提供了三个不同层级的配置位置,它们的影响范围和优先级各不相同,就像一把三叉戟,用对了威力无穷,用错了可能伤到自己。

2.1 全局配置:一把双刃剑

在Mybatis的核心配置文件(通常是mybatis-config.xml)中,你可以在<settings>标签下进行全局配置:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <!-- 启用二级缓存 -->
        <setting name="cacheEnabled" value="true"/>
        <!-- 允许JDBC支持自动生成主键 -->
        <setting name="useGeneratedKeys" value="true"/>
        <!-- 其他配置... -->
    </settings>
</configuration>

或者在Spring Boot的application.yml中通过configLocation指定上述配置文件,也可以直接在application.yml中配置:

mybatis:
  configuration:
    # 注意:这是configuration下的use-generated-keys,不是config-location
    use-generated-keys: true

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值