记使用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());
    }

在这里插入图片描述

你可能感兴趣的:(写bug专家)