Appearance
Mapper XML 映射文件
Mapper XML 是 MyBatis 的核心所在,承载了 SQL 语句、参数映射、结果映射等所有数据库操作的定义。
一、Mapper XML 基本结构
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">
<!-- namespace = 接口全限定名 -->
<mapper namespace="com.example.mapper.UserMapper">
<!-- 可复用的 SQL 片段 -->
<sql id="baseColumns">id, name, age, email, create_time</sql>
<!-- 结果映射 -->
<resultMap id="userMap" type="User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
</resultMap>
<!-- CRUD 操作 -->
<select id="selectById" resultMap="userMap">
SELECT <include refid="baseColumns"/>
FROM user WHERE id = #{id}
</select>
</mapper>二、CRUD 操作详解
2.1 select(查询)
xml
<!-- ========== 基础查询 ========== -->
<!-- 单条查询 -->
<select id="selectById" resultType="User">
SELECT * FROM user WHERE id = #{id}
</select>
<!-- 列表查询 -->
<select id="selectAll" resultType="User">
SELECT * FROM user
</select>
<!-- 统计查询 -->
<select id="count" resultType="int">
SELECT COUNT(*) FROM user
</select>
<!-- 模糊查询 -->
<select id="selectByName" resultType="User">
SELECT * FROM user WHERE name LIKE CONCAT('%', #{name}, '%')
</select>
<!-- 多参数查询 -->
<select id="selectByAgeRange" resultType="User">
SELECT * FROM user
WHERE age BETWEEN #{minAge} AND #{maxAge}
</select>2.2 insert(新增)
xml
<!-- 普通新增 -->
<insert id="insert">
INSERT INTO user (name, age, email)
VALUES (#{name}, #{age}, #{email})
</insert>
<!-- 新增并返回自增主键 -->
<insert id="insertAndGetId" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user (name, age, email)
VALUES (#{name}, #{age}, #{email})
</insert>
<!-- 支持子查询插入 -->
<insert id="insertBatch">
INSERT INTO user (name, age, email)
SELECT name, age, email FROM temp_user WHERE status = 1
</insert>2.3 update(修改)
xml
<!-- 根据 ID 修改 -->
<update id="update">
UPDATE user
SET name = #{name}, age = #{age}, email = #{email}
WHERE id = #{id}
</update>
<!-- 动态修改(只更新不为 null 的字段) -->
<update id="updateSelective">
UPDATE user
<set>
<if test="name != null">name = #{name},</if>
<if test="age != null">age = #{age},</if>
<if test="email != null">email = #{email},</if>
</set>
WHERE id = #{id}
</update>2.4 delete(删除)
xml
<!-- 根据 ID 删除 -->
<delete id="deleteById">
DELETE FROM user WHERE id = #{id}
</delete>
<!-- 批量删除 -->
<delete id="deleteByIds">
DELETE FROM user WHERE id IN
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>三、参数传递
3.1 单个参数
java
// 接口
User selectById(Long id);xml
<!-- 单个参数:直接写 #{任意名} -->
<select id="selectById" resultType="User">
SELECT * FROM user WHERE id = #{id}
</select>3.2 多个参数
java
// 接口
List<User> selectByAgeRange(@Param("minAge") int minAge,
@Param("maxAge") int maxAge);xml
<!-- 多个参数:必须用 @Param 注解指定名字 -->
<select id="selectByAgeRange" resultType="User">
SELECT * FROM user
WHERE age BETWEEN #{minAge} AND #{maxAge}
</select>如果不加 @Param 注解,默认名字是:
第一个参数 → param1
第二个参数 → param2
...
或者使用 arg0, arg1, arg2...(MyBatis 3.4.1+)3.3 对象参数
java
// 接口
List<User> selectByCondition(UserQuery query);xml
<!-- 对象参数:直接写属性名 -->
<select id="selectByCondition" resultType="User">
SELECT * FROM user
WHERE name = #{name}
AND age > #{age}
</select>3.4 Map 参数
java
// 接口
List<User> selectByMap(Map<String, Object> params);xml
<!-- Map 参数:直接写 key -->
<select id="selectByMap" resultType="User">
SELECT * FROM user
WHERE name = #{name}
AND age > #{minAge}
</select>3.5 List/数组参数
java
// 接口
List<User> selectByIds(@Param("ids") List<Long> ids);xml
<!-- List 参数:用 foreach 遍历 -->
<select id="selectByIds" resultType="User">
SELECT * FROM user WHERE id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>四、#{ } 与 ${ } 的区别
xml
<!-- #{ } 预编译占位符(推荐) -->
<select id="selectById" resultType="User">
SELECT * FROM user WHERE id = #{id}
</select>
<!-- 实际执行:SELECT * FROM user WHERE id = ? -->
<!-- ${ } 字符串替换(有风险) -->
<select id="selectByTable" resultType="User">
SELECT * FROM ${tableName} WHERE id = #{id}
</select>
<!-- 实际执行:SELECT * FROM user WHERE id = ? -->| 对比 | # | $ |
|---|---|---|
| 处理方式 | 预编译参数占位符 ? | 字符串直接拼接 |
| SQL 注入 | 安全 | 有风险 |
| 类型处理 | 自动加引号 | 原样拼接 |
| 使用场景 | 普通参数值 | 动态表名/列名/排序 |
使用 ${ } 的典型场景:
① 动态表名:SELECT * FROM ${tableName}
② 动态列名:ORDER BY ${columnName}
③ 动态排序:ORDER BY ${column} ${direction}
④ 动态数据库名:USE ${dbName}
注意:${ } 必须严格校验,防止 SQL 注入!五、SQL 片段(复用)
xml
<!-- 定义 SQL 片段 -->
<sql id="baseColumns">
id, name, age, email, create_time
</sql>
<sql id="whereCondition">
<where>
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="age != null">
AND age = #{age}
</if>
<if test="email != null and email != ''">
AND email = #{email}
</if>
</where>
</sql>
<!-- 使用 SQL 片段 -->
<select id="selectByCondition" resultType="User">
SELECT
<include refid="baseColumns"/>
FROM user
<include refid="whereCondition"/>
</select>xml
<!-- SQL 片段也可以传参 -->
<sql id="columns">
${alias}.id, ${alias}.name, ${alias}.age
</sql>
<select id="selectWithAlias" resultType="User">
SELECT
<include refid="columns">
<property name="alias" value="u"/>
</include>
FROM user u
</select>六、selectKey(获取主键)
xml
<!-- 方式一:useGeneratedKeys(推荐) -->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user (name, age, email) VALUES (#{name}, #{age}, #{email})
</insert>
<!-- 方式二:selectKey(适用于不支持自增的数据库) -->
<insert id="insert">
<selectKey keyProperty="id" order="BEFORE" resultType="long">
SELECT SEQ_USER.NEXTVAL FROM DUAL
</selectKey>
INSERT INTO user (id, name, age) VALUES (#{id}, #{name}, #{age})
</insert>
<!-- 方式三:selectKey AFTER(MySQL UUID 场景) -->
<insert id="insertWithUUID">
<selectKey keyProperty="id" order="AFTER" resultType="string">
SELECT UUID()
</selectKey>
INSERT INTO user (name, age) VALUES (#{name}, #{age})
</insert>七、速记总结
四大标签:
<select> → 查询
<insert> → 新增
<update> → 修改
<delete> → 删除
参数传递:
单参数 → #{任意名}
多参数 → @Param("name") + #{name}
对象 → #{属性名}
Map → #{key}
List → foreach 遍历
两个占位符:
#{ } → 预编译,防注入,用参数值
${ } → 字符串拼接,有风险,用动态表名/列名八、面试要点
| 问题 | 答案要点 |
|---|---|
| #{ } 和 ${ } 区别? | #{} 预编译防注入,${} 字符串拼接有风险 |
| 多参数怎么传? | @Param 注解指定名字 |
| 怎么获取自增主键? | useGeneratedKeys + keyProperty |
| SQL 片段怎么用? | sql 标签定义,include 引用 |
