当前位置: 首页 > article >正文

MyBatis映射文件常用元素详解与示例

引言

MyBatis是一个优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。MyBatis的配置文件和映射文件分离,映射文件用于定义SQL语句和结果映射。本文将介绍MyBatis映射文件中常用的元素及其示例用法。


一、基础CRUD元素

1. <mapper>

作用:定义映射文件的根元素,指定命名空间。
属性namespace(对应Mapper接口的全限定名)。

<mapper namespace="com.example.UserMapper">

2. <select>

作用:定义查询操作。
关键属性

  • id:方法名
  • parameterType:参数类型
  • resultType/resultMap:返回类型

示例:查询用户

<!-- 
查询用户信息
参数:用户ID(整数类型)
返回:一个User对象
说明:WHERE id = #{id}:根据id条件进行查询,#{id}是MyBatis的占位符,用于动态传参。
用法:在Mapper接口中定义对应的方法,例如:
    User getUserById(int id); 
-->
<select id="getUserById" parameterType="int" resultType="User">
  SELECT * FROM users WHERE id = #{id}
</select>

官方文档


3. <insert>

作用insert元素用于定义插入语句,用于向数据库中插入数据。
属性useGeneratedKeys(是否使用自增主键),keyProperty(主键属性名)。

示例:插入用户并返回自增ID

<!-- 
 插入用户信息到数据库
 参数:User对象(包含name和age属性)
 功能:将用户信息插入到users表中
 说明:
    1. useGeneratedKeys="true":表示启用数据库自动生成主键(通常是自增ID)。
    2. keyProperty="id":指定生成的主键值将赋值到User对象的id属性中。
    3. 通过#{name}和#{age}动态获取User对象的name和age属性值。
 用法:在Mapper接口中定义对应的方法,例如:
      int insertUser(User user);
      调用后,user对象的id属性会被自动填充为数据库生成的主键值。
 -->
