| name | lumina_mybatis_plus |
| description | Use this skill when writing database access code, creating Mapper interfaces, or writing SQL queries. This skill enforces MyBatis-Plus usage priority, SQL writing restrictions, and data persistence best practices. |
Lumina MyBatis-Plus 使用规范
功能概述
本技能包用于确保 Lumina 框架项目正确使用 MyBatis-Plus,包括基础 CRUD、复杂查询、分页、批量操作等。
核心原则
- 优先使用 MyBatis-Plus - 所有简单 CRUD 操作必须使用 MyBatis-Plus
- 复杂 SQL 才用 XML - 仅当 MyBatis-Plus 无法满足时,才使用 XML Mapper
- 禁止 SQL 函数和存储过程 - 不允许在 SQL 中编写函数、存储过程、触发器
- 业务逻辑在 Java 代码中 - 所有业务逻辑必须在 Java 代码中实现,不允许写在 SQL 中
MyBatis-Plus 基础使用
Mapper 接口
@Mapper
public interface AgentMapper extends BaseMapper<AgentDO> {
}
常用操作示例
条件查询
AgentDO agentDO = agentMapper.selectOne(
new LambdaQueryWrapper<AgentDO>()
.eq(AgentDO::getAgentName, agentName)
.eq(AgentDO::getDeleted, 0)
);
LambdaQueryWrapper<AgentDO> wrapper = new LambdaQueryWrapper<AgentDO>()
.eq(AgentDO::getDeleted, 0);
if (StringUtils.isNotBlank(dto.getAgentName())) {
wrapper.like(AgentDO::getAgentName, dto.getAgentName());
}
List<AgentDO> list = agentMapper.selectList(wrapper);
分页查询
Page<AgentDO> page = new Page<>(dto.getPageNum(), dto.getPageSize());
LambdaQueryWrapper<AgentDO> wrapper = new LambdaQueryWrapper<AgentDO>()
.eq(AgentDO::getDeleted, 0)
.orderByDesc(AgentDO::getCreateTime);
Page<AgentDO> result = agentMapper.selectPage(page, wrapper);
条件更新
agentMapper.update(null,
new LambdaUpdateWrapper<AgentDO>()
.set(AgentDO::getStatus, status.getValue())
.set(AgentDO::getUpdateTime, LocalDateTime.now())
.eq(AgentDO::getAgentId, agentId)
.eq(AgentDO::getDeleted, 0)
);
软删除
agentMapper.update(null,
new LambdaUpdateWrapper<AgentDO>()
.set(AgentDO::getDeleted, 1)
.set(AgentDO::getUpdateTime, LocalDateTime.now())
.eq(AgentDO::getAgentId, agentId)
);
何时使用 XML Mapper
✅ 可以使用 XML 的场景:
- 多表关联查询(JOIN)
- 复杂的子查询
- 统计聚合查询(GROUP BY、HAVING)
- 动态 SQL 条件过于复杂,QueryWrapper 难以表达
❌ 禁止使用 XML 的场景:
- 简单的 CRUD 操作(必须使用 MyBatis-Plus)
- 单表条件查询(必须使用 QueryWrapper)
- 包含 SQL 函数、存储过程、触发器
- 包含业务逻辑判断
SQL 编写禁止事项
禁止使用 SQL 函数
<select id="selectAgents">
SELECT
agent_id,
agent_name,
DATE_FORMAT(create_time, '%Y-%m-%d') AS createDate,
CONCAT(agent_name, '-', agent_type) AS displayName
FROM lumina_agent
</select>
替代方案: 在 Java 代码中处理日期格式化和字符串拼接
禁止使用存储过程和触发器
CREATE PROCEDURE get_agent_statistics(IN tenant_id BIGINT)
BEGIN
SELECT COUNT(*) FROM lumina_agent WHERE tenant_id = tenant_id;
END;
CREATE TRIGGER update_agent_time
BEFORE UPDATE ON lumina_agent
FOR EACH ROW
BEGIN
SET NEW.update_time = NOW();
END;
替代方案:
- 存储过程 → 使用 Java 代码 + MyBatis-Plus
- 触发器 → 使用 MyBatis-Plus 自动填充或 Java 代码处理
禁止在 SQL 中写业务逻辑
<select id="selectActiveAgents">
SELECT * FROM lumina_agent
WHERE deleted = 0
AND status = 1
AND (CASE
WHEN agent_type = 'PREMIUM' THEN create_time > DATE_SUB(NOW(), INTERVAL 30 DAY)
WHEN agent_type = 'BASIC' THEN create_time > DATE_SUB(NOW(), INTERVAL 7 DAY)
ELSE TRUE
END)
</select>
替代方案: 业务逻辑在 Java 代码中处理
实体类注解规范
@Data
@TableName("lumina_agent")
public class AgentDO {
@TableId(value = "agent_id", type = IdType.AUTO)
private Long agentId;
@TableField("agent_name")
private String agentName;
@TableLogic
@TableField("deleted")
private Integer deleted;
@TableField(value = "create_time", fill = FieldFill.INSERT)
private LocalDateTime createTime;
}
使用场景
- 创建 Mapper 接口时,优先使用 MyBatis-Plus
- 编写查询代码时,优先使用 QueryWrapper
- 需要复杂查询时,才使用 XML Mapper
- 代码审查时,检查是否违反 SQL 规范
检查清单
可用资源
references/mybatis-plus-guide.md: MyBatis-Plus 详细使用指南
examples/basic-crud.java: 基础 CRUD 示例
examples/complex-query.xml: 复杂查询 XML 示例
examples/bad-sql-examples.sql: 禁止的 SQL 示例