这次坑让我知道一个之前没想到过得知识点:
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());
}

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

被折叠的 条评论
为什么被折叠?



