MyBatis 入门 (三)

Use Insert

为方便理解,本章涉及示例代码已上传至 gitee
==>获取示例代码请点击这里。。。
拉取示例代码时,请拉取所有分支,master 分支只是做了示例的初始化

首先先来实现一个简单的 Insert 查询:

public interface SysUserMapper {
    // other methods ...
    Integer insertInfo(SysUser sysUser);
}
<insert id="insertInfo" parameterType="SysUser" >
        insert into sys_user(
                id,
                user_name,
                user_password,
                user_info,
                user_email,
                head_img,
                create_time
            )
       value
            (
             #{id},
             #{userName},
             #{userPassword},
             #{userInfo},
             #{userEmail},
             #{headImg,jdbcType = BLOB},
             #{createTime,jdbcType = TIMESTAMP}
            );
</insert>

介绍一下 insert 标签里的属性:

  • id : 命名空间中的唯一标识符,同 select 标签的 ID 属性性质相同
  • parameterType : 传入参数的完全限定名或别名,可选
  • flushCahe : 默认值为 true,表示当该条语句被调用,都会清空 MyBatis 的一级和二级缓存
  • timeout : 设置在抛出异常之前,驱动程序等待数据库返回请求结果的秒数
  • statementType : 对于 statement、prepared、callable,MyBatis 会分别使用对应的 Statement、PreparedStatment、CallableStatement,默认值是 Prepared
  • useGeneratedKeys : 默认值为 false,如果设置为 true,MyBatis 会使用 JDBC 的 getGeneratedKeys() 方法取出数据库内部生成的主键
  • keyPreparty : MyBatis 通过 JDBC 的 getGeneratedKeys() 方法获取主键后,将要赋值的实体类属性名;如果希望得到多个数据库自动生成的列,属性值是以逗号分隔的属性名称列表
  • keyColumn : 仅对 Insert 和 Update 有用,该设置仅在某些数据库中必须(PostgreSQL),当主键列不是表中的第一列时需要设置,如果希望得到多个生成的列, 也可以是逗号分隔的属性名称列表
  • databaseId : 如果配置了 databaseIdProvider (后续会介绍该属性的详细情况),MyBatis 会加载所有的不带 databaseId 的或匹配当前 databaseId 的语句,如果同时存在带 databaseId 和不带 databaseId 的语句,后者会被忽略

介绍完 insert 标签的属性,再来说一下使用 insert 标签最常用的返回插入数据的主键自增值:

  1. 使用 JDBC 方式返回主键自增值(注:该方式只适用于主键自增的数据库)
    在项目中新增如下代码:
public interface SysUserMapper {
    // other methods ...
    Integer insertInfoNotId(SysUser sysUser);
}
<insert id="insertInfoNotId" parameterType="SysUser" useGeneratedKeys="true" keyProperty="id">
        insert into sys_user(
                            user_name,
                            user_password,
                            user_info,
                            user_email,
                            head_img,
                            create_time
                            )
                    value
                            (
                            #{userName},
                            #{userPassword},
                            #{userInfo},
                            #{userEmail},
                            #{headImg,jdbcType = BLOB},
                            #{createTime,jdbcType = TIMESTAMP}
                            );
</insert>

通过与 insert id=“insertInfo” 对比,发现 insert id=“insertInfoNotId” 只是新增了两个属性:useGeneratedKeys=“true” keyProperty=“id” ;这两个属性的设置表示:MyBatis 会使用 JDBC 的 getGeneratedKeys() 方法来取出由数据库内部生成的主键,获得主键值后,将其赋值给 keyProperty 配置的 id 属性,当需要设置多个属性时,使用逗号隔开,这种情况下还需要设置 keyColumn 属性,keyColumn 设置的数据库列名与 keyProperty 配置的属性一一对应。

大概说一下 MyBatis 通过 JDBC 获取自增主键的流程:
在这里插入图片描述
PreparedStatementHandler 类的 update(Statement statement) 方法源码如下:

@Override
public int update(Statement statement) throws SQLException {
    PreparedStatement ps = (PreparedStatement) statement;
    ps.execute();
    int rows = ps.getUpdateCount();
    Object parameterObject = boundSql.getParameterObject();
    KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
    keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
    return rows;
}

关键的获取数据库生成的主键的步骤就在

keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);

方法中,有兴趣的可以打断点进去跟着走一遍这里只贴出关键的步骤:

Jdbc3KeyGenerator.class
 
private void populateKeys(ResultSet rs, MetaObject metaParam, String[] keyProperties, TypeHandler<?>[] typeHandlers) throws SQLException {
    for (int i = 0; i < keyProperties.length; i++) {
      String property = keyProperties[i];
      TypeHandler<?> th = typeHandlers[i];
      if (th != null) {
        // 具体的获取 数据库生成的 主键代码 
        Object value = th.getResult(rs, i + 1);
        metaParam.setValue(property, value);
      }
    }
  }

之后,便能可以查看到实体对象的 id 属性的值了。

  1. 使用 selectKey 标签返回主键的值(不论数据库是否提供主键自增功能,均适用)
public interface SysUserMapper {
    // other methods ...
    Integer insertUseSelectKey(SysUser sysUser);
}
<insert id="insertUseSelectKey" parameterType="SysUser" useGeneratedKeys="true" keyProperty="id">
	insert into sys_user(user_name,user_password,user_info,user_email,head_img,create_time)
	value(#{userName},#{userPassword},#{userInfo},#{userEmail},#{headImg,jdbcType = BLOB},#{createTime,jdbcType = TIMESTAMP});
    <selectKey keyProperty="id" keyColumn="id" order="AFTER" resultType="long">
        <!-- 用于获取数据库中最后插入的数据的 ID 值 -->
    	select last_insert_id()
    </selectKey>
</insert>

介绍一下 selectKey 标签中的属性值:

  • keyColumn 和 keyProperty 与 useGenertedKeys 中的用法相同
  • resultType : 用于设置返回值类型
  • order : 根据数据库种类不同而不同,MySQL 数据库,设置为 after,Oracle 数据库设置为 before
    • MySQL 数据库中当前记录的主键值只有在 insert 语句执行完后才能获得,所以 order = “after”
    • Oracle 数据库中则需要先从序列获取值,然后将值作为主键插入,所以 order = “before” ;并且 insert 的 sql 语句中明确写出 id 字段和值,如果 sql 中没有 明确写出 id 字段和值,则有可能会因为主键不能为空而抛出异常

selectKey 标签的执行流程和 useGenertedKeys 相同,只不过

keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);

中 keyGenerator 属性的实例变成了 SelectKeyGenerator 类型,在 SelectKeyGenerator 的

processGeneratedKeys(Executor executor, MappedStatement ms, Object parameter);

方法中,会有如下的代码段:

List<Object> values = keyExecutor.query(keyStatement, parameter, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);

它会去执行 selectKey 标签中的 SQL 语句 : select last_insert_id();以获得最后一次插入的数据的 id 值。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值