MyBatis 学习(四)之 SQL 映射文件

目录

[1 SQL 映射文件介绍](#1 SQL 映射文件介绍)

[2 select 元素](#2 select 元素)

[3 insert 元素](#3 insert 元素)

[4 update 和 delete 元素](#4 update 和 delete 元素)

[5 sql 元素](#5 sql 元素)

[6 parameterType 元素](#6 parameterType 元素)

[7 resultType 元素](#7 resultType 元素)

[8 resultMap 元素(重要)](#8 resultMap 元素(重要))

[9 参考文档](#9 参考文档)


1 SQL 映射文件介绍

映射器是 MyBatis 中最复杂并且是最重要的组件。它由一个接口和 SQL 映射文件(或者注解)组成。在映射器中我们可以配置各类 SQL、动态 SQL、缓存、存储过程、级联等复杂的内容。

以下是 SQL 映射文件的部分元素介绍

元素 描述
cache 该命名空间的缓存配置
cache-ref 引用其它命名空间的缓存配置
resultMap 描述如何从数据库结果集中加载对象,它是最复杂也是最强大的元素
sql 可被其它语句引用的可重用语句块
select 映射查询语句
insert 映射插入语句
update 映射更新语句
delete 映射删除语句

2 select 元素

select 元素表示 SQL 的 select 语句,用于查询,以下是 select 元素的部分属性

属性 描述
id 在命名空间中唯一的标识符,可以被用来引用这条语句
parameterType 将会传入这条语句的参数类的全类名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler) 推断出具体传入语句的参数,默认值为未设置(unset)
resultType 从这条语句中返回的期望类型的类的全类名或别名。 注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。可以使用 resultType 或 resultMap,但不能同时使用
resultMap 外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂映射的情形都能迎刃而解。可以使用 resultMap 或 resultType,但不能同时使用
flushCache 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false
useCache 将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true
timeout 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖驱动)
fetchSize 这是一个给驱动的提示,尝试让驱动程序每次批量返回的结果行数和这个设置值相等。 默认值为未设置(unset)(依赖驱动)
statementType STATEMENT,PREPARED 或 CALLABLE 中的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED
resultSetType FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset) 中的一个,默认值为 unset (依赖驱动)
databaseId 如果配置了数据库厂商标识 (databaseIdProvider) 并且存在两个相同的语句,一个带 databaseId 而另一个不带,MyBatis 会优先加载带有 databaseId 的语句。如果 databaseId 与当前数据库匹配,则不带 databaseId 的相同语句将被忽略。未设置 databaseId 使用通用 SQL 规则
resultOrdered resultOrdered:这个设置仅对嵌套结果 select 语句适用:如果为 true,就是假设包含了嵌套结果集或是分组,这样的话当返回一个主结果行的时候,就不会发生有对前面结果集的引用的情况。 这就使得在获取嵌套的结果集的时候不至于导致内存不够用。默认值:false
resultSets 这个设置仅对多结果集的情况适用。它将列出语句执行后返回的结果集并给每个结果集一个名称,名称是逗号分隔的

3 insert 元素

属性 描述
id 在命名空间中唯一的标识符,可以被用来引用这条语句
parameterType 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)
flushCache 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true
timeout 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)
statementType 可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED
useGeneratedKeys (仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false
keyProperty (仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。不能和keyColumn连用
keyColumn (仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。不能和keyProperty连用
databaseId 同 select 元素

主键回填

在 MyBatis 中,若表中的主键设置为自增,插入数据时没有插入主键,但是又想获得数据库中该条数据的主键,那么可以通过设置 useGeneratedKeys="true",然后再把 keyProperty 设置到目标属性(如 User 类中的 id 属性)上来获得该值。

XML 复制代码
<insert id="insertUser" parameterType="com.entity.User" useGeneratedKeys="true" keyProperty="id">
        insert into person(name, age, sex)
        values (#{name}, #{age}, #{sex});
</insert>
java 复制代码
//添加一个用户数据
@Test
public void testInsertUser() {
    String statement = "com.mapper.UserMapper.insertUser";
    User user = new User();
    user.setName("孙尚香");
    user.setAge(24);
    user.setSex("女");
    int i = sqlSession.insert(statement, user);
    System.out.println( (i>0)? "添加成功!":"添加失败!");
    //提交插入的数据
    sqlSession.commit();
    sqlSession.close();
    // 输出返回的主键值
    System.out.println("返回的主键值=" + user.getId());
}

自定义主键并且可以在 Java 中通过属性获得该值

在 MyBatis 中可以通过 selectKey 元素自定义主键,以下是其属性介绍

  • keyProperty:selectKey 需要设置的目标属性
  • resultType:结果类型
  • order:可以设置为 BEFORE 或 AFTER ,表示先设置主键,后执行插入语句或先执行插入语句,后设置主键
XML 复制代码
<insert id="insertUser" parameterType="com.entity.User" >
    <selectKey keyProperty="id" resultType="int" order="BEFORE">
        select ROUND(RAND()*1000)
    </selectKey>
    insert into person(id, name, age, sex)
    values (#{id}, #{name}, #{age}, #{sex});
</insert>
java 复制代码
@Test
public void testInsertUser() {
    String statement = "com.mapper.UserMapper.insertUser";
    User user = new User();
    user.setName("郑旦");
    user.setAge(24);
    user.setSex("女");
    int i = sqlSession.insert(statement, user);
    System.out.println( (i>0)? "添加成功!":"添加失败!");
    //提交插入的数据
    sqlSession.commit();
    sqlSession.close();
    // 输出返回的主键值
    System.out.println("返回的主键值=" + user.getId());
}

4 update 和 delete 元素

update 和 delete 元素在使用上比较简单,所以这里把它们放在一起论述。它们和 insert 元素的属性差不多,执行完后也会返回一个整数,用来表示该 SQL 语句影响了多少条数据库记录。

XML 复制代码
<!-- 根据 id 更新用户 -->
<update id="updateUser">
    update person set name = #{name},
                      age = #{age},sex = #{sex} where id = #{id}
</update>
<!-- 根据 id 删除用户 -->
<delete id="deleteUser" parameterType="int">
    delete from person where id = #{id}
</delete>

5 sql 元素

sql 元素是用来定义可重用的 sql 代码片段,这样在字段比较多的时候,以便在其它语句中使用。需要结合 include 元素一起使用,以下是代码示例。

XML 复制代码
<!--定义sql代码片段-->
<sql id="userCols">
    id,username,age,sex
</sql>
<!-- 查询所有用户 -->
<select id="selectAllUser" resultType="com.entity.User">
    select <include refid="userCols"/> from person
</select>

6 parameterType 元素

parameterType 元素可以输入以下类型:

  • Java 基本数据类型
  • POJO 类型
  • Map 类型
XML 复制代码
<!-- 通过 普通数据类型 int 查询一个用户 -->
<select id="selectUserById" parameterType="int" resultType="com.entity.User">
    select * from person where id = #{id};
</select>

<!-- 通过 POJO 类型 User 添加用户-->
<insert id="insertUser" parameterType="com.entity.User">
    insert into person(id,username,age,sex) values (#{id},#{username},#{age},#{sex});
</insert>
 
<!-- 通过 嵌套 POJO 类型 查询一个用户,QueryVo 类中定义了 User user 属性 -->
<select id="selectUserByUserNameAndAge" parameterType="com.entity.QueryVo" resultType="com.entity.User">
    select * from person where name = #{user.name} and age = #{user.age};
</select>

<!-- 通过 Map 类型 查询一个用户, HashMap<String, Object> map = new HashMap<>(); 
map.put("name","赵飞燕"); map.put("age",24); 通过 key 获得 map 中的 value-->
<select id="selectUserByMap" parameterType="hashmap" resultType="com.entity.User">
    select * from person where name = #{name} and age = #{age};
</select>

7 resultType 元素

resultType 元素和 parameterType 元素用法差不多,一个是输出,一个是输入。resultType 元素可以输出以下类型:

  • Java 基本数据类型
  • POJO 对象
  • POJO 对象列表
  • Map 对象列表
XML 复制代码
<!-- 统计用户总数量,输出为一个整数 int -->
<select id="countUsers" resultType="int">
    select count(1) from person
</select>

<!-- 通过 id 查询一个用户,输出为一个 User -->
<select id="selectUserById" parameterType="int" resultType="com.entity.User">
    select * from personwhere id = #{id};
</select>

<!-- 查询所有用户,输出为一个 List<User> 列表 -->
<select id="selectAllUser" resultType="com.entity.User">
    select * from person
</select>

<!-- 查询所有用户, 输出为一个 List<HashMap<String, Object>> Map 列表-->
<select id="selectAllUser" resultType="hashmap">
    select * from person
</select>

8 resultMap 元素(重要)

我们在使用 resultType 的时候,需要保证数据库表中的字段名和表对应实体类的属性名称一致才行(包括驼峰命名规则)。那不一致怎么办,查询的时候可以给列名起个别名,但是一般不建议这样做,而是通过 resultMap 元素进行一个转换。

XML 复制代码
<!-- id:唯一标识,type:需要映射的 Java 类型-->
<resultMap id="userMap" type="com.entity.User">
    <!-- 与主键字段的对应,property对应实体属性,column对应表字段 -->
    <id property="userId" column="id"/>
    <!-- 与非主键字段的对应,property对应实体属性,column对应表字段 -->
    <result property="userName" column="username"/>
    <result property="userAge" column="age"/>
    <result property="userSex" column="sex"/>
</resultMap>

<!-- 查询所有用户,返回集为resultMap类型,resultMap的value上面配置的 id=userMap 要一致-->
<select id="selectAllUser" resultMap="userMap">
    select * from person
</select>

上述代码是不是很眼熟,在 MyBatis 案例中使用了 @ResultMap 注解来实现上述代码

resultMap 元素的组成

XML 复制代码
<!-- autoMapping:指定是否自动映射查询结果的列到 Java 对象的属性。
默认为开启(true),如果设置为 false,则需要手动配置每个属性的映射关系 -->
<resultMap id="标识" type="输出类型" extends="继承其他 <resultMap>" autoMapping="自动映射">
    <constructor><!--构造器注入属性值-->
        <!-- 构造器标识,一般为主键 -->
        <!-- column对应表字段,name对应实体属性 -->
        <idArg column="id" name="userId" javaType="int"/>
        <!-- 构造器参数 -->
        <arg column="username" name="userName" javaType="string"/> 
    </constructor>
        <!-- id 与主键字段的对应,property对应实体属性,column对应表字段 -->
        <id property="userId" column="id"/>
        <!-- result 与非主键字段的对应,property对应实体属性,column对应表字段 -->
        <result property="userName" column="username"/>
    <association/><!--高级映射,一对一映射-->
    <collection /><!--高级映射,一对多映射-->
    <discriminator>
        <case/>
    </discriminator><!--根据返回的字段的值封装不同的类型-->
</resultMap>

9 参考文档

Mybatis3详解(四)----SQL映射文件详解(XxxMapper.xml) - 唐浩荣 - 博客园 (cnblogs.com)

相关推荐
014-code18 小时前
Spring Boot 自动配置原理深度解析
java·spring boot·后端·spring
康小庄18 小时前
JVM学习——Gc Roots
java·jvm·spring boot·学习·spring
sdanss18 小时前
Spring Boot接收参数的19种方式
java·spring boot·后端
金銀銅鐵18 小时前
Byte Buddy 生成的类的结构如何?(第一篇)
java·后端
sxhcwgcy18 小时前
Spring Cloud GateWay搭建
java
umeelove3518 小时前
Spring框架
java·后端·spring
baizhigangqw18 小时前
SpringBoot中整合ONLYOFFICE在线编辑
java·spring boot·后端
pangares18 小时前
Spring Boot文件上传
java·spring boot·后端
zhglhy18 小时前
Java分布式链路技术
java·分布式·分布式链路
1candobetter18 小时前
JAVA后端开发——如何在多层代理环境下实现稳定的签名算法:Host 与端口问题解析
java·开发语言