`

iBatis自动生成的主键 (Oracle,MS Sql Server,MySQL)

阅读更多
iBatis的sqlMap配置文件的selectKey元素有个type属性,可以指定pre或者post表示前生成(pre)还是后生成(post)。

Oracle设置
<!-- Oracle SEQUENCE --> 
<insert id="insertProduct-ORACLE" parameterClass="com.domain.Product"> 
    <selectKey resultClass="int" keyProperty="id" type="pre"> 
        <![CDATA[SELECT STOCKIDSEQUENCE.NEXTVAL AS ID FROM DUAL]]> 
    </selectKey> 
    <![CDATA[insert into PRODUCT (PRD_ID,PRD_DESCRIPTION) values(#id#,#description#)]]> 
</insert> 

MS SQL Server配置
<!-- Microsoft SQL Server IDENTITY Column --> 
<insert id="insertProduct-MS-SQL" parameterClass="com.domain.Product"> 
    <![CDATA[insert into PRODUCT (PRD_DESCRIPTION) values(#description#) ]]> 
    <selectKey resultClass="int" keyProperty="id" type="post"> 
        <![CDATA[SELECT @@IDENTITY AS ID ]]>
        <!-- 该方法不安全 应当用SCOPE_IDENTITY() 但这个函数属于域函数,需要在一个语句块中执行。 -->
    </selectKey> 
</insert>

上述MS SQL Server配置随是官网提供的配置,但实际上却恰恰隐患重重!按下述配置,确保获得有效主键。
<!-- Microsoft SQL Server IDENTITY Column 改进--> 
<insert id="insertProduct-MS-SQL" parameterClass="com.domain.Product"> 
    <selectKey resultClass="int" keyProperty="id"> 
        <![CDATA[insert into PRODUCT (PRD_DESCRIPTION) values(#description#)
        SELECT SCOPE_IDENTITY() AS ID ]]>
    </selectKey> 
</insert>

MySQL配置
<!-- MySQL Last Insert Id -->
<insert id="insertProduct-Mysql" parameterClass="com.domain.Product">
    <![CDATA[insert into PRODUCT(PRD_DESCRIPTION) values(#description#)]]> 
    <selectKey resultClass="int" keyProperty="id">
        <![CDATA[SELECT LAST_INSERT_ID() AS ID ]]> 
        <!-- 该方法LAST_INSERT_ID()与数据库连接绑定,同属统一会话级别,不会发生上述MS SQL Server的函数问题。 -->
    </selectKey>
</insert>

通过以上方式,可以最大程度上确保插入数据的时候获得当前自增主键。
分享到:
评论
5 楼 snowolf 2009-07-15  
xnxqs 写道
Xml代码
<!-- Microsoft SQL Server IDENTITY Column 改进-->   
<insert id="insertProduct-MS-SQL" parameterClass="com.domain.Product">   
    <selectKey resultClass="int" keyProperty="id">   
        <![CDATA[insert into PRODUCT (PRD_DESCRIPTION) values(#description#) 
        SELECT SCOPE_IDENTITY() AS ID ]]> 
    </selectKey>   
</insert>

这个你试过吗?如果直接在selectKey里面写插入语句是会报错的:
by: com.microsoft.sqlserver.jdbc.SQLServerException: 未能准备语句。
我现在也是被这个问题所困扰,用 @@IDENTITY 如果在同一事务内插入二个表,得到的结果不一定是你想要的,但用SCOPE_IDENTITY() 又没法用。不知道其它人是怎么解决。其实网上很多例子是这样写的。
<!-- Microsoft SQL Server IDENTITY Column 改进-->   
<insert id="insertProduct-MS-SQL" parameterClass="com.domain.Product">  
insert into PRODUCT (PRD_DESCRIPTION) values(#description#) 

    <selectKey resultClass="int" keyProperty="id">   
        <![CDATA[        SELECT SCOPE_IDENTITY() AS ID ]]> 
    </selectKey>   
</insert>

但实际这样就把它当二条语句执行了。依旧得不到ID。按你的方法又会报错。怎么办???请楼下的给出解答。我这边IE有问题,没法用UBB。还请见谅

我写出来,当然是我测试过的!环境是 sql server 2005 绝对没有问题
4 楼 xnxqs 2009-07-15  
Xml代码
<!-- Microsoft SQL Server IDENTITY Column 改进-->   
<insert id="insertProduct-MS-SQL" parameterClass="com.domain.Product">   
    <selectKey resultClass="int" keyProperty="id">   
        <![CDATA[insert into PRODUCT (PRD_DESCRIPTION) values(#description#) 
        SELECT SCOPE_IDENTITY() AS ID ]]> 
    </selectKey>   
</insert>

这个你试过吗?如果直接在selectKey里面写插入语句是会报错的:
by: com.microsoft.sqlserver.jdbc.SQLServerException: 未能准备语句。
我现在也是被这个问题所困扰,用 @@IDENTITY 如果在同一事务内插入二个表,得到的结果不一定是你想要的,但用SCOPE_IDENTITY() 又没法用。不知道其它人是怎么解决。其实网上很多例子是这样写的。
<!-- Microsoft SQL Server IDENTITY Column 改进-->   
<insert id="insertProduct-MS-SQL" parameterClass="com.domain.Product">  
insert into PRODUCT (PRD_DESCRIPTION) values(#description#) 

    <selectKey resultClass="int" keyProperty="id">   
        <![CDATA[        SELECT SCOPE_IDENTITY() AS ID ]]> 
    </selectKey>   
</insert>

但实际这样就把它当二条语句执行了。依旧得不到ID。按你的方法又会报错。怎么办???请楼下的给出解答。我这边IE有问题,没法用UBB。还请见谅
3 楼 penghao122 2008-07-23  
单独写一个主键生成器啦。没有配置那么麻烦
2 楼 snowolf 2008-07-20  
tibetjungle 写道
snowolf 写道
iBatis的sqlMap配置文件的selectKey元素有个type属性,可以指定pre或者post表示前生成还是后生成。


<!-- Mysql Last Insert Id -->
<insert id="insertProduct-Mysql" parameterClass="com.domain.Product">
<![CDATA[insert into PRODUCT(PRD_DESCRIPTION) values (#description#)]]> 
<selectKey resultClass="int" keyProperty="id">
<![CDATA[SELECT LAST_INSERT_ID() AS ID ]]> <!-- 该方法LAST_INSERT_ID()与数据库连接绑定,不会发生上述MS SQL Server的函数问题。 -->
</selectKey>
</insert>


通过以上方式,可以最大程度上确保插入数据的时候获得当前自增主键。



mysql中不是可以用auto_increment吗?为什么要这样在ibatis中用?ms sql中也有identity可以用啊,干吗用这么麻烦的方法?如果是为了兼容其他数据库,还是可以考虑。

可能我没有说清楚,我要在插入表的时候获得的当前的主键,自增是有的。如果你要再插入动作的时候获得,一般都怎么做呢?
1 楼 tibetjungle 2008-07-19  
snowolf 写道
iBatis的sqlMap配置文件的selectKey元素有个type属性,可以指定pre或者post表示前生成还是后生成。


<!-- Mysql Last Insert Id -->
<insert id="insertProduct-Mysql" parameterClass="com.domain.Product">
<![CDATA[insert into PRODUCT(PRD_DESCRIPTION) values (#description#)]]> 
<selectKey resultClass="int" keyProperty="id">
<![CDATA[SELECT LAST_INSERT_ID() AS ID ]]> <!-- 该方法LAST_INSERT_ID()与数据库连接绑定,不会发生上述MS SQL Server的函数问题。 -->
</selectKey>
</insert>


通过以上方式,可以最大程度上确保插入数据的时候获得当前自增主键。



mysql中不是可以用auto_increment吗?为什么要这样在ibatis中用?ms sql中也有identity可以用啊,干吗用这么麻烦的方法?如果是为了兼容其他数据库,还是可以考虑。

相关推荐

Global site tag (gtag.js) - Google Analytics