1.5 Mapper 接口与 XML 映射文件 1.5 Mapper 接口与 XML 映射文件:MyBatis的核心桥梁 在 MyBatis 的世界里,Mapper 接口与 XML 映射文件是连接 Java 代码和数据库的关键桥梁。它们协同工作,将 Java 方法调用转化为 SQL 语句执行,并将数据库查询结果映射到 Java 对象。理解这两个组件及其关系,是掌握 MyBatis 的核心。 1.5.1 Mapper 接口:定义数据访问契约 Mapper 接口本质上是一个 Java 接口,它定义了一系列数据访问操作。每个方法对应一个 SQL 语句,并指定了输入参数和返回类型。 1. 接口定义规范: 命名: 接口名通常与对应的实体类或业务模块相关,例如 、 。
在 MyBatis 的世界里,Mapper 接口与 XML 映射文件是连接 Java 代码和数据库的关键桥梁。它们协同工作,将 Java 方法调用转化为 SQL 语句执行,并将数据库查询结果映射到 Java 对象。理解这两个组件及其关系,是掌握 MyBatis 的核心。
Mapper 接口本质上是一个 Java 接口,它定义了一系列数据访问操作。每个方法对应一个 SQL 语句,并指定了输入参数和返回类型。
1. 接口定义规范:
命名: 接口名通常与对应的实体类或业务模块相关,例如 UserMapper、OrderMapper。
方法名: 方法名应清晰表达其功能,例如 getUserById、insertUser、updateUser。
参数: 方法参数用于传递 SQL 语句所需的输入数据。可以使用基本类型、JavaBean、Map 或 MyBatis 提供的 @Param 注解。
返回值: 方法返回值指定 SQL 语句执行后的结果类型。可以是单个对象、对象集合、影响行数(int)或 void。
2. 代码示例:
package com.example.mapper; import com.example.entity.User; import org.apache.ibatis.annotations.Param; import java.util.List; public interface UserMapper { /** * 根据用户ID查询用户信息 * @param id 用户ID * @return User对象 */ User getUserById(Integer id); /** * 查询所有用户 * @return 用户列表 */ List<User> getAllUsers(); /** * 插入新用户 * @param user 用户对象 * @return 影响行数 */ int insertUser(User user); /** * 根据用户ID更新用户信息 * @param id 用户ID * @param username 用户名 * @return 影响行数 */ int updateUserUsernameById(@Param("id") Integer id, @Param("username") String username); /** * 根据用户ID删除用户 * @param id 用户ID * @return 影响行数 */ int deleteUserById(Integer id); }
3. 接口作用:
定义数据访问操作: 明确规定了可以对数据进行哪些操作,例如查询、插入、更新、删除。
解耦业务逻辑和数据访问: 业务代码只需调用 Mapper 接口的方法,无需关心 SQL 语句的细节。
提高代码可读性和可维护性: 通过接口,可以更清晰地了解数据访问层的职责和功能。
XML 映射文件是 Mapper 接口的“灵魂”,它负责将接口方法与具体的 SQL 语句关联起来,并定义查询结果到 Java 对象的映射规则。
1. 文件结构:
XML 映射文件通常包含以下元素:
<mapper>: 根元素,namespace 属性指定对应的 Mapper 接口的完整类名。
<select>: 定义查询操作,id 属性与 Mapper 接口的方法名对应,parameterType 属性指定输入参数类型,resultType 或 resultMap 属性指定返回结果类型。
<insert>: 定义插入操作,id 属性与 Mapper 接口的方法名对应,parameterType 属性指定输入参数类型。
<update>: 定义更新操作,id 属性与 Mapper 接口的方法名对应,parameterType 属性指定输入参数类型。
<delete>: 定义删除操作,id 属性与 Mapper 接口的方法名对应,parameterType 属性指定输入参数类型。
<sql>: 定义可重用的 SQL 代码片段。
<resultMap>: 定义结果集到 Java 对象的映射规则。
2. 代码示例:
与 UserMapper.java 对应的 UserMapper.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.mapper.UserMapper"> <select id="getUserById" parameterType="java.lang.Integer" resultType="com.example.entity.User"> SELECT id, username, email FROM users WHERE id = #{id} </select> <select id="getAllUsers" resultType="com.example.entity.User"> SELECT id, username, email FROM users </select> <insert id="insertUser" parameterType="com.example.entity.User"> INSERT INTO users (username, email) VALUES (#{username}, #{email}) </insert> <update id="updateUserUsernameById" > UPDATE users SET username = #{username} WHERE id = #{id} </update> <delete id="deleteUserById" parameterType="java.lang.Integer"> DELETE FROM users WHERE id = #{id} </delete> </mapper>
3. 核心功能:
SQL 语句定义: 包含了实际执行的 SQL 语句,包括查询、插入、更新、删除等。
参数映射: 将 Mapper 接口方法中的参数值传递到 SQL 语句中,例如 #{id}、#{username}。
结果映射: 将数据库查询结果映射到 Java 对象,例如将 id、username、email 列的值映射到 User 对象的对应属性。
动态 SQL: 支持根据条件动态生成 SQL 语句,提高 SQL 的灵活性和可重用性。 可以使用 <if>, <choose>, <when>, <otherwise>, <where>, <set>, <foreach> 等标签实现。
MyBatis 通过配置的方式将 Mapper 接口与 XML 映射文件关联起来。通常,在 mybatis-config.xml 配置文件中,使用 <mappers> 元素指定 Mapper 接口和 XML 映射文件的位置。
1. 配置示例:
<configuration> <environments default="development"> <environment id="development"> <!-- ... 数据源配置 ... --> </environment> </environments> <mappers> <mapper resource="com/example/mapper/UserMapper.xml"/> <!-- 或者使用类名 --> <!-- <mapper class="com.example.mapper.UserMapper"/> --> </mappers> </configuration>
2. 关联方式:
resource 属性: 指定 XML 映射文件的路径,通常是相对于 classpath 的路径。
class 属性: 指定 Mapper 接口的完整类名。 MyBatis 会自动查找与该接口同名的 XML 映射文件(在同一目录下,文件名与接口名相同,后缀为 .xml)。
3. 工作原理:
当 MyBatis 初始化时,会解析 mybatis-config.xml 文件,加载 Mapper 接口和 XML 映射文件。然后,MyBatis 会为每个 Mapper 接口创建一个代理对象。当业务代码调用 Mapper 接口的方法时,实际上是调用了代理对象的方法。代理对象会根据方法名找到对应的 SQL 语句,执行 SQL 语句,并将结果映射到 Java 对象,最后返回给业务代码。
MyBatis 的动态 SQL 功能允许根据不同的条件动态生成 SQL 语句,这在处理复杂的查询和更新操作时非常有用。
1. 常用标签:
<if>: 根据条件判断是否包含某段 SQL 代码。
<choose>、<when>、<otherwise>: 类似于 Java 中的 switch 语句,根据不同的条件选择不同的 SQL 代码。
<where>: 动态生成 WHERE 子句,并自动处理 AND 或 OR 前缀。
<set>: 动态生成 SET 子句,用于更新操作,并自动处理逗号后缀。
<foreach>: 用于循环遍历集合,生成 IN 子句或批量插入/更新操作。
2. 代码示例:
<select id="findUsersByCondition" parameterType="com.example.entity.User" resultType="com.example.entity.User"> SELECT id, username, email FROM users <where> <if test="username != null and username != ''"> AND username LIKE #{username} </if> <if test="email != null and email != ''"> AND email = #{email} </if> </where> </select> <update id="updateUserSelective" parameterType="com.example.entity.User"> UPDATE users <set> <if test="username != null"> username = #{username}, </if> <if test="email != null"> email = #{email}, </if> </set> WHERE id = #{id} </update>
当数据库表的列名与 Java 对象的属性名不一致,或者需要进行更复杂的结果映射时,可以使用 <resultMap> 元素。
1. <resultMap> 元素属性:
id: resultMap 的唯一标识符,用于在 <select> 元素中引用。
type: 结果集映射到的 Java 对象的类型。
2. 子元素:
<id>: 映射主键列。
<result>: 映射普通列。
<association>: 映射关联对象(一对一)。
<collection>: 映射集合对象(一对多)。
<discriminator>: 根据不同的列值选择不同的映射规则。
3. 代码示例:
假设 users 表的列名为 user_id、user_name、user_email,需要映射到 User 对象的 id、username、email 属性。
<resultMap id="UserResultMap" type="com.example.entity.User"> <id column="user_id" property="id"/> <result column="user_name" property="username"/> <result column="user_email" property="email"/> </resultMap> <select id="getUserById" parameterType="java.lang.Integer" resultMap="UserResultMap"> SELECT user_id, user_name, user_email FROM users WHERE user_id = #{id} </select>
以下是一个使用 Mermaid 绘制的流程图,展示了 Mapper 接口、XML 映射文件以及 MyBatis 框架之间的关系:
流程解释:
Java 代码 调用 Mapper 接口 的方法。
Mapper 接口 将调用传递给 MyBatis 框架。
MyBatis 框架 根据 Mapper 接口的方法名,在 XML 映射文件 中查找对应的 SQL 语句。
XML 映射文件 中定义了 SQL 语句和结果映射规则。
MyBatis 框架 执行 SQL 语句,并从 数据库 获取结果。
XML 映射文件 定义的规则将数据库结果映射到 Java 对象。
MyBatis 框架 将映射后的 Java 对象返回给 Mapper 接口。
Mapper 接口 将 Java 对象返回给 Java 代码。
Mapper 接口和 XML 映射文件是 MyBatis 的核心组件,它们共同完成了 Java 代码与数据库之间的交互。Mapper 接口定义了数据访问的契约,XML 映射文件则负责实现这些契约,定义 SQL 语句和映射规则。掌握这两个组件的使用,是深入理解 MyBatis 的关键。通过灵活运用动态 SQL 和 ResultMap,可以处理各种复杂的数据访问场景,提高开发效率和代码质量。