在复杂业务场景中,SQL查询往往需要动态拼接条件、复用代码片段,并支持批量操作。MyBatis的动态SQL功能提供了强大的解决方案,本文将深入解析
条件分支、
片段复用、批量操作优化等核心技巧,助你写出高效、可维护的SQL映射。
假设需要实现一个商品查询接口,支持以下条件组合:
<select id="selectGoods" resultType="Goods">
SELECT * FROM goods
<where>
<choose>
<when test="name != null">
AND name LIKE CONCAT('%', #{name}, '%')
when>
<when test="minPrice != null and maxPrice != null">
AND price BETWEEN #{minPrice} AND #{maxPrice}
when>
<when test="status != null">
AND status = #{status}
when>
<otherwise>
AND is_deleted = 0
otherwise>
choose>
where>
select>
标签内按顺序匹配第一个满足的
条件
均不满足,则执行
标签自动处理前缀AND/OR及空条件多个查询需要复用以下内容:
<sql id="Base_Column_List">
id, name, price, status, create_time
sql>
<sql id="Common_Where">
AND is_deleted = 0
sql>
<select id="selectGoodsList" resultType="Goods">
SELECT
<include refid="Base_Column_List"/>
FROM goods
<where>
<include refid="Common_Where"/>
<if test="categoryId != null">
AND category_id = #{categoryId}
if>
where>
select>
<sql id="Price_Filter">
<if test="minPrice != null">
AND price >= #{minPrice}
if>
<if test="maxPrice != null">
AND price <= #{maxPrice}
if>
sql>
<select id="selectByPrice" resultType="Goods">
SELECT * FROM goods
<where>
<include refid="Common_Where"/>
<include refid="Price_Filter"/>
where>
select>
<insert id="insertGoods" parameterType="Goods">
INSERT INTO goods (name, price) VALUES (#{name}, #{price})
insert>
Java调用:
for (Goods goods : list) {
goodsMapper.insertGoods(goods);
}
<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO goods (name, price) VALUES
<foreach collection="list" item="item" separator=",">
(#{item.name}, #{item.price})
foreach>
insert>
<update id="batchUpdatePrice" parameterType="java.util.List">
<foreach collection="list" item="item" separator=";">
UPDATE goods
SET price = #{item.newPrice}
WHERE id = #{item.id}
foreach>
update>
在JDBC URL中添加批处理参数:
jdbc.url=jdbc:mysql://localhost:3306/mydb?rewriteBatchedStatements=true
MyBatis全局配置启用批量模式:
<settings>
<setting name="defaultExecutorType" value="BATCH"/>
settings>
减少动态SQL嵌套:
中嵌套其他动态标签合理使用缓存:
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
批量操作最佳实践:
try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
GoodsMapper mapper = session.getMapper(GoodsMapper.class);
for (Goods goods : list) {
mapper.update(goods);
}
session.commit();
}
// GoodsMapper.java
public interface GoodsMapper {
List<Goods> selectGoods(@Param("name") String name,
@Param("minPrice") BigDecimal minPrice,
@Param("maxPrice") BigDecimal maxPrice,
@Param("status") Integer status);
int batchInsert(@Param("list") List<Goods> goodsList);
}
<mapper namespace="com.example.mapper.GoodsMapper">
<sql id="Base_Column_List">
id, name, price, status, create_time
sql>
<select id="selectGoods" resultType="Goods">
SELECT
<include refid="Base_Column_List"/>
FROM goods
<where>
<choose>
<when test="name != null">
name LIKE CONCAT('%', #{name}, '%')
when>
<when test="minPrice != null and maxPrice != null">
price BETWEEN #{minPrice} AND #{maxPrice}
when>
<otherwise>
status = 1
otherwise>
choose>
where>
select>
<insert id="batchInsert" parameterType="list">
INSERT INTO goods (name, price) VALUES
<foreach collection="list" item="item" separator=",">
(#{item.name}, #{item.price})
foreach>
insert>
mapper>
技术点 | 适用场景 | 性能影响 | 最佳实践 |
---|---|---|---|
|
多条件分支选择 | 低 | 优先处理高频条件 |
复用 |
字段/条件复用 | 中 | 避免过度抽象 |
批量插入 | 大数据量写入 | 高 | 配合JDBC批处理参数 |
动态SQL缓存 | 重复执行的动态查询 | 高 | 设置合理的flushInterval |
通过灵活运用MyBatis的动态SQL特性,可显著提升复杂查询场景的开发效率和运行性能。实际开发中需根据数据量、查询复杂度、并发量等因素综合选择优化策略。
mybatis基础专栏就结束啦,期待下我下专栏mybatis进阶,感情到一定阶段了,可以深入了解一下了!