在使用触发器的情况下使用Mybatis通过 SelectKey获取回传ID

使用数据库:sqlServer

开发语言:Java

场景:原本使用正常运行的mybaits获取

<insert id="insert" parameterType="com.sl.pt.base.model.Customer" >
    <selectKey resultType="java.lang.Long" keyProperty="id" order="AFTER" >
      SELECT @@IDENTITY
    </selectKey>
    insert into dbo.BASE_CUSTOMER (...)
                                                   values(...)
 </insert>

 但是客户提出需要添加一个触发器,新增的时候同时添加另一个表的数据,写好后发现在控制台运行没有问题,触发器什么都正常运行,但是在程序中每次都报错。

解决步骤

我是在网上不断的找各种资料,发现一位大佬说的蛮好的

COPE_IDENTITY 和 @@IDENTITY 返回在当前会话中的任何表内所生成的最后一个标识值。但是,SCOPE_IDENTITY 只返回插入到当前作用域中的值;@@IDENTITY 不受限于特定的作用域。例如,有两个表 T1 和 T2,在 T1 上定义了一个 INSERT 触发器。当将某行插入 T1 时,触发器被激发,并在 T2 中插入一行。此例说明了两个作用域:一个是在 T1 上的插入,另一个是作为触发器的结果在 T2 上的插入。 假设 T1 和 T2 都有 IDENTITY 列,@@IDENTITY 和 SCOPE_IDENTITY 将在 T1 上的 INSERT 语句的最后返回不同的值。 @@IDENTITY 返回插入到当前会话中任何作用域内的最后一个 IDENTITY 列值,该值是插入 T2 中的值。SCOPE_IDENTITY() 返回插入 T1 中的 IDENTITY 值,该值是发生在相同作用域中的最后一个 INSERT。如果在作用域中发生插入语句到标识列之前唤醒调用 SCOPE_IDENTITY() 函数,则该函数将返回 NULL 值。

然后他给出了个他的(正确)方法

<insert id="addUser" parameterClass="user">  
       select 1;  
       <selectKey resultClass="int" keyProperty="id" type="post">  
               INSERT INTO t_user (name,sex)VALUES (#name#,#sex#)  
               SELECT SCOPE_IDENTITY() AS  ID  
         </selectKey>    
</insert>

网址(建议查看源代码的方式看这篇文章):https://www.iteye.com/problems/20809

 我也是照个这个他这个思路做的,把insert放到<selectKey>标签里面,insert后面放入个SELECT SCOPE_IDENTITY() ,这样SCOPE_IDENTITY()就和insert在同一个域里面了,返回的就是控制,而外面(<insert>标签内)则放入select 1,也有人说什么都不放,就空着,但是我测试发现总是报错。

于是想到<insert><selectKey></selectKey></insert>的原理上入手,没找到。。。就自己思考了下,其实无外乎<insert>标签内执行新增前或后调用<selectKey>标签获取返回值,突然想明白了,既然如此,<insert>标签内里面写select 1当然是有问题的,<insert>标签里面应该写insert语句才不报错嘛,于是立马创建了一张表BASE_TPL,讲语句改为如下

<insert id="insert" parameterType="com.sl.pt.base.model.Customer" >
    insert into dbo.BASE_TPL(ID,NAME) VALUES('1','1')
    <selectKey resultType="java.lang.Long" keyProperty="id" order="AFTER" >
               insert into dbo.BASE_CUSTOMER (...)
                                                              values(...) SELECT SCOPE_IDENTITY()
    </selectKey>
 </insert>

这样写了以后发现可以解决了,但是我想随着数据的增多,BASE_TPL表里面的数据也变多了,于是在触发器中写了个删除BASE_TPL的语句。

 

虽然问题是解决了,但是平白无故多出一张没用的表,还是感觉不太好,如果有更好的方法,希望各位提出来。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值