MyBatis SQL映射文件的作用和结构详解
作者:冰糖心书房
MyBatis SQL 映射文件定义了 SQL 语句以及如何将 SQL 语句的参数和结果映射到 Java 对象。
一、 作用 (Purpose)
MyBatis SQL 映射文件(通常命名为 XXXMapper.xml)的主要作用是:
- 定义 SQL 语句: 在 XML 映射文件中编写 SQL 语句,包括 SELECT, INSERT, UPDATE, DELETE 等各种类型的 SQL 语句。
- 参数映射 (Parameter Mapping): 定义如何将 Java 方法的参数映射到 SQL 语句中的参数。 可以使用
#和$占位符,并指定参数类型、jdbcType 等信息。 - 结果映射 (Result Mapping): 定义如何将 SQL 语句的查询结果映射到 Java 对象。 可以使用
resultType或resultMap,并定义一对一、一对多等关系映射。 - 动态 SQL (Dynamic SQL): 使用 MyBatis 提供的动态 SQL 元素 (例如
<if>,<choose>,<when>,<otherwise>,<where>,<set>,<foreach>),根据不同的条件动态生成 SQL 语句。 - 缓存配置 (Cache Configuration): 配置 SQL 语句的缓存行为,提高查询性能。
- 与 Mapper 接口关联: 将 SQL 映射文件与 Java Mapper 接口关联起来,使得可以通过调用 Mapper 接口的方法来执行 SQL 语句。
总而言之,SQL 映射文件是 MyBatis 将 SQL 语句与 Java 代码解耦的关键,它允许开发者专注于 SQL 语句的编写和优化,而无需关心 JDBC 的细节。
二、 结构 (Structure)
MyBatis SQL 映射文件的根元素是 <mapper>,它包含多个子元素,用于定义 SQL 语句、参数映射、结果映射等信息。
以下是一个典型的 SQL 映射文件结构:
<?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.mapper.UserMapper">
<!-- 1. cache (缓存) -->
<cache
eviction="LRU"
flushInterval="60000"
readOnly="true"
size="512"/>
<!-- 2. resultMap (结果映射) -->
<resultMap id="UserResultMap" type="com.example.model.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="email" column="email"/>
<!-- association (一对一) -->
<association property="address" column="address_id" javaType="com.example.model.Address"
select="com.example.mapper.AddressMapper.selectAddressById"/>
<!-- collection (一对多) -->
<collection property="orders" column="id" ofType="com.example.model.Order"
select="com.example.mapper.OrderMapper.selectOrdersByUserId"/>
</resultMap>
<!-- 3. select (查询) -->
<select id="selectUserById" parameterType="int" resultMap="UserResultMap" useCache="true">
SELECT * FROM user WHERE id = #{id}
</select>
<!-- 4. insert (插入) -->
<insert id="insertUser" parameterType="com.example.model.User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user (username, email) VALUES (#{username}, #{email})
</insert>
<!-- 5. update (更新) -->
<update id="updateUser" parameterType="com.example.model.User">
UPDATE user SET username = #{username}, email = #{email} WHERE id = #{id}
</update>
<!-- 6. delete (删除) -->
<delete id="deleteUserById" parameterType="int">
DELETE FROM user WHERE id = #{id}
</delete>
<!-- 7. sql (SQL 片段) -->
<sql id="userColumns">
id, username, email
</sql>
</mapper>三、各个元素详解
<mapper> (根元素):
namespace属性:指定 Mapper 接口的完全限定名。 MyBatis 会根据这个命名空间来查找 SQL 映射文件,并将 SQL 语句与 Mapper 接口的方法关联起来。 这是将 SQL 映射文件与 Java 代码关联的关键。- 例如:
<mapper namespace="com.example.mapper.UserMapper">对应着UserMapper.java接口文件
<cache> (缓存):
- 配置该 Mapper 对应的二级缓存。
eviction属性:指定缓存的淘汰策略 (LRU, FIFO, SOFT, WEAK)。flushInterval属性:指定缓存的刷新间隔 (毫秒)。size属性:指定缓存的最大容量。readOnly属性:指定缓存是否只读 (true或false)。<cache type="org.mybatis.cache.impl.PerpetualCache"/>使用自定义缓存
<cache-ref> (缓存引用):
- 引用其他 Mapper 的缓存配置。
namespace属性:指定要引用的 Mapper 的命名空间。
<resultMap> (结果映射):
作用: 定义如何将 SQL 语句的查询结果映射到 Java 对象。
id属性:指定resultMap的唯一标识。type属性:指定要映射的 Java 类型。
子元素:
<id>:定义主键映射。property属性:指定 Java 对象的属性名。column属性:指定数据库表中的列名。
<result>:定义普通属性映射。property属性:指定 Java 对象的属性名。column属性:指定数据库表中的列名。
<association>:定义一对一关系映射。property属性:指定 Java 对象的属性名。column属性:指定数据库表中的列名。javaType属性:指定关联对象的 Java 类型。select属性:指定用于查询关联对象的 SQL 语句的 ID。
<collection>:定义一对多关系映射。property属性:指定 Java 对象的属性名。column属性:指定数据库表中的列名。ofType属性:指定集合中元素的 Java 类型。select属性:指定用于查询集合元素的 SQL 语句的 ID。
<discriminator>:定义鉴别器,根据不同的条件选择不同的映射规则。column属性:指定用于鉴别的列名。<case>元素:定义不同的映射规则。value属性:指定鉴别值。resultMap属性:指定要使用的resultMap。
示例:
<resultMap id="UserResultMap" type="com.example.model.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="email" column="email"/>
<association property="address" column="address_id" javaType="com.example.model.Address"
select="com.example.mapper.AddressMapper.selectAddressById"/>
<collection property="orders" column="id" ofType="com.example.model.Order"
select="com.example.mapper.OrderMapper.selectOrdersByUserId"/>
</resultMap><select> (查询):
- 作用: 定义 SELECT 语句,用于查询数据。
id属性:指定 SQL 语句的唯一标识。 与 Mapper 接口中的方法名对应。parameterType属性:指定参数类型。resultType属性:指定结果类型(如果使用简单类型映射)。resultMap属性:指定结果映射 (如果使用<resultMap>元素)。parameterMap属性: (已经过时, 不建议使用)flushCache属性: 如果设置为true,则每次执行该语句都会刷新缓存。useCache属性:如果设置为true,则该语句的结果会被缓存。timeout属性:设置超时时间(秒)。fetchSize属性:设置每次从数据库获取的记录数量。statementType属性: 指Statement类型, 可选值为 STATEMENT、PREPARED 和 CALLABLE。- STATEMENT, 默认值, 使用Statement
- PREPARED, 使用PreparedStatement, 可以防止SQL注入, 性能更好。
- CALLABLE, 主要用于执行存储过程
示例:
<select id="selectUserById" parameterType="int" resultMap="UserResultMap" useCache="true">
SELECT * FROM user WHERE id = #{id}
</select><insert> (插入):
- 作用: 定义 INSERT 语句,用于插入数据。
id属性:指定 SQL 语句的唯一标识。parameterType属性:指定参数类型。useGeneratedKeys属性:是否允许 MyBatis 使用 JDBC 的getGeneratedKeys方法获取自增主键值。keyProperty属性:指定 Java 对象的哪个属性用于接收自增主键值。keyColumn属性:指定数据库表的主键列名.
示例:
<insert id="insertUser" parameterType="com.example.model.User" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
INSERT INTO user (username, email) VALUES (#{username}, #{email})
</insert><update> (更新):
- 作用: 定义 UPDATE 语句,用于更新数据。
id属性:指定 SQL 语句的唯一标识。parameterType属性:指定参数类型。
示例:
<update id="updateUser" parameterType="com.example.model.User">
UPDATE user SET username = #{username}, email = #{email} WHERE id = #{id}
</update><delete> (删除):
- 作用: 定义 DELETE 语句,用于删除数据。
id属性:指定 SQL 语句的唯一标识。parameterType属性:指定参数类型。
示例:
<delete id="deleteUserById" parameterType="int">
DELETE FROM user WHERE id = #{id}
</delete><sql> (SQL 片段):
- 作用: 定义可以重复使用的 SQL 代码片段。
id属性:指定 SQL 片段的唯一标识。
示例:
<sql id="userColumns">
id, username, email
</sql>四、动态 SQL 元素 (Dynamic SQL Elements)
MyBatis 提供了以下动态 SQL 元素,可以根据不同的条件动态生成 SQL 语句:
<if>:
- 作用: 根据条件判断是否包含某段 SQL 代码。
test属性:指定判断条件,使用 OGNL 表达式。
示例:
<select id="selectUserByCondition" parameterType="com.example.model.User" resultMap="UserResultMap">
SELECT * FROM user
<where>
<if test="username != null and username != ''">
AND username = #{username}
</if>
<if test="email != null and email != ''">
AND email = #{email}
</if>
</where>
</select><choose>, <when>, <otherwise>:
- 作用: 类似于 Java 中的
switch-case语句,用于选择其中一个条件分支。 <choose>元素:包含多个<when>元素和一个<otherwise>元素。<when>元素:指定条件和对应的 SQL 代码。<otherwise>元素:指定默认的 SQL 代码(当所有<when>条件都不满足时执行)。test属性:指定<when>元素的判断条件,使用 OGNL 表达式。
示例:
<select id="selectUserByCondition" parameterType="com.example.model.User" resultMap="UserResultMap">
SELECT * FROM user
<where>
<choose>
<when test="username != null and username != ''">
AND username = #{username}
</when>
<when test="email != null and email != ''">
AND email = #{email}
</when>
<otherwise>
AND 1 = 1
</otherwise>
</choose>
</where>
</select><where>:
- 作用: 动态生成
WHERE子句,并自动处理AND或OR关键字。 - 如果
<where>元素内部有任何内容,它会自动添加WHERE关键字。 - 如果
<where>元素内部的内容以AND或OR开头,它会自动移除这些关键字。
示例:
<select id="selectUserByCondition" parameterType="com.example.model.User" resultMap="UserResultMap">
SELECT * FROM user
<where>
<if test="username != null and username != ''">
AND username = #{username}
</if>
<if test="email != null and email != ''">
AND email = #{email}
</if>
</where>
</select><set>:
- 作用: 动态生成
SET子句,用于 UPDATE 语句,并自动处理逗号,。 - 如果
<set>元素内部有任何内容,它会自动添加SET关键字。 - 如果
<set>元素内部的内容以逗号,开头,它会自动移除这个逗号。
示例:
<update id="updateUserSelective" parameterType="com.example.model.User">
UPDATE user
<set>
<if test="username != null">
username = #{username},
</if>
<if test="email != null">
email = #{email},
</if>
</set>
WHERE id = #{id}
</update><trim>:
- 作用: 更通用的动态 SQL 元素,可以自定义前缀、后缀、以及前缀和后缀要移除的内容。
prefix属性:指定前缀。suffix属性:指定后缀。prefixOverrides属性:指定要移除的前缀。suffixOverrides属性:指定要移除的后缀。
示例:
<select id="selectUserByCondition" parameterType="com.example.model.User" resultMap="UserResultMap">
SELECT * FROM user
<trim prefix="WHERE" prefixOverrides="AND |OR">
<if test="username != null and username != ''">
AND username = #{username}
</if>
<if test="email != null and email != ''">
AND email = #{email}
</if>
</trim>
</select>
<update id="updateUserSelective" parameterType="com.example.model.User">
UPDATE user
<trim prefix="SET" suffixOverrides=",">
<if test="username != null">
username = #{username},
</if>
<if test="email != null">
email = #{email},
</if>
</trim>
WHERE id = #{id}
</update><foreach>:
- 作用: 用于遍历集合,生成重复的 SQL 代码。
collection属性:指定要遍历的集合。item属性:指定集合中元素的别名。index属性:指定当前元素的索引的别名。open属性:指定循环开始时的字符串。close属性:指定循环结束时的字符串。separator属性:指定元素之间的分隔符。
示例:
<select id="selectUsersByIds" parameterType="list" resultMap="UserResultMap">
SELECT * FROM user
WHERE id IN
<foreach item="id" collection="list" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<insert id="insertUsers" parameterType="list">
INSERT INTO user (username, email) VALUES
<foreach item="user" collection="list" separator="," >
(#{user.username}, #{user.email})
</foreach>
</insert><bind>:
- 作用: 创建一个变量,并将其绑定到 OGNL 表达式的结果。
name属性: 指定变量名value属性: 指定 OGNL 表达式
示例:
<select id="selectUsersBySearchTerm" parameterType="string" resultMap="UserResultMap">
<bind name="pattern" value="'%' + searchTerm + '%'" />
SELECT * FROM user
WHERE username LIKE #{pattern} OR email LIKE #{pattern}
</select>五、DOCTYPE (Document Type Definition)
MyBatis SQL 映射文件需要遵循特定的 DTD 约束.
DTD 声明:
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">DTD 文件:
mybatis-3-mapper.dtd文件定义了 MyBatis SQL 映射文件的结构。可以在 MyBatis 的官方网站上找到该文件。- 开发中通常不需要我们手动修改 DTD 文件,只需要在 XML 配置文件中声明 DTD 即可。
六、总结
MyBatis SQL 映射文件是 MyBatis 框架的核心,它定义了 SQL 语句以及如何将 SQL 语句的参数和结果映射到 Java 对象。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
