zoukankan      html  css  js  c++  java
  • mybatis获取insert插入之后的id

    一.为什么要获取insert的id

    写了测试类测试插入,插入之后用select查询出来进行Assert

    插入成功后,不管Select对比的结果成功还是失败,都希望删除掉测试插入的结果

    二.运行环境

    mysql自增主键

    mapper中的insert下是,这是通过mybatis_generator自动生成的,最新版本1.3.6.

       <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.Long">
          SELECT LAST_INSERT_ID()
        </selectKey>

    然后

     goodsClassService.insertGoodsClass(goodsclass);

    但是用断点调试发现goodsclass的id一直是0,这让我不得其解.

    三.原因

    感觉Mybatis的这个自动生成的xml有问题.

    参考:http://blog.csdn.net/slvher/article/details/42298355

    6. last_insert_id()的值是由MySQL server来维护的,而且是为每条连接维护独立的值,也即,某条连接调用last_insert_id()获取到的值是这条连接最近一次insert操作执行后的自增值,该值不会被其它连接的sql语句所影响。这个行为保证了不同的连接能正确地获取到它最近一次insert sql执行所插入的行的自增值,也就是说,last_insert_id()的值不需要通过加锁或事务机制来保证其在多连接场景下的正确性。

    mybatis的连接和客户端,比如workbench连接不同,last_insert_id()不能进行比较.

    每一次测试运行都是新的连接,所last_insert_id()都是0,

    mybatis默认生成的selectKey是在before之前,手动插入id为0,

    如果给自增列插入0或者null,那么自增列设置为根据当前最大的id+1

    如果批量插入就有问题了

    Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '66671' for key 'PRIMARY'

    第一次插入id是0,可以自增.因为用了连接池,即使关闭了sqlsession也可能是同一个连接,第二次插入取出了last_insert_id()为66671,再插入,重复id错误.

    三.解决办法

    将上面的改为

     <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
          SELECT LAST_INSERT_ID()
        </selectKey>

    这是插入之后取出SELECT LAST_INSERT_ID(),插入的时候id默认不插入,mysql会自动帮我们自增.

    插入之后二中的goodsclass的id就变为last_id,可以取出来用了.

    所以我觉得mybatis_generator这个配置操作有点小bug的

    四.测试代码

    省略了部分Assert代码

    插入成功后,无论查询对比失败或者成功,都将插入的数据删掉.

    //测试添加商品分类
        //isok()返回状态码200
        @Test
        public void  test_add_goodsClass() throws Exception
        {
            //测试插入是否成功
            String ret=mockMvc.perform(post("/goods_class/add")
                    .param("pid","1"))
                    .andExpect(status().isOk())
                    .andReturn().getResponse().getContentAsString();
            ObjectMapper objectMapper=new ObjectMapper();
            Map<String,String> map=objectMapper.readValue(ret,Map.class);
            Assert.assertNotNull(map);
            Long last_insert_id=Long.valueOf(map.get("id"));
            Assert.assertNotEquals(last_insert_id,Long.valueOf(0));
           try {
     
    //测试插入结果 Goodsclass goodsclass= goodsClassService.getGoodsClassById(last_insert_id); Assert.assertEquals(goodsclass.getParent().getId(),Long.valueOf(1)); } finally { goodsClassService.deleteGoodsClassById(last_insert_id); Assert.assertNull(goodsClassService.getGoodsClassById(last_insert_id)); } }
  • 相关阅读:
    Why Choose Jetty?
    Jetty 的工作原理以及与 Tomcat 的比较
    Tomcat设计模式
    Servlet 工作原理解析
    Tomcat 系统架构
    spring boot 打包方式 spring boot 整合mybaits REST services
    wireshark udp 序列号 User Datagram Protocol UDP
    Maven 的聚合(多模块)和 Parent 继承
    缓存策略 半自动化就是mybaitis只支持数据库查出的数据映射到pojo类上,而实体到数据库的映射需要自己编写sql语句实现,相较于hibernate这种完全自动化的框架我更喜欢mybatis
    Mybatis解决sql中like通配符模糊匹配 构造方法覆盖 mybits 增删改
  • 原文地址:https://www.cnblogs.com/ptqueen/p/8435230.html
Copyright © 2011-2022 走看看