Skip to content

Mapper XML 查询规范

Forge 要求查询 SQL 写在 Mapper XML 中,而非在 Service 层用 LambdaQueryWrapper 构建。原因:DataScopeInterceptormapperMethod 精确匹配改写 SQL。

BaseMapper vs XML

场景使用方式
单表 selectByIdMyBatis-Plus BaseMapper
单表 insertBaseMapper
单表 updateByIdBaseMapper
单表 deleteByIdBaseMapper(逻辑删除)
多表关联查询Mapper XML
条件查询Mapper XML
分页查询Mapper XML

Mapper 接口

java
public interface OrderMapper extends BaseMapper<OrderEntity> {

    List<OrderVO> selectOrderPage(@Param("query") OrderQueryDTO query);

    OrderVO selectOrderDetail(@Param("id") Long id);
}

XML 文件位置

src/main/resources/com/mdframe/forge/business/order/mapper/OrderMapper.xml

路径与 Mapper 接口包名一致。

resultMap 定义

xml
<resultMap id="OrderVOMap" type="com.mdframe.forge.business.order.vo.OrderVO">
    <id property="id" column="id"/>
    <result property="orderNo" column="order_no"/>
    <result property="amount" column="amount"/>
    <result property="status" column="status"/>
    <result property="statusLabel" column="status_label"/>
    <result property="createByName" column="create_by_name"/>
    <result property="createTime" column="create_time"/>
</resultMap>

参数化查询

xml
<select id="selectOrderPage" resultMap="OrderVOMap">
    SELECT
        o.id, o.order_no, o.amount, o.status, o.create_time,
        d.dict_label AS status_label,
        u.nickname AS create_by_name
    FROM biz_order o
    LEFT JOIN sys_dict_data d ON d.dict_type = 'biz_order_status' AND d.dict_value = o.status AND d.del_flag = 0
    LEFT JOIN sys_user u ON u.id = o.create_by AND u.del_flag = 0
    WHERE o.del_flag = 0
    <if test="query.orderNo != null and query.orderNo != ''">
        AND o.order_no LIKE CONCAT('%', #{query.orderNo}, '%')
    </if>
    <if test="query.status != null and query.status != ''">
        AND o.status = #{query.status}
    </if>
    ORDER BY o.create_time DESC
</select>

#{} vs ${}

xml
<!-- 正确:#{} 预编译参数,防 SQL 注入 -->
WHERE username = #{username}

<!-- 禁止:${} 字符串拼接,SQL 注入风险 -->
WHERE username = '${username}'

${} 仅用于动态表名或排序字段,且必须白名单校验:

xml
<!-- 仅用于排序字段,Java 层已做白名单校验 -->
ORDER BY ${sortField} ${sortOrder}

逻辑删除过滤

XML 查询必须显式过滤 del_flag

xml
<!-- 正确 -->
WHERE o.del_flag = 0

<!-- 禁止:MyBatis-Plus 不会自动补全 XML 查询 -->
<!-- 缺少 del_flag 条件 -->

分页查询

分页查询使用 MyBatis-Plus 的 Page 对象:

java
// Service 层
Page<OrderEntity> page = new Page<>(pageNum, pageSize);
List<OrderVO> list = orderMapper.selectOrderPage(page, query);
return PageResult.of(list, page.getTotal());
xml
<!-- XML 中不需要写 LIMIT,MyBatis-Plus 分页插件自动追加 -->
<select id="selectOrderPage" resultMap="OrderVOMap">
    SELECT ... FROM biz_order o WHERE o.del_flag = 0
</select>

常见错误

错误原因
SQL 报错 Unknown column 'tenant_id'表缺少 tenant_id 字段
查询不到数据del_flag 条件缺失或 tenant_id = 0
数据权限不生效SQL 写在 Service 层而非 XML
SQL 注入使用了 ${} 拼接用户输入

Forge Admin — 基于 Vue3 + Spring Boot 的企业级后台管理框架