<insert id="insertUser" parameterType="User" 
        useGeneratedKeys="true" keyProperty="id">
  INSERT INTO users (name, age) VALUES (#{name}, #{age})
</insert>

4. <update><delete>

作用:更新和删除操作。

示例:更新用户

<!-- 
更新用户信息
参数:User对象(包含id、name和age属性)
功能:根据用户ID更新用户的名字和年龄
说明:
    1. parameterType="User":表示传入的参数是一个User对象。
    2. #{name}、#{age}、#{id}:MyBatis占位符,用于从User对象中动态获取对应的属性值。
    3. UPDATE users SET name=#{name}, age=#{age} WHERE id=#{id}:更新users表中指定ID的用户记录。
用法:在Mapper接口中定义对应的方法,例如:
    int updateUser(User user);
    调用时传入一个User对象即可。
 -->
<update id="updateUser" parameterType="User">
  UPDATE users SET name=#{name}, age=#{age} WHERE id=#{id}
</update>

示例:删除用户

<!-- 
删除用户信息
参数:用户ID(整数类型)
功能:根据用户ID删除用户记录
说明:
    1. parameterType="int":表示传入的参数是一个整数类型的用户ID。
    2. #{id}:MyBatis占位符,用于动态获取传入的用户ID值。
    3. DELETE FROM users WHERE id=#{id}:从users表中删除指定ID的用户记录。
用法:在Mapper接口中定义对应的方法,例如:
    int deleteUser(int id);
    调用时传入用户ID即可。
 -->
<delete id="deleteUser" parameterType="int">
  DELETE FROM users WHERE id = #{id}
</delete>

官方文档


二、结果映射 <resultMap>

拓展阅读:MyBatis映射文件 <resultMap> 元素详解与示例

1. 基础字段映射

用途:解决数据库列名与Java属性名不一致问题。

示例

<!-- 
用户结果映射
功能:将数据库查询结果映射到User对象
说明:
    1. id="UserResult":标识这个结果映射的唯一名称。
    2. type="User":指定目标Java对象类型为User。
    3. <id property="userId" column="user_id">:定义User对象的userId属性与数据库表的user_id列对应。
    4. <result property="userName" column="user_name">:定义User对象的userName属性与数据库表的user_name列对应。
 -->
<resultMap id="UserResult" type="User">
  <id property="userId" column="user_id" />
  <result property="userName" column="user_name" />
</resultMap>

<!-- 
查询用户信息
功能:从users表中查询user_id和user_name列,并将结果映射到User对象
说明:
    1. id="getUser":标识这个查询操作的唯一名称。
    2. resultMap="UserResult":指定使用UserResult结果映射来处理查询结果。
    3. SELECT user_id, user_name FROM users:从users表中查询user_id和user_name两列。
用法:在Mapper接口中定义对应的方法,例如:
    List<User> getUser();
    返回一个包含所有用户信息的User对象列表。
 -->
<select id="getUser" resultMap="UserResult">
  SELECT user_id, user_name FROM users
</select>

2. 关联关系映射

  • <association>:一对一关联
  • <collection>:一对多关联

示例:用户与订单的一对多关系

<!-- 
用户与订单结果映射
功能:将用户和其关联的订单信息映射到User对象
说明:
    1. id="UserWithOrders":标识这个结果映射的唯一名称。
    2. type="User":指定目标Java对象类型为User。
    3. <id property="id" column="id">:定义User对象的id属性与数据库表的id列对应,作为主键。
    4. <collection property="orders" ofType="Order">:定义User对象的orders属性为集合类型,存储Order对象。
        a. property="orders":User类中的订单集合属性。
        b. ofType="Order":集合中的元素类型为Order。
        c. <id property="orderId" column="order_id">:定义Order对象的orderId属性与数据库表的order_id列对应,作为主键。
        d. <result property="orderNo" column="order_no">:定义Order对象的orderNo属性与数据库表的order_no列对应。
    5. 通过这个结果映射,可以将用户的订单信息一并查询出来,并映射为嵌套的Java对象结构。
 -->
<resultMap id="UserWithOrders" type="User">
  <id property="id" column="id"/>
  <collection property="orders" ofType="Order">
    <id property="orderId" column="order_id"/>
    <result property="orderNo" column="order_no"/>
  </collection>
</resultMap>

<!-- 
查询用户及其订单信息
功能:从users和orders表中查询用户及订单数据,并通过UserWithOrders结果映射转换为Java对象
说明:
    1. id="getUserWithOrders":标识这个查询操作的唯一名称。
    2. resultMap="UserWithOrders":指定使用UserWithOrders结果映射来处理查询结果。
    3. SELECT u.*, o.order_id, o.order_no FROM users u LEFT JOIN orders o ON u.id = o.user_id:
        a. 查询users表的所有列(u.*)和orders表的order_id、order_no列。
        b. 使用LEFT JOIN将users表和orders表连接,连接条件为用户ID(u.id = o.user_id)。
        c. 查询结果将包含用户的基本信息和其关联的订单信息。
用法:在Mapper接口中定义对应的方法,例如:
    List<User> getUserWithOrders();
    返回一个包含用户及其订单信息的User对象列表。
 -->
<select id="getUserWithOrders" resultMap="UserWithOrders">
  SELECT u.*, o.order_id, o.order_no 
  FROM users u LEFT JOIN orders o ON u.id = o.user_id
</select>

三、动态SQL元素

1. <if>

用途:条件判断。

示例:动态过滤用户

<!-- 
动态条件查询用户信息
功能:根据传入的条件动态查询用户信息,支持组合条件过滤
参数:parameterType="map" 表示传入的参数是一个Map对象,可以包含多个条件
说明:
    1. SELECT * FROM users:从users表中查询所有列的数据。
    2. <where>:标识查询条件的开始,MyBatis会自动处理WHERE关键字的拼接。
    3. <if> 标签用于动态判断条件是否满足:
        - test="name != null":如果传入的name参数不为空,则拼接name = #{name}作为查询条件。
        - test="age != null":如果传入的age参数不为空,则拼接age = #{age}作为查询条件。
    4. 这个查询的灵活性在于可以根据传入的参数动态生成查询条件,如果多个条件同时存在,MyBatis会自动将它们用AND连接。
用法:在Mapper接口中定义对应的方法,例如:
    List<User> findUsers(Map<String, Object> params);
    参数params可以包含"name"和/或"age"键,也可以都不包含。
    如果参数不包含这些键,查询将没有条件限制(即查询所有用户)。
注意:
    1. 如果需要查询默认条件下的数据,建议为每个参数设置默认值或在Mapper方法中提供默认参数。
    2. 如果需要更复杂的条件组合(如OR条件),可以使用<choose>、<when>等动态SQL标签。
    3. 传递的参数类型为Map,便于动态传递多个查询条件。
    4. #{name}和#{age}是MyBatis的占位符,用于动态获取Map中的值。
 -->
<select id="findUsers" parameterType="map" resultType="User">
  SELECT * FROM users
  <where>
    <if test="name != null">AND name = #{name}</if>
    <if test="age != null">AND age = #{age}</if>
  </where>
</select>

2. <choose>, <when>, <otherwise>

用途:多条件分支(类似Java的switch-case)。

示例

<!-- 
动态条件查询用户信息
功能:根据传入的条件动态查询用户信息
参数:parameterType="map" 表示传入的参数是一个Map对象,可以包含多个条件
说明:
    1. SELECT * FROM users:从users表中查询所有列的数据。
    2. <where>:定义查询条件的开始,MyBatis会自动处理WHERE关键字的拼接。
    3. <choose>:类似于Java中的switch语句,用于条件选择。
    4. <when test="name != null">name = #{name}:当传入的name不为空时,拼接name = #{name}作为查询条件。
    5. <when test="age != null">age = #{age}:当传入的age不为空时,拼接age = #{age}作为查询条件。
    6. <otherwise>status = 1:当所有<when>条件都不满足时,拼接status = 1作为默认查询条件。
用法:在Mapper接口中定义对应的方法,例如:
    List<User> selectByCondition(Map<String, Object> params);
    参数params可以包含"name"或"age"键,也可以都不包含。
    返回一个包含符合条件的User对象列表。
注意:
    1. 如果传入多个条件,MyBatis会自动将它们拼接成AND连接的条件。
    2. 如果不需要默认条件,可以移除<otherwise>标签。
    3. 传递的参数类型为Map,便于动态传递查询条件。
    4. #{name}和#{age}是MyBatis的占位符,用于动态获取Map中的值。
    5. 如果需要更复杂的查询条件,可以结合使用<if>、<where>等动态SQL标签。
 -->
<select id="selectByCondition" parameterType="map" resultType="User">
  SELECT * FROM users
  <where>
    <choose>
      <when test="name != null">name = #{name}</when>
      <when test="age != null">age = #{age}</when>
      <otherwise>status = 1</otherwise>
    </choose>
  </where>
</select>

3. <foreach>

用途:遍历集合,常用于IN查询或批量操作。

示例:批量插入用户

<!-- 
批量插入用户信息
功能:将多个用户对象批量插入到users表中
参数:parameterType="list"指定传入的参数是一个用户对象列表
说明:
    1. INSERT INTO users (name, age) VALUES
        定义插入语句的目标表和字段,这里是name和age。
    2. <foreach item="user" collection="list" separator=",">
        - 标识这是一个批量操作。
        - collection="list"表示传入的参数是一个列表。
        - item="user"表示列表中的每个元素。
        - separator=","用于分隔每个插入的值。
    3. (#{user.name}, #{user.age})
        表示从每个用户对象中获取name和age属性值,并插入到数据库中。
    4. 此方法适用于需要批量插入多个用户记录的场景,可以显著提高插入效率。
使用方法:
    在Mapper接口中定义对应的方法,例如:
    int batchInsert(List<User> users);
    调用时传入一个User对象列表即可。
注意:
    1. 如果传入的用户列表为空,MyBatis将不会执行任何插入操作。
    2. 如果用户的数据库不支持批量插入,可能会导致插入失败或者性能问题。
    3. 如果需要插入多个字段,可以在values中添加更多的 #{user.xxx} 占位符。
 -->
<insert id="batchInsert" parameterType="list">
  INSERT INTO users (name, age) VALUES
  <foreach item="user" collection="list" separator=",">
    (#{user.name}, #{user.age})
  </foreach>
</insert>

四、复用SQL片段

1. <sql><include>

用途:定义可重用的SQL片段。

示例

<!-- 
定义SQL片段
功能:定义一个可重用的SQL片段,包含用户表的列名
说明:
    1. id="userColumns":定义这个SQL片段的唯一名称,用于在其他地方引用。
    2. 这个片段包含用户表的主要列名:id, name, age。
    3. 通过使用SQL片段,可以避免在多个查询中重复编写相同的列名。
    4. 如果需要按条件查询或动态列过滤,可以在此基础上进行扩展。
 -->
<sql id="userColumns">id, name, age</sql>

<!-- 
查询所有用户信息
功能:从 users 表中查询所有用户信息,并返回 User 对象列表
说明:
    1. id="getAllUsers":标识这个查询操作的唯一名称。
    2. resultType="User":指定查询结果的类型为 User 对象。
    3. <include refid="userColumns"/>:引用之前定义的SQL片段,避免重复编写列名。
    4. 这个查询会从 users 表中选择 id, name, age 列的所有数据。
用法:在Mapper接口中定义对应的方法,例如:
    List<User> getAllUsers();
    返回一个包含所有用户信息的User对象列表。
建议:
    1. 如果需要查询特定条件下的用户,可以在SQL中添加 WHERE 子句。
    2. 如果需要避免列名和别名冲突,可以在SQL片段中使用别名,例如:
        <sql id="userColumns">id AS user_id, name AS user_name, age AS user_age</sql>
    3. 对于查询结果的列数较多的情况,建议使用 resultMap 映射字段,以确保列名与对象属性正确对应。
 -->
<select id="getAllUsers" resultType="User">
  SELECT <include refid="userColumns"/> FROM users
</select>

五、参数处理

1. #{}${}

  • #{}:预编译参数(防SQL注入)
  • ${}:直接替换(慎用,如动态表名)

示例:动态排序

<!-- 
动态排序查询用户信息
功能:从 users 表中查询所有用户信息,并根据传入的 orderBy 参数进行排序
参数:orderBy(字符串类型)
注意:
    1. ${orderBy} 是 MyBatis 的动态 SQL 特性,用于将传入的参数直接拼接到 SQL 语句中,而不是通过预编译参数。
    2. 使用 ${} 时需要特别小心,因为它会直接将参数插入到 SQL 语句中,可能导致 SQL 注入漏洞。
    3. 如果 `orderBy` 参数未经过充分验证,可能会被恶意构造的 SQL 语句利用,对数据库造成危害。
建议:
    1. 在应用程序中,确保 `orderBy` 参数只能来源于受信任的来源,如预定义的有效排序字段。
    2. 对于不可信的输入,应使用白名单机制对 `orderBy` 参数进行验证,只允许指定的有效字段。
    3. 如果必须使用动态排序,可以考虑以下更安全的实现方式:
        - 使用枚举起有效的排序字段,并在代码中进行验证。
        - 或者,将 `orderBy` 参数替换为一个完整的 SQL 片段,但同样需要进行严格的验证和转义。
 -->
<select id="getUsersOrdered" resultType="User">
  SELECT * FROM users ORDER BY ${orderBy}
</select>

六、总结

拓展阅读:MyBatis映射文件 resultMap 元素详解与示例

MyBatis官方文档(mybatis.org)
在这里插入图片描述


http://www.kler.cn/a/549303.html

相关文章:

  • Flutter 常见布局模型
  • 【LeetCode】LCR 120. 寻找文件副本
  • 使用 pgvector 实现 PostgreSQL 语义搜索和 RAG:完整指南
  • DeepSeek R1 与 OpenAI O1:机器学习模型的巅峰对决
  • 关于防火墙运维面试题2
  • Unity3D 可视化脚本框架设计详解
  • Linux搭建ESP32开发环境
  • 线性代数中的正交和标准正交向量
  • DeepSeek 的开源优势:为什么选择它而不是其他闭源模型?
  • Spring Boot “约定大于配置”
  • 网络安全的现状如何?
  • Keepalived + Nginx 高可用负载均衡部署
  • 低代码组态软件-BY组态
  • nodejs 038: Js Worker线程消息传递 Worker.postMessage() Worker.postMessage()
  • 图像生成GAN和风格迁移
  • mysql读写分离与proxysql的结合
  • FOT(Forest-of-Thought):增强大型语言模型推理能力的新框架
  • Docker安装Kafka(不依赖ZooKeeper)
  • 【Linux】Ubuntu Linux 系统 ——PHP开发环境
  • Netty的基本架构详解