MyBatis SQL映射深度解析:从CRUD到动态SQL实战

一、CRUD操作基础

MyBatis的核心功能是通过SQL映射实现数据库操作,我们先从基础的CRUD操作开始。

1. select查询操作

基础查询示例

<select id="selectUser" resultType="User">
  SELECT * FROM users WHERE id = #{id}
</select>

多参数查询

<select id="selectUsersByCondition" resultType="User">
  SELECT * FROM users 
  WHERE name = #{name} AND age > #{age}
</select>

实践建议

  • 对于简单查询,优先使用resultType自动映射
  • 复杂查询建议使用resultMap进行显式映射
  • 避免使用SELECT *,明确列出所需字段

2. insert插入操作

基础插入

<insert id="insertUser" parameterType="User">
  INSERT INTO users(name, age) 
  VALUES(#{name}, #{age})
</insert>

获取自增主键

<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
  INSERT INTO users(name, age) VALUES(#{name}, #{age})
</insert>

3. update更新操作

<update id="updateUser" parameterType="User">
  UPDATE users 
  SET name=#{name}, age=#{age}
  WHERE id=#{id}
</update>

4. delete删除操作

<delete id="deleteUser">
  DELETE FROM users WHERE id=#{id}
</delete>

二、动态SQL实战

MyBatis最强大的特性之一就是动态SQL,它允许我们在XML中构建灵活的SQL语句。

1. if条件判断

<select id="findActiveUsers" resultType="User">
  SELECT * FROM users
  WHERE status = 'ACTIVE'
  <if test="name != null">
    AND name like #{name}
  </if>
  <if test="age != null">
    AND age = #{age}
  </if>
</select>

2. choose/when/otherwise多重选择

<select id="findUsers" resultType="User">
  SELECT * FROM users
  WHERE status = 'ACTIVE'
  <choose>
    <when test="name != null">
      AND name like #{name}
    </when>
    <when test="age != null">
      AND age = #{age}
    </when>
    <otherwise>
      AND role = 'DEFAULT'
    </otherwise>
  </choose>
</select>

3. where/set/trim智能处理

where标签自动处理AND/OR前缀:

<select id="findUsers" resultType="User">
  SELECT * FROM users
  <where>
    <if test="name != null">
      name like #{name}
    </if>
    <if test="age != null">
      AND age = #{age}
    </if>
  </where>
</select>

set标签用于更新操作:

<update id="updateUser">
  UPDATE users
  <set>
    <if test="name != null">name=#{name},</if>
    <if test="age != null">age=#{age},</if>
  </set>
  WHERE id=#{id}
</update>

4. foreach遍历集合

<select id="selectUsersInIds" resultType="User">
  SELECT * FROM users
  WHERE id IN
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
    #{item}
  </foreach>
</select>

5. bind创建变量

<select id="selectUsers" resultType="User">
  <bind name="pattern" value="'%' + name + '%'" />
  SELECT * FROM users
  WHERE name LIKE #{pattern}
</select>

三、参数处理进阶

1. 各种参数类型示例

简单参数

User selectUser(@Param("id") int id);

对象参数

int insertUser(User user);

Map参数

List<User> selectUsers(Map<String, Object> params);

2. @Param注解使用场景

User selectUser(@Param("id") int id, @Param("name") String name);

对应的XML:

<select id="selectUser" resultType="User">
  SELECT * FROM users 
  WHERE id = #{id} AND name = #{name}
</select>

3. 参数类型处理器

MyBatis内置了常见类型的处理器,如:

  • StringTypeHandler
  • IntegerTypeHandler
  • DateTypeHandler

自定义类型处理器

@MappedTypes(PhoneNumber.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class PhoneTypeHandler extends BaseTypeHandler<PhoneNumber> {
  // 实现抽象方法
}

四、结果映射详解

1. 自动映射 vs 显式映射

自动映射

<select id="selectUsers" resultType="User">
  SELECT id, name, age FROM users
</select>

显式映射

<resultMap id="userResultMap" type="User">
  <id property="id" column="user_id"/>
  <result property="name" column="user_name"/>
  <result property="age" column="user_age"/>
</resultMap>

2. 关联查询(association)

<resultMap id="blogResultMap" type="Blog">
  <id property="id" column="blog_id"/>
  <result property="title" column="blog_title"/>
  <association property="author" javaType="Author">
    <id property="id" column="author_id"/>
    <result property="name" column="author_name"/>
  </association>
</resultMap>

3. 集合查询(collection)

<resultMap id="blogResultMap" type="Blog">
  <id property="id" column="blog_id"/>
  <result property="title" column="blog_title"/>
  <collection property="comments" ofType="Comment">
    <id property="id" column="comment_id"/>
    <result property="content" column="comment_content"/>
  </collection>
</resultMap>

4. 鉴别器(discriminator)

<resultMap id="vehicleResult" type="Vehicle">
  <id property="id" column="id"/>
  <discriminator javaType="int" column="vehicle_type">
    <case value="1" resultMap="carResult"/>
    <case value="2" resultMap="truckResult"/>
  </discriminator>
</resultMap>

五、最佳实践总结

  1. SQL可读性:保持XML中的SQL格式良好,适当换行和缩进
  2. 参数安全:始终使用#{}防止SQL注入,${}仅用于动态表名/列名
  3. 结果映射:复杂对象关系使用显式resultMap
  4. 动态SQL:合理使用动态SQL标签,避免过度复杂化
  5. 性能考虑:大批量操作考虑使用批处理模式

图1

通过掌握这些SQL映射技术,你将能够高效地使用MyBatis进行数据库操作,构建灵活且高性能的数据访问层。

添加新评论