Mybatis+MSSql插入数据的同时并获取自增的ID

在项目中遇到这样的情况,新增一个角色,这个角色有某些权限,这两个数据存在不同的表中,一个是sys_role,另外一个是sys_role_permission表,注意,现在的逻辑是这样的

1,在表sys_user中新增一个角色,里面存放角色id和角色名称,

2,从1中获取新增的角色id,然后讲这个角色对应的权限存放在sys_role_permission中。

本项目使用的是mybatis+ms sql 2008,然后我在网上开始找资料,以及在api文档中找资料,发现资料几乎是mysql的,而针对ms sqlserver的比较少。还好我试了一晚上终于出来结果了,并且对api文档的介绍有了更进一步的认识

首先,贴代码,然后讲解

    <insert id="insertRole">
        BEGIN
        INSERT INTO [sys_role]([role_name],[available]) VALUES(#{role.roleName},1);
        <selectKey resultType="int" keyProperty="role_id" order="BEFORE">
            -- SELECT MAX(role_id) as id FROM [sys_role];
            SELECT IDENT_CURRENT('sys_role')+1
        </selectKey>
        <foreach item="item" index="index" collection="list">
            insert into sys_role_permission(role_id,permission_id) VALUES (#{role_id}, #{item});
        </foreach>
        END
    </insert>

注意,官方文档关于order的注释:

这可以被设置为 BEFORE 或 AFTER。如果设置为 BEFORE,那么它会首先选择主键,设置 keyProperty 然后执行插入语句。如果设置为 AFTER,那么先执行插入语句,然后是 selectKey 元素 - 这和像 Oracle 的数据库相似,在插入语句内部可能有嵌入索引调用。

怎么理解这个“先执行插入语句”?

上面的mapper.xml文件中,有两部插入操作

1,给sys_role插入角色信息

2,给sys_role_permission中插入角色权限对应关系

所以,刚开始我理解的先执行插入语句是这样的:在执行selectKey下面的那个insert语句前执行的,所以,我刚开始设置的order="after",这样一直出现这样的错误

2017-02-20 23:19:32,757 [main] DEBUG [com.unisits.zngkpt.common.userprivrman.mapper.SysRoleDao.insertRole] - ==>  Preparing: BEGIN INSERT INTO [sys_role]([role_name],[available]) VALUES(?,1); insert into sys_role_permission(role_id,permission_id) VALUES (?, ?); insert into sys_role_permission(role_id,permission_id) VALUES (?, ?); END 
  2017-02-20 23:19:32,813 [main] DEBUG [com.unisits.zngkpt.common.userprivrman.mapper.SysRoleDao.insertRole] - ==> Parameters: test1(String), null, 10(Integer), null, 11(Integer)
  2017-02-20 23:19:32,820 [main] DEBUG [com.unisits.zngkpt.common.userprivrman.mapper.SysRoleDao.insertRole] - <==    Updates: 1
  2017-02-20 23:19:32,822 [main] DEBUG [com.unisits.zngkpt.common.userprivrman.mapper.SysRoleDao.insertRole!selectKey] - ==>  Preparing: -- SELECT MAX(role_id) as id FROM [sys_role]; SELECT IDENT_CURRENT('sys_role')+1 
  2017-02-20 23:19:32,822 [main] DEBUG [com.unisits.zngkpt.common.userprivrman.mapper.SysRoleDao.insertRole!selectKey] - ==> Parameters: 
  2017-02-20 23:19:32,847 [main] DEBUG [com.unisits.zngkpt.common.userprivrman.mapper.SysRoleDao.insertRole!selectKey] - <==      Total: 1

看看,先看执行顺序啊:1,先执行所有的insert语句,而第二步中的insert语句的role_id为空,也就是说没有这个值,为什么呢?很明显,给sys_role_permission的role_id参数设置值的selectKey并没有执行,所以,到这里你就明白了,“先执行插入语句”意思就是说先执行所有的插入语句,然后执行selectKey里面的语句

那么,真的是这样么?那我把order该为“BEFORE”呢,运行结果如下:

  2017-02-20 23:24:36,036 [main] DEBUG [com.unisits.zngkpt.common.userprivrman.mapper.SysRoleDao.insertRole!selectKey] - ==>  Preparing: -- SELECT MAX(role_id) as id FROM [sys_role]; SELECT IDENT_CURRENT('sys_role')+1 
  2017-02-20 23:24:36,085 [main] DEBUG [com.unisits.zngkpt.common.userprivrman.mapper.SysRoleDao.insertRole!selectKey] - ==> Parameters: 
  2017-02-20 23:24:36,119 [main] DEBUG [com.unisits.zngkpt.common.userprivrman.mapper.SysRoleDao.insertRole!selectKey] - <==      Total: 1
  2017-02-20 23:24:36,168 [main] DEBUG [com.unisits.zngkpt.common.userprivrman.mapper.SysRoleDao.insertRole] - ==>  Preparing: BEGIN INSERT INTO [sys_role]([role_name],[available]) VALUES(?,1); insert into sys_role_permission(role_id,permission_id) VALUES (?, ?); insert into sys_role_permission(role_id,permission_id) VALUES (?, ?); END 
  2017-02-20 23:24:36,186 [main] DEBUG [com.unisits.zngkpt.common.userprivrman.mapper.SysRoleDao.insertRole] - ==> Parameters: test1(String), 31(Integer), 10(Integer), 31(Integer), 11(Integer)
  2017-02-20 23:24:36,193 [main] DEBUG [com.unisits.zngkpt.common.userprivrman.mapper.SysRoleDao.insertRole] - <==    Updates: 1

看看上面的结果,是不是说明上面的假设成立

综上,对mybatis selectKey中的order的正确理解是

before是在所有的insert操作前执行

after是在所有的insert操作后执行

好了,上面是自己的一些见解。主要网上针对mybatis+mssql的资料并不多。只能边做编总结了。

还有,以后哟时间来琢磨琢磨mybatis的源码,提升一下自己。

posted @ 2017-02-20 23:28  凝荷  阅读(2031)  评论(0编辑  收藏  举报