在 MyBatis / 通用“动态 SQL”场景里,复用的核心思路是:把“可变部分”和“公共部分”拆开,然后通过 include、片段、模板、参数化 等方式组合。下面按常见方案讲。
<sql> + <include>(最推荐)把公共 SQL 片段抽出来复用。
<sql id="Base_Column_List">
id, name, age, status
</sql>
<select id="selectUser" resultType="User">
SELECT
<include refid="Base_Column_List"/>
FROM user
WHERE 1=1
<if test="name != null">
AND name = #{name}
</if>
</select>
✅ 适合:
<sql> 片段MyBatis 支持 <include> 传参(3.4+)
<sql id="likeCondition">
AND ${column} LIKE CONCAT('%', #{value}, '%')
</sql>
<select id="search">
SELECT * FROM user
WHERE 1=1
<include refid="likeCondition">
<property name="column" value="name"/>
<property name="value" value="tom"/>
</include>
</select>
⚠️ ${column} 有 SQL 注入风险,只用于“列名/固定结构”
<where> / <set> 复用避免手写 1=1
<sql id="User_Where">
<if test="name != null">AND name = #{name}</if>
<if test="age != null">AND age = #{age}</if>
</sql>
<select id="list">
SELECT * FROM user
<where>
<include refid="User_Where"/>
</where>
</select>
<trim> 做通用拼装(高级复用)<trim prefix="WHERE" prefixOverrides="AND |OR ">
<include refid="User_Where"/>
</trim>
@SelectProvider)适合复杂、可复用逻辑
public class UserSqlProvider {
public String list(User u) {
return new SQL(){{
SELECT("*");
FROM("user");
if (u.getName() != null) WHERE("name = #{name}");
}}.toString();
}
}
✅ 好处:
public class SqlBuilder {
public static String where(User u) {
// 复用逻辑
}
}
<sql> 最常见<include refid="com.xxx.mapper.CommonMapper.Base_Column_List"/>
| 场景 | 推荐方案 |
|---|---|
| 字段列表 | <sql> |
| WHERE 条件 | <sql> + <where> |
| UPDATE 字段 | <sql> + <set> |
| 多表通用 | Provider |
| 跨模块 | 公共 Mapper |
${} → SQL 注入如果你用的是 MyBatis-Plus / JPA / 原生 JDBC,或者想看“真实业务例子”,可以告诉我具体技术栈。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。