MyBatis 动态 SQL、多表查询与注解开发详解
MyBatis 动态 SQL、多表查询与注解开发详解
1. MyBatis 动态 SQL
MyBatis 提供了强大的动态 SQL 功能,允许我们根据不同的条件拼接 SQL 语句,避免了手动拼接 SQL 的繁琐和错误。常见的动态 SQL 标签包括:
- if:用于条件判断,根据条件是否成立来决定是否拼接 SQL 片段。
- choose (when, otherwise):类似于 Java 中的 switch 语句,用于多选一的场景。
- where:用于拼接 WHERE 子句,并自动去除多余的 AND 或 OR。
- set:用于拼接 UPDATE 语句中的 SET 子句,并自动去除多余的逗号。
- foreach:用于遍历集合或数组,常用于 IN 查询。
1.1 if 标签
if 标签用于条件判断,根据条件是否成立来决定是否拼接 SQL 片段。例如:
<select id="queryLikeUserName" resultType="user">
select * from user where sex='男'
<if test="userName!=null and userName.trim()!=''">
and username like '%${userName}%'
</if>
</select>
解释:
test属性用于编写 OGNL 表达式,判断条件是否成立。- 如果
userName不为空且不为空字符串,则拼接and username like '%${userName}%'到 SQL 语句中。
1.2 choose 标签
choose 标签类似于 Java 中的 switch 语句,用于多选一的场景。例如:
<select id="queryByUserNameOrAddress" resultType="user">
select * from user where sex='男'
<choose>
<when test="userName!=null and userName.trim()!=''">
and username like '%${userName}%'
</when>
<when test="address!=null and address.trim()!=''">
and address = #{address}
</when>
<otherwise>
and username='孙悟空'
</otherwise>
</choose>
</select>
解释:
choose标签包含多个when子标签和一个otherwise子标签。- 每个
when子标签都有一个test属性,用于判断条件是否成立。 - 如果某个
when子标签的条件成立,则拼接对应的 SQL 片段。 - 如果所有
when子标签的条件都不成立,则拼接otherwise子标签中的 SQL 片段。
1.3 where 标签
where 标签用于拼接 WHERE 子句,并自动去除多余的 AND 或 OR。例如:
<select id="queryByUserNameAndAge" resultType="user">
SELECT * FROM user
<where>
<if test="userName != null and userName.trim()!=''">
username = #{userName}
</if>
<if test="address!=null and address.trim()!=''">
AND address = #{address}
</if>
</where>
</select>
解释:
where标签会自动在生成的 SQL 语句中添加WHERE关键字。- 如果
where标签内的条件都不成立,则不会添加WHERE关键字。 where标签会自动去除多余的AND或OR关键字。
1.4 set 标签
set 标签用于拼接 UPDATE 语句中的 SET 子句,并自动去除多余的逗号。例如:
<update id="updateSelectiveUser">
update user
<set>
<if test="username != null and username.trim()!=''">
username = #{username},
</if>
<if test="birthday != null">
birthday=#{birthday},
</if>
<if test="sex != null and sex.trim()!=''">
sex=#{sex},
</if>
<if test="address != null and address.trim()!=''">
address=#{address}
</if>
</set>
where id = #{id}
</update>
解释:
set标签会自动在生成的 SQL 语句中添加SET关键字。set标签会自动去除多余的逗号。
1.5 foreach 标签
foreach 标签用于遍历集合或数组,常用于 IN 查询。例如:
<select id="queryByIds" resultType="user">
SELECT * FROM user WHERE id IN
<foreach collection="arrIds" item="ID" separator="," open="(" close=")">
#{ID}
</foreach>
</select>
解释:
collection属性指定要遍历的集合或数组。item属性指定集合或数组中的每个元素的别名。separator属性指定每个元素之间的分隔符。open属性指定遍历开始时的字符串。close属性指定遍历结束时的字符串。
2. MyBatis 多表查询
MyBatis 支持多表查询,常见的多表关系包括一对一、一对多和多对多。通过 resultMap 可以灵活地处理多表查询的结果映射。
2.1 一对一查询
一对一查询通常用于查询主表数据及其关联的从表数据。例如,查询订单信息及其对应的用户信息:
<resultMap id="orderAndUserResultRelative" type="Order" autoMapping="true">
<id column="oid" property="id"/>
<association property="user" javaType="User" autoMapping="true">
<id column="uid" property="id"/>
</association>
</resultMap>
<select id="queryOrderAndUserByOrderNumber2" resultMap="orderAndUserResultRelative">
SELECT * FROM tb_order tbo
INNER JOIN tb_user tbu ON tbo.user_id = tbu.id
WHERE tbo.order_number = #{orderNumber}
</select>
解释:
resultMap标签用于定义结果集的映射关系。association标签用于定义一对一关联关系。id标签用于定义主键映射关系。result标签用于定义普通字段的映射关系。
2.2 一对多查询
一对多查询通常用于查询主表数据及其关联的多个从表数据。例如,查询用户信息及其对应的多个订单信息:
<resultMap id="oneToManyResult" type="User" autoMapping="true">
<id column="uid" property="id"/>
<collection property="orders" javaType="List" ofType="Order" autoMapping="true">
<id column="oid" property="id"/>
</collection>
</resultMap>
<select id="oneToManyQuery" resultMap="oneToManyResult">
SELECT * FROM tb_user tbu
INNER JOIN tb_order tbo ON tbu.id = tbo.user_id
WHERE tbu.id = #{id}
</select>
解释:
collection标签用于定义一对多关联关系。ofType属性指定集合中元素的类型。
3. MyBatis 注解开发
MyBatis 提供了基于注解的开发方式,可以简化 XML 配置文件的编写。常见的注解包括:
- @Insert:用于插入数据。
- @Update:用于更新数据。
- @Delete:用于删除数据。
- @Select:用于查询数据。
- @Options:用于配置主键回填等选项。
- @Results:用于结果集映射。
3.1 注解实现 CRUD
通过注解可以快速实现 CRUD 操作。例如:
@Insert("INSERT INTO tb_user VALUES(NULL,#{userName},#{password},#{name},#{age},#{sex})")
@Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id")
void saveUser(User user);
@Delete("DELETE FROM tb_user WHERE id = #{id}")
void deleteUserById(Long id);
@Update("UPDATE tb_user SET user_name=#{userName}, password=#{password}, name=#{name}, age=#{age}, sex=#{sex} WHERE id=#{id}")
void updateUser(User user);
@Select("SELECT * FROM tb_user")
List<User> queryAllUsers();
解释:
@Insert注解用于插入数据。@Options注解用于配置主键回填。@Delete注解用于删除数据。@Update注解用于更新数据。@Select注解用于查询数据。
3.2 注解实现动态 SQL
MyBatis 注解开发也支持动态 SQL,可以通过 @SelectProvider 注解来实现。例如:
@SelectProvider(type = ProviderUtils.class, method = "queryUsersBySexOrUsernameSQL")
List<User> queryUsersBySexOrUsername(@Param("sex") String sex, @Param("username") String username);
动态 SQL 生成类:
public class ProviderUtils {
public String queryUsersBySexOrUsernameSQL(@Param("sex") String sex, @Param("username") String username) {
String sql = "SELECT * FROM tb_user WHERE sex = #{sex}";
if (username != null && !"".equals(username)) {
sql += " AND user_name LIKE CONCAT('%', #{username}, '%')";
}
return sql;
}
}
解释:
@SelectProvider注解用于指定动态 SQL 生成类和方法。ProviderUtils类中的queryUsersBySexOrUsernameSQL方法用于生成动态 SQL。
4. 总结
MyBatis 提供了强大的动态 SQL 功能,能够根据不同的条件灵活拼接 SQL 语句。同时,MyBatis 支持多表查询,通过 resultMap 可以轻松处理一对一、一对多等复杂关系。注解开发方式进一步简化了 MyBatis 的配置,使得开发更加高效。通过合理使用动态 SQL 和注解,可以大大提升 MyBatis 的开发效率和代码的可维护性。
浙公网安备 33010602011771号