记使用SelectKey标签的遇到的一个天坑

博客讲述了在使用`SelectKey`标签时遇到的问题,强调了`SELECT LAST_INSERT_ID()`只能获取默认键方式插入记录的ID。通过示例展示了如何在插入数据时正确获取自定义主键的值,对比了使用`useGeneratedKeys`和`keyProperty`与`SelectKey`标签的区别,指出后者在特定情况下的不足。

这次坑让我知道一个之前没想到过得知识点:
select last_insert_id()只能获取按照默认键方式插入的记录的key。
可以先做个测试,然后再来看下面的天坑,觉得啰嗦的可以直接看坑
建表语句
CREATE TABLEgoods3(goodsIdINT(11) NOT NULL AUTO_INCREMENT,goodsNameVARCHAR(20) NOT NULL,goodsPriceDOUBLE DEFAULT NULL,goodsStateINT(1) DEFAULT '1', PRIMARY KEY (goodsId) ) ENGINE=INNODB DEFAULT CHARSET=utf8

连续两次以default作为key的形式插入值,每次插完都调用
SELECT LAST_INSERT_ID()

 INSERT INTO goods3 VALUES(DEFAULT,'wdnm',DEFAULT,DEFAULT)
 SELECT LAST_INSERT_ID()  #值为1
 INSERT INTO goods3 VALUES(DEFAULT,'wdnm',DEFAULT,DEFAULT)
 SELECT LAST_INSERT_ID()  #值为2 

然后我们再试着不用default来插入一下试试

 INSERT INTO goods3 VALUES(1000,'wdnm',DEFAULT,DEFAULT)
 SELECT LAST_INSERT_ID()  
 #值还是为2,说明我们自定义主键的这次插入并没有使得LAST_INSERT_ID()的值变化

获取主键有两种方法,一种是在insert里面写useGeneratedKeys和keyProperty;
另一种是使用标签,先看几组测试,再说遇到的坑
使用第一种获取主键的方法
先看看用标签来获取的,坑就是在这里踩的

TestA1
先利用default插入,可以发现,确实是得到了返回的key

<insert id="insertIntoGoods3" parameterType="bean.GoodsInfo">
        <selectKey resultType="java.lang.Integer" keyProperty="goodsId"
         order="AFTER">
             select last_insert_id()
        </selectKey>
        insert into goods values(default,#{goodsName},default ,default)
</insert>
public void Method1WithNoId(){
        InputStream in = Goods1.class.getClassLoader().getResourceAsStream("config.xml");
        SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(in);
        SqlSession session = ssf.openSession();
        GoodsMapper gm = session.getMapper(GoodsMapper.class);
        GoodsInfo gi = new GoodsInfo();
        gi.setGoodsName("戒骄戒躁");
        gm.insertIntoGoods3(gi);
        session.commit();
        System.out.println("返回的主键为:"+gi.getGoodsId());
    }

在这里插入图片描述

然后我们试着用自己传入的主键来插入值,

坑出现在这里

TestA2

<insert id="insertIntoGoods4" parameterType="bean.GoodsInfo">
        <selectKey resultType="java.lang.Integer" keyProperty="goodsId"
           order="AFTER">
            select last_insert_id()
        </selectKey>
        insert into goods values(#{goodsId},#{goodsName},default ,default)
</insert>
public void Method1WithId(){
        InputStream in = Goods1.class.getClassLoader().getResourceAsStream("config.xml");
        SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(in);
        SqlSession session = ssf.openSession();
        GoodsMapper gm = session.getMapper(GoodsMapper.class);
        GoodsInfo gi = new GoodsInfo();
        gi.setGoodsId(1000);
        gi.setGoodsName("戒骄戒躁");
        gm.insertIntoGoods4(gi);
        session.commit();
        System.out.println("返回的主键为:"+gi.getGoodsId());
}

在这里插入图片描述
有没有觉得很神奇,当时不知道select last_insert_id()只能查找按照default插入的值的,我纠结了很久为啥返回个主键是0.

但是,使用下面这种方法就可以规避上面的返回值是0的情况,它这种是直接使用JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键,所以就算是自己写的主键也可以正常返回。
TestB1

<insert id="insertIntoGoods1" parameterType="bean.GoodsInfo"
            useGeneratedKeys="true" keyProperty="goodsId">
      insert into goods values(default ,#{goodsName},default ,default)
</insert>
//调用使用default的方法
public void Method1WithNoId(){
        InputStream in = Goods1.class.getClassLoader().getResourceAsStream("config.xml");
        SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(in);
        SqlSession session = ssf.openSession();
        GoodsMapper gm = session.getMapper(GoodsMapper.class);
        GoodsInfo gi = new GoodsInfo();
        gi.setGoodsName("戒骄戒躁");
        gm.insertIntoGoods1(gi);
        session.commit();
        System.out.println("返回的主键为:"+gi.getGoodsId());
    }

在这里插入图片描述

TestB2

<!--这里相对于上面唯一的改变就是把values中的default改成goodsId-->
<insert id="insertIntoGoods2" parameterType="bean.GoodsInfo" useGeneratedKeys="true" keyProperty="goodsId">
        insert into goods values(#{goodsId} ,#{goodsName},default ,default)
</insert>
public void Method1WithId(){
        InputStream in = Goods1.class.getClassLoader().getResourceAsStream("config.xml");
        SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(in);
        SqlSession session = ssf.openSession();
        GoodsMapper gm = session.getMapper(GoodsMapper.class);
        GoodsInfo gi = new GoodsInfo();
        gi.setGoodsId(10);
        gi.setGoodsName("戒骄戒躁");
        gm.insertIntoGoods2(gi);
        session.commit();
        System.out.println("返回的主键为:"+gi.getGoodsId());
    }

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值