MyBatis insert

1. 前言

本小节,我们将一起学习 MyBatis insert。

在 MyBatis 中,insert 标签对应于 SQL 语句中的 insert 插入;与 select 相比,insert 要简单许多,只有当需要返回主键时,才会麻烦一些,我们将从简单到复杂来依次介绍。

2. 定义

慕课解释:insert 标签用于映射 SQL 中的插入语句

3. 实例

3.1 xml 实例

下面是一个简单的 insert 标签。

<insert id="insertUser" parameterType="com.imooc.mybatis.model.User">
  INSERT INTO imooc_user(id,username,age,score) VALUES (#{id},#{username},#{age},#{score})
</insert>

同 select 一样,每一个 insert 标签都必须有一个唯一的 id 和可选的 parameterType。标签里面则是真正的 SQL 语句,该语句共有 4 个参数,分别对应 User 类的四个属性。

3.2 注解实例

如果不使用 xml 的方式,使用注解也可取得同样的效果,如下:

@Insert("INSERT INTO imooc_user(username,age,score) VALUES (#{username},#{age},#{score})")
int insertUser(User user);

4. insert 属性

insert 标签也支持诸多属性来改变语句的行为。

其中常见且重要的属性如下表:

属性 描述
id 在命名空间中的唯一标识符
parameterType 语句的参数类型,默认可选,MyBatis 会自动推断
flushCache 设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认为 false
timeout 设置超时时间
statementType STATEMENT,PREPARED 或 CALLABLE 中的一个,默认为 PREPARED(预处理)
useGeneratedKeys 取出由数据库自动生成的主键,仅对支持主键自动生成的数据库有效,默认为 false
keyProperty 主键的名称,必须与useGeneratedKeys 一起使用,默认未设置

5. 返回主键

select 标签在需要返回被添加记录的主键时,会稍微复杂一点。

5.1 自增主键

5.1.1 xml 方式

如果使用的数据库,如 MySQL,PostgreSQL,这些数据库支持自增主键,那么得到返回的主键只需添加上 useGeneratedKeys 和 keyProperty 两个属性即可。如下:

<insert id="insertUserNoId" useGeneratedKeys="true" keyProperty="id"
        parameterType="com.imooc.mybatis.model.User">
  INSERT INTO imooc_user(username,age,score) VALUES (#{username},#{age},#{score})
</insert>

在 insertUserNoId 中,我们并未添加上 id 参数,而是使用了数据库自增主键的特性,keyProperty 属性值对应 id 字段的名称,这样当语句执行成功后,对象的 id 字段会被自动设置为返回的 id 值。

5.1.2 注解方式

使用下面的注解方式,同样可以实现同样的效果:

@Insert("INSERT INTO imooc_user(username,age,score) VALUES (#{username},#{age},#{score})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insertUser(User user);

MyBatis 提供了 Options 注解来指定方法调用的行为。

5.2 selectKey 标签

5.2.1 xml 方式

如果使用的数据库不支持主键自增,如 Oracle,MyBatis 提供了 selectKey 标签来通过 SQL 语句获得主键。

例如:

<insert id="insertUserNoId" parameterType="com.imooc.mybatis.model.User">
  INSERT INTO imooc_user(username,age,score) VALUES (#{username},#{age},#{score})
  <selectKey keyColumn="id" resultType="long" keyProperty="id" order="AFTER">
    SELECT LAST_INSERT_ID()
  </selectKey>
</insert>

selectKey 标签必须在 insert 标签里面,selectKey 有 4 个属性,它们的作用如下表:

属性 描述
keyColumn 数据库字段名,对应返回结果集中的名称
keyProperty 目标字段名称,对应Java 对象的字段名
resultType id字段的类型
order 执行的顺序,在 insert 之前调用为 BEFORE,之后为 AFTER

注意,selectKey 中的语句其实就是 SQL 语句,不同数据库得到主键的语句均不一样。

5.2.2 注解方式

@Insert("INSERT INTO imooc_user(username,age,score) VALUES (#{username},#{age},#{score})")
@SelectKey(statement = "SELECT LAST_INSERT_ID()", keyProperty = "id", before = false, resultType = Long.class)
int insertUser(User user);

selectKey 也有相应的注解,不过配置属性略有不同,statement 属性对应标签中的 SQL 语句,而 before 属性则对应标签中的 order 属性,若 before 为 false,则 order 对应为 AFTER。

6. 实践

下面,我们一起来实操巩固一下。

6.1 例1. 插入用户

请使用 MyBatis 完成在 imooc_user 表中插入用户的功能。

分析:

按照 MyBatis 的开发模式,先在对应 UserMapper.xml 文件中添加插入用户的 insert 标签,然后在 UserMapper.java 中增加上对应的方法即可。

步骤:

使用 MyBatis 向数据库中插入用户。由于我们使用的数据库是 MySQL,因为直接使用 useGeneratedKeys 得到自增主键。

首先,我们在 UserMapper.xml 文件中添加上对应的 insert 标签:

<insert id="insertUser" useGeneratedKeys="true" keyProperty="id"
        parameterType="com.imooc.mybatis.model.User">
  INSERT INTO imooc_user(username,age,score) VALUES (#{username},#{age},#{score})
</insert>

然后在 UserMapper.java 中添加对应的方法:

package com.imooc.mybatis.mapper;

import com.imooc.mybatis.model.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper {
  int insertUser(User user);
}

结果:

通过如下代码,我们运行 insertUser 方法:

UserMapper userMapper = session.getMapper(UserMapper.class);
User user = new User();
user.setUsername("insert test");
user.setAge(100);
user.setScore(100000);
int rows = userMapper.insertUser(user);
System.out.println(rows);
// 一定要提交
session.commit();
session.close();

TIPS: 注意,这里必须通过 commit 方法提交会话,语句才会生效。

7. 小结

  • 绝大多数情况下,我们都不会在插入时指定 id 的值,而是通过数据库自动去生成。
  • 不同数据库获得主键的 SQL 语句也不同,如果通过 selectKey 获得主键,那么一定要注意数据库厂商之间的差异性。