MyBatis教程[7]----xml映射配置补充

本篇文章针对前面没有讲到的XML映射配置文件做一个补充说明。

1. selectKey自动生成主键

对于不支持自动生成主键列的数据库和可能不支持自动生成主键的 JDBC 驱动,MyBatis 有另外一种方法来生成主键。

这里有一个简单(也很傻)的示例,它可以生成一个随机 ID(不建议实际使用,这里只是为了展示 MyBatis 处理问题的灵活性和宽容度):

<insert id="insert">
    <selectKey keyProperty="id" resultType="int" order="BEFORE">
        SELECT FLOOR(RAND()*10000) AS id
    </selectKey>
    INSERT INTO `user`(`id`,`name`, `phone`, `birthday`) VALUES (#{id}, #{u.name}, #{u.phone}, #{u.birthday})
</insert>

单元测试:

@Test
void insert() throws ParseException {
    User user = new User();
    user.setName("啊随");
    user.setPhone("11111111111");
    user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1996-07-18"));

    userMapper.insert(user);
}

运行结果:
在这里插入图片描述
并不建议这样做,毕竟绝大多数数据库都有自增主键的功能,不需要更没必要自动生成一个随机数来当作id。这里只是演示一下selectKey标签还有这种用法。

属性 描述
keyProperty selectKey 语句结果应该被设置到的目标属性。如果生成列不止一个,可以用逗号分隔多个属性名称。
keyColumn 返回结果集中生成列属性的列名。如果生成列不止一个,可以用逗号分隔多个属性名称。
resultType 结果的类型。通常 MyBatis 可以推断出来,但是为了更加准确,写上也不会有什么问题。MyBatis 允许将任何简单类型用作主键的类型,包括字符串。如果生成列不止一个,则可以使用包含期望属性的 Object 或 Map。
order 可以设置为 BEFORE 或 AFTER。如果设置为 BEFORE,那么它首先会生成主键,设置 keyProperty 再执行插入语句。如果设置为 AFTER,那么先执行插入语句,然后是 selectKey 中的语句 - 这和 Oracle 数据库的行为相似,在插入语句内部可能有嵌入索引调用。
statementType 和前面一样,MyBatis 支持 STATEMENT,PREPARED 和 CALLABLE 类型的映射语句,分别代表 Statement, PreparedStatement 和 CallableStatement 类型。

2. 返回主键id

在实际应用中,常常需要返回insert语句的主键id。配置起来很简单,只需:

  • 指定insert标签的useGeneratedKeys属性为true
  • 指定insert标签的keyProperty属性所对应的实体类的属性名
  • 指定insert标签的keyColumn属性所对应的数据表的字段名
<insert id="insertAndGetId" parameterType="com.yky.springboot.entities.User" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
        INSERT INTO `user`(`name`, `phone`, `birthday`) VALUES (#{u.name}, #{u.phone}, #{u.birthday})
</insert>

返回的主键id会直接注入到user对象中。

@Test
void insertAndGetId() throws ParseException {
    User user = new User();
    user.setName("id返回");
    user.setPhone("11111111111");
    user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1996-07-18"));

    userMapper.insertAndGetId(user);
    System.out.println(user.getId());
}

3. sql标签代码重用

可以使用sql标签将多个地方会用到的代码抽取出来。

<sql id="allColumn">
	`id`, `name`, `phone`, `birthday`
</sql>

直接使用include标签进行引用

<select id="selectById" resultType="User" >
   SELECT 
        <include refid="allColumn"></include>
   FROM `user` WHERE id = #{id}
</select>

4. 占位符与字符串替换

前面我们用了很多次#{}占位符,默认情况下,使用 #{} 参数语法时,MyBatis 会创建 PreparedStatement 参数占位符,并通过占位符安全地设置参数(就像使用 ? 一样)。 这样做更安全,更迅速,通常也是首选做法,不过有时你就是想直接在 SQL 语句中直接插入一个不转义的字符串。这时就需要用到${}了。

比如:

ORDER BY ${columnName}

那什么时候用 ${} 呢?当SQL语句中的表名/列名需要动态生成时,则需要用到 ${}。因为表名/列名需要直接替换进SQL语句,而不能经过转义。

在这里举一个使用字符串替换的例子:

映射接口:

/**
 * 根据列名和改列所对应的值匹配
 * @param columnName 列名
 * @param value 值
 * @return
 */
List<User> selectByColumn(@Param("columnName") String columnName,@Param("value") String value);

xml映射配置:

<select id="selectByColumn" resultType="User">
    SELECT 
    <include refid="allColumn"></include>
    FROM `user`
    WHERE ${columnName} = #{value}
</select>

单元测试代码:

@Test
void selectByColumn() {
    List<User> users = userMapper.selectByColumn("name", "小明");

    System.out.println(users);
}

Mybatis不推荐我们这样做,因为这种用法会导致潜在的SQL注入攻击。如果非要这样用,推荐对输入的参数进行校验,以防止非法SQL语句被执行。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章