SQL映射文件就是我们通常说的mapper.xml配置文件,主要实现SQL语句的配置和映射,同时实现Java的POJO对象与数据库中的表和字段进行映射关联的功能。
下面就来详细介绍mapper.xml文件的结构。首先看一个完整的mapper.xml示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.StudentMapper">
<select id="selectAll" resultMap="BaseResultMap">
SELECT
*
FROM student
</select>
<resultMap id="BaseResultMap" type="com.example.demo.model.Student">
<id column="id" property="id" jdbcType="BIGINT" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="sex" property="sex" javaType="INTEGER" />
<result column="age" property="age" jdbcType="INTEGER" />
</resultMap>
</mapper>
如上述示例所示,一般mapper.xml主要分为4部分:
1)mapper.xml的语法声明,声明MyBatis语法。
2)通过namespace指明mapper.xml文件对应的Mapper接口。
3)通过XML标签定义接口方法对应的SQL语句,id属性对应Mapper接口中的方法,resultMap属性为返回值类型。
4)
标签定义返回的结果类型与数据库表结构的对应关系,上面映射的是Student实体类对象。
mapper.xml映射文件提供了一些非常实用的标签,其中比较常用的有resultMap、sql、insert、update、delete、select等标签。熟练掌握标签的使用,这样使用MyBatis才能如鱼得水。MyBatis标签和功能说明如表所示。
MyBatis提供了insert、update、delete和delete四个标签来定义SQL语句。接下来就从SQL语句开始介绍每个标签的用法。
select是MyBatis常用的元素之一,MyBatis在查询和结果映射中做了相当多的改进。一个简单查询的select元素是非常简单的,比如:
<select id="selectOne" resultType="hashmap" parameterType="Long">
SELECT name,age FROM student WHERE id = #{id}
</select>
在上面的示例中,通过id查询学生的姓名和年龄。定义方法名为selectOne,接收一个Long类型的参数,并返回一个HashMap类型的对象。HashMap的键是列名,值是结果集中的对应值。#{id}为传入的参数符号。
select标签允许配置很多属性来配置每条语句的行为细节,比如参数类型、返回值类型等,包含的属性如表所示。
属性 | 说明 |
---|---|
id | 命名空间中唯一的标识符,被用来引用这条语句 |
parameterType | 将传入语句的参数的数据类型,可选。因为 MyBatis 可以通过类型处理程序(TypeHandler)推断出传入语句的参数的数据类型,默认值为未设置 (unset) |
resultType | 返回结果的数据类型。注意,如果返回的是集合,那么应该设置为集合包含的类型,而不是集合本身的类型。resultType 和 resultMap 之间只能使用一个 |
resultMap | 结果映射, resultMap 是 MyBatis 的强大特性之一, resultType 和resultMap 之间只能使用一个 |
flushCache | 是否清空缓存,Select 语句默认值为 false,如果设置为 true,只要语句被调用,将清空本地缓存和二级缓存 |
useCache | 是否使用缓存,默认值为 tue,缓存本条语句的查询结果 |
timeout | 超时时间,等待数据库返回请求结果的时间。默认值为未设置 (unset) |
fetchSize | 设置返回的结果行数。默认值为未设置 (unset) |
statementType | 使用 Statement、PreparedStatement或CallableStatement执行SQL 语句,默认值为PREPARED |
resultSetType | FORWARD_ONLY、SCROLL_SENSITIVE、SCROLL_INSENSITIVE 或 DEFAULT (等价于unset),默认值为DEFAULT |
databaseId | 数据库厂商标识 (databaseldProvider),如果配置了此属性,MyBatis 会加载所有不带databaseId 或匹配当前 databaseId 的语句 |
resultOrdered | 针对嵌套结果 select 语句,默认值为 false,如果为 true,将会假设包含嵌套结果集或分组,当返回一个主结果行时,不会产生对前面结果集的引用 |
resultSets | 仅适用于多结果集的情况。将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔 |
select标签虽然有很多属性,但是常用的是id、parameterType、resultType、resultMap这4个属性。需要注意的是,resultMap是MyBatis的强大特性之一,如果对其理解透彻,许多复杂的映射问题都能迎刃而解。
insert标签主要用于定义插入数据的SQL语句,例如:
<insert id="insert" parameterType="com.example.demo.Mapper.Student">
INSERT INTO
student
(id, name, sex, age)
VALUES
(#{id}, #{name}, #{sex}, #{age})
</insert>
在上面的示例中,插入语句的配置规则更加复杂,同时提供了额外的属性和子元素用来处理主键的生成方式。
如果数据库包含自动生成主键的字段,那么可以设置useGeneratedKeys=“true”,然后把keyProperty设置为目标属性。比如,上面的Student表已经在id列上使用了自动生成主键,那么语句可以修改为:
<insert id="insert" useGeneratedKeys="true" keyProperty="id" parameterType="com.example.demo.model.Student">
INSERT INTO
student
(name, sex, age)
VALUES
(#{name}, #{sex}, #{age})
</insert>
在上面的示例中,设置useGeneratedKeys=“true”,然后设置keyProperty="id"对应的主键字段。
insert标签包含的属性如表所示。
属性 | 说明 |
---|---|
id | 命名空间中唯一的标识符,被用来引用这条语句 |
parameterType | 将传入语句的参数的数据类型,可选。MyBatis 可以通过类型处理程序 (TypeHandler)推断出传入语句的参数的数据类型,默认值为未设置 (unset) |
flushCache | 是否清空缓存,默认值为 true,只要语句被调用,就清空本地缓存和二级缓存 |
timeout | 超时时间,即等待数据库返回请求结果的时间。默认值为未设置 (unset) |
statementType | 使用 Statement、PreparedStatement 或 CallableStatement 执行 SQL 语句,默认值为PREPARED |
useGeneratedKeys | 自动生成主键,默认值为 false,设置为 true 时,根据规则自动生成主键 |
keyProperty | 指定能够唯一识别对象的属性 |
keyColumn | 指定数据库表的主键列名 |
databaseld | 数据库厂商标识 (databaseIdProvider),如果配置了此属性,MyBatis 会加载所有不带databaseId 或匹配当前 databaseId 的语句 |
常用的属性有id、parameterType、useGeneratedKeys、keyProperty等,部分属性和select标签是一致的。
update标签和insert标签类似,主要用来映射更新语句,示例代码如下:
<update id="update" parameterType="com.example.demo.model.Student">
UPDATE
student
SET
name = #{name},
sex = #{sex},
age = #{age}
WHERE
id = #{iid
</update>
如果需要根据传入的参数来动态判断是否进行修改,可以使用if标签动态生成SQL语句,示例代码如下:
<update id="update" parameterType="com.example.demo.model.Student">
UPDATE
student
SET
<if test="name != null">name = #{name},</if>
<if test="sex != null">sex = #{sex},</if>
age = #{age}
WHERE
id = #{iid
</update>
在上面的示例中,通过if标签判断传入的name参数是否为空,实现根据参数动态生成SQL语句。
update标签包含的属性和insert标签基本一致。
delete标签用来映射删除语句。
<delete id="delete" parameterType="Long">
DELETE FROM
student
WHERE
id = #{id}
</delete>
delete标签包含的属性如表所示。
delete标签除了少了useGeneratedKeys、keyProperty和keyColumn三个属性之外,其余的和insert、update标签一样。
结果映射是MyBatis重要的功能之一。对于简单的SQL查询,使用resultType属性自动将结果转换成Java数据类型。不过,如果是复杂的语句,则使用resultMap映射将查询结果转换为数据实体关系。
前面介绍select标签的时候提到,select标签的返回结果可以使用resultMap和resultType两个属性指定映射结构。下面就来演示resultType的用法。
<select id="selectOne" resultType="com.example.demo.model.Student">
select *
from student
where id =#{id}
</select>
通过设置resultType属性,MyBatis会自动把查询结果集转换为Student实体对象。当然,如果只查询部分字段,则可以返回HashMap,比如:
<select id="selectOne" parameterType="Long" resultType="hashmap">
select name,age from student where id = #{id}
</select>
上述语句,Mybatis会自动将所有的列映射成HashMap对象
在日常开发过程中,在大部分情况下resultType就能满足。但是使用resultType需要数据库字段和属性字段名称一致,否则就得使用别名,这样就使得SQL语句变得复杂。
所以MyBatis提供了resultMap标签定义SQL查询结果字段与实体属性的映射关系。下面演示resultMap的使用。
首先,定义resultMap:
<resultMap id="BaseResultMap" type="com.example.demo.model.Student">
<id column="id" property="id" jdbcType="BIGINT" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="sex" property="sex" javaType="INTEGER" />
<result column="age" property="age" jdbcType="INTEGER" />
</resultMap>
在上面的示例中,我们使用resultMap标签定义了BaseResultMap映射关系,将数据库中的字段映射为Student实体对象。
然后,在SQL语句中使用自定义的BaseResultMap映射关系,设置select标签的resultMap=“BaseResultMap”,示例代码如下:
<select id="selectOne" parameterType="Long" resultMap="BaseResultMap">
SELECT
*
FROM student
WHERE id =#{id}
</select>
resultMap标签的结构比较复杂,包含很多子属性和子标签。resultMap标签包含id和type属性:
同样,resultMap还可以包含多个子标签,包括:
1)id标签用于设置主键字段与领域模型属性的映射关系,此处主键为id,对应数据库字段中的主键ID。
2)result标签用于设置普通字段与领域模型的属性映射关系。
3)association标签用于配置一对一结果映射,可以关联resultMap中的定义,或者对其他结果映射的引用。
4)collection标签用于配置一对多结果映射,可以关联resultMap中的定义,或者对其他结果映射的引用。
下面是完整的resultMap元素的结构:
<resultMap id="BaseResultMap" type="com.example.demo.model.Student">
<id column="id" property="id" jdbcType="BIGINT" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="sex" property="sex" javaType="INTEGER" />
<result column="age" property="age" jdbcType="INTEGER" />
<association property="classes" javaType="com.example.demo.model.Classes">
<id column="id" property="id"/>
<result column="class_name" property="name" jdbcType="VARCHAR"/>
<result column="memo" property="memo" jdbcType="VARCHAR"/>
</association>
</resultMap>