• Mybatis「MySQL-Oracle」 中主键自动生成 <selectKey> 序列化


    有时候我们不仅仅是通过返回 int 影响行数来确定数据是否插入成功就行了,因为我们总是会用到这个刚刚插入的自增主键,比如主子表入库,子表需要主表的 id,那这个时候我们再去数据库查就显得有点 low 了~

    关于数据库中主键的生成无非就两种,一种是 int 类型的自增,一种是 varchar 类型的非自增(例如:UUID)。

    Mybatis 中,提供了 selectKey 来帮我们获取新增的主键,同时通过 selectKey 可以很容易的实现自增还是非自增规则的需求。

    首先看一下 MybatisselectKey 的属性说明:

    属性描述
    keyProperty selectKey 语句结果应该被设置的目标属性(也就是自增的主键字段,比如id)。
    resultType 结果的类型,比如java.lang.Integer,java.lang.String等。MyBatis 通常可以算出来,但是写上也没有问题。MyBatis 允许任何简单类型用作主键的类型,包括字符串。
    order 这可以被设置为 BEFORE 或 AFTER。如果设置为 BEFORE,那么它会首先选择主键,设置 keyProperty 然后执行插入语句。如果设置为 AFTER,那么先执行插入语句,然后是 selectKey 元素-这和如 Oracle 数据库相似,可以在插入语句中嵌入序列调用。
    statementType 和前面的相同,MyBatis 支持 STATEMENT,PREPARED 和 CALLABLE 语句的映射类型,分别代表 PreparedStatement 和 CallableStatement 类型。

    下面从 OracleMySQL 分别举例说明。

    1. Oracle

    <insert id="insertUserInfo" parameterType="club.sscai.entity.UserInfo">
        <selectKey keyProperty="id" resultType="java.lang.Integer" order="BEFORE">
            select SEQ_T_USER_INFO.NEXTVAL from dual
        </selectKey>
        insert into "T_USER_INFO"
        <trim prefix="(" suffix=")" suffixOverrides=",">
            ID,USER_NAME,PASSWORD,PHONE,STATUS,
            <if test="remark != null">
                REMARK,
            </if>
            CREATE_TIME,UPDATE_TIME,UPDATE_BY
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            #{id,jdbcType=DECIMAL}, #{userName,jdbcType=VARCHAR},
            #{PASSWORD,jdbcType=VARCHAR},#{PHONE,jdbcType=VARCHAR},#{status,jdbcType=CHAR},
            <if test="remark != null">
                #{remark,jdbcType=VARCHAR},
            </if>
            #{createTime,jdbcType=TIMESTAMP},#{updateTime,jdbcType=TIMESTAMP}, #{updateBy,jdbcType=VARCHAR}
        </trim>
    </insert>

    如上代码主要是向 T_USER_INFO 表插入用户数据,parameterType 值传入的是实体对象,这里也可以是 map 或者是其他对象。

    其中 的 keyProperty 值对应生成主键的字段,resultType 表示要返回的主键的类型,在这里我用的 Integer 类型,你也可以用 String,只要跟实体的字段对应即可。order 属性需要注意一下,不同于支持自增类型的 MySQL 等数据库,Oracle 需要设置设置为 after 才能取到正确的值,但是如果要从序列化中取值,则需要设置为 befor,否则会报错,我上边的代码是从序列中取值所以设置为 befor

    标签内的 SEQ_T_USER_INFO 表示该表的序列化,关于创建表序列化代码如下(SEQ_T_USER_INFO 名称随便起,尽量规范即可):

    create sequence SEQ_T_USER_INFO
    minvalue 1
    maxvalue 9999999999999999999999999999
    start with 1
    increment by 1
    cache 20;

    字符串 uuid 类型非自增主键, selectKey 如下:

    <selectKey keyProperty="id" resultType="java.lang.String" order="BEFORE">
        select sys_guid() from dual
    </selectKey>

    2. MySQL

    <insert id="insertUserInfo" parameterType="club.sscai.entity.UserInfo" >
        <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.string">
            select uuid()
        </selectKey>
        insert into T_USER_INFO 
            (id, user_name, PASSWORD,PHONE,STATUS,REMARK,CREATE_TIME,UPDATE_TIME,UPDATE_BY)
        values 
        (#{id},#{userName},#{password},#{phone},#{status},省略...)
    </insert>

    上方是 MySQL 通过 select uuid() 就能得到 uuid 字符串,实现 UUID 字符串形式的主键生成。如果需要 int 类型则如下所示:

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

    至此,关于主键生成基本已经完事了,再额外补充关于 order = befor、after 的应用。

    如果你使用的是 UUID() 这种形式的,建议选择 order = befor,而 order = after 更适合返回自增(int)类型的主键。


    我创建了一个用来记录自己学习之路的公众号,感兴趣的小伙伴可以关注一下微信公众号:niceyoo

  • 相关阅读:
    异常处理
    面向对象 -- 内置方法
    面向对象 -- 反射(详细)
    面向对象 -- 反射
    面向对象 -- 三大特性之封装
    pickle模块 collections模块在面向对象中的应用
    面向对象 -- 三大特性之多态
    Third Week(补充完整)
    Second Week(补充完整)
    First Week (补充完整)
  • 原文地址:https://www.cnblogs.com/niceyoo/p/11979875.html
Copyright © 2020-2023  润新知