zoukankan      html  css  js  c++  java
  • 关于iBatis-selectKey的一点笔记

    技术前提:我们使用iBatis作为持久层方案 

    技术场景: 
        假设我们有两张表,一张主表Main,一张子表Sub,并且主表的主键是由数据库维护的自增长的主键,子表中有一个字段引用这个主键,那么当我们插入主表数据后,就需要马上返回这个自增长的主键。 

    解决方案: 
        可以在insert时通过iBatis的selectKey返回那个主键。 
        selectKey有3个主要的属性: 
        1)resultClass:返回的主键的数据类型,跟sqlMap中的数据类型一致; 
        2)type:表示主键在insert之前或之后生成(取决于数据库的主键生成策略),取值分别为[pre|post],非必须,未填写时如果在insert之前表示pre,否则表示post; 
        2)keyProperty:返回值保存到的属性,非必须(作用参见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#) 
    <!-- 此处体现了keyProperty的作用 -->  
        ]]>    
    </insert>  

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

    <!-- DB2 Identity Val Local -->  
    <insert id="insertProduct-DB2" parameterClass="com.domain.Product"> 
        insert into PRODUCT(PRD_DESCRIPTION) values(#description#) 
        <selectKey resultClass="int" type="post"> 
            VALUES IDENTITY_VAL_LOCAL() 
        </selectKey> 
    </insert> 

    <!-- Sqlite sqlite_sequence -->  
    <insert id="insertProduct-Sqlite" parameterClass="com.domain.Product"> 
        insert into PRODUCT(PRD_DESCRIPTION) values(#description#) 
        <selectKey resultClass="string" type="post"> 
            SELECT seq FROM sqlite_sequence WHERE name = 'PRD_DESCRIPTION' 
        </selectKey> 
    </insert> 
    <!-- 主键字段一定要加下INTEGER PRIMARY KEY AUTOINCREMENT,否则会报找不到 sqlite_sequence 表。 --> 


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

  • 相关阅读:
    ubuntu下android开发工作环境搭建
    ADB命令行控制界面开关
    chromium os系统编译与环境搭建
    完整代理的简单实现
    OC协议、代理的简单使用
    OC字典的使用
    OC数组的简单使用、NSArray
    OC中NSString的使用、字符串的使用
    OC内存管理、非ARC机制、MRR机制
    OC中重写set和get方法、懒加载
  • 原文地址:https://www.cnblogs.com/google4y/p/3502807.html
Copyright © 2011-2022 走看看