Mybatis 示例之 SelectKey
SelectKey 在 Mybatis 中是为了解决 Insert 数据时不支持主键自动生成的问题,他可以很随意的设置生成主键的方式。
不管 SelectKey 有多好,尽量不要遇到这种情况吧,毕竟很麻烦。
属性 | 描述 |
---|---|
keyProperty | selectKey 语句结果应该被设置的目标属性。 |
resultType | 结果的类型。MyBatis 通常可以算出来, 但是写上也没有问题。MyBatis 允许任何简单类型用作主键的类型, 包括字符串。 |
order | 这可以被设置为 BEFORE 或 AFTER。如果设置为 BEFORE, 那么它会首先选择主键, 设置 keyProperty 然后执行插入语句。如果设置为 AFTER, 那么先执行插入语句, 然后是 selectKey 元素 - 这和如 Oracle 数据库相似, 可以在插入语句中嵌入序列调用。 |
statementType | 和前面的相 同,MyBatis 支持 STATEMENT ,PREPARED 和 CALLABLE 语句的映射类型, 分别代表 PreparedStatement 和 CallableStatement 类型。 |
SelectKey 需要注意 order 属性,像 Mysql 一类支持自动增长类型的数据库中,order 需要设置为 after 才会取到正确的值。
像 Oracle 这样取序列的情况,需要设置为 before,否则会报错。
另外在用 Spring 管理事务时,SelectKey 和插入在同一事务当中,因而 Mysql 这样的情况由于数据未插入到数据库中,所以是得不到自动增长的 Key。取消事务管理就不会有问题。
下面是一个 xml 和注解的例子,SelectKey 很简单,两个例子就够了:
上面 xml 的传入参数是 map,selectKey 会将结果放到入参数 map 中。用 POJO 的情况一样,但是有一点需要注意的是,keyProperty 对应的字段在 POJO 中必须有相应的 setter 方法,setter 的参数类型还要一致,否则会报错。
@Insert("insert into table2 (name) values(#{name})") @SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class) int insertTable2(Name name);
上面是注解的形式。
在使用 ibatis 插入数据进数据库的时候,会用到一些 sequence 的数据,有些情况下,在插入完成之后还需要将 sequence 的值返回,然后才能进行下一步的操作。
使用 ibatis 的 selectKey 就可以得到 sequence 的值,同时也会将值返回。不过对于不同的数据库有不同的操作方式。
对于 oracle:
<insert id="insertUser" parameterClass="ibatis.User"> <selectKey resultClass="long" keyProperty="id"> select SEQ_USER_ID.nextval as id from dual </selectKey> insert into user (id,name,password) values (#id#,#name#,#password#) </insert>
该句话执行完之后,传进来的参数 User 对象 DO 里的 id 字段就会被赋值成 sequence 的值。
对于 mysql
<insert id="insertUser" parameterClass="ibatis.User"> insert into user (name,password) values (#name#,#password#) <selectKey resultClass="long" keyProperty="id"> SELECT LAST_INSERT_ID() AS ID </selectKey> </insert>
将 selectKey 放在 insert 之后,通过 LAST_INSERT_ID() 获得刚插入的自动增长的 id 的值。