Mybatis作为持久层框架,通过XML映射文件将Java接口方法与数据库操作解耦。开发者在resources目录下编写以Mapper.xml结尾的文件,利用特定标签描述SQL逻辑。这种配置方式相比注解更利于维护复杂查询,也方便DBA直接审阅语句。理解各标签的语义与约束,是写出稳定数据访问层的前提。

Mapper根标签与命名空间配置
每个Mybatis映射文件都以<mapper>作为根元素,其namespace属性是整个文件的核心坐标。该属性必须填写对应Mapper接口的全限定类名,例如com.demo.dao.UserMapper。框架在启动时会扫描接口与XML,通过namespace加子标签id定位具体方法。如果namespace写错,调用接口就会出现Invalid bound statement异常,这类问题在模块拆分不清晰时尤为常见。
除了namespace,<mapper>内部可放置多种顶级子标签,包括<select>、<insert>、<update>、<delete>以及<resultMap>、<sql>、<cache>等。这些标签各司其职,但都依赖根标签提供的上下文。建议在文件头部引入Mybatis的DTD约束,这样编辑器能自动补全并校验标签合法性,减少手写错误。
下面是一个最小可用的映射文件结构示例,展示了根标签与一条查询的定义方式:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://ipipp.com/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.demo.dao.UserMapper">
<select id="selectById" parameterType="int" resultType="com.demo.entity.User">
select id, name, age from user where id = #{id}
</select>
</mapper>
SQL操作标签与参数结果映射
<select>、<insert>、<update>、<delete>四类标签分别对应数据库的读与写操作。它们共有的关键属性包括id、parameterType、resultType或resultMap。id值必须和Mapper接口中的方法名完全相同,否则绑定失败。parameterType可省略,Mybatis能根据接口参数自动推断,但显式声明有助于阅读。resultType适合单表简单映射,直接写实体类全名或别名即可。
当数据库列名与Java属性名不一致,或涉及一对一、一对多关联时,应使用<resultMap>标签预先定义映射规则,再在SQL标签中通过resultMap属性引用。<resultMap>内部用<id>标记主键,<result>标记普通列,<association>处理对象嵌套,<collection>处理集合嵌套。这种声明式映射比在SQL里写大量别名更清晰,也便于复用。
以下代码演示了带参数和结果映射的插入与查询配置,其中使用了生成主键回填的useGeneratedKeys特性:
<insert id="insertUser" parameterType="com.demo.entity.User"
useGeneratedKeys="true" keyProperty="id">
insert into user(name, age) values(#{name}, #{age})
</insert>
<resultMap id="userMap" type="com.demo.entity.User">
<id column="uid" property="id"/>
<result column="uname" property="name"/>
<result column="uage" property="age"/>
</resultMap>
<select id="selectAll" resultMap="userMap">
select uid, uname, uage from user
</select>
动态SQL标签提升配置灵活性
实际业务常需根据条件拼接SQL,Mybatis提供了一系列动态标签来避免手动字符串拼接的风险。<if>标签通过test表达式判断是否加入片段;<where>会自动剔除开头多余的and或or;<foreach>用于遍历集合生成in条件或批量插入;<choose>、<when>、<otherwise>则类似switch分支。这些标签在解析阶段生成参数化SQL,从根本上防止SQL注入。
使用<foreach>时需注意collection属性取值:若接口方法参数是List,默认名为list;若是数组则为array;若用@Param注解则取注解名。item代表当前元素,open与close定义包裹符,separator定义分隔符。错误配置collection会导致反射取不到参数而报错,因此建议统一使用@Param明确名称。
下面例子展示了一个带多条件筛选与批量删除的映射配置,体现了动态标签的实用价值:
<select id="queryUser" parameterType="map" resultType="com.demo.entity.User">
select id, name, age from user
<where>
<if test="name != null">
and name like concat('%', #{name}, '%')
</if>
<if test="minAge != null">
and age >= #{minAge}
</if>
</where>
</select>
<delete id="batchDelete" parameterType="list">
delete from user where id in
<foreach collection="list" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</delete>
除了上述标签,<sql>和<include>可用于抽取公共列或条件片段,减少重复书写。例如将常用查询字段定义为<sql id="baseColumn">id, name, age</sql>,在多处通过<include refid="baseColumn"/>引入。这种模块化思维能让映射文件在业务膨胀后依然保持可控。掌握XML映射文件的标签体系,才能把Mybatis的能力真正落地到项目里。