SQL 第五篇:SQL 如何真正接入 Spring Boot 项目(企业 Mapper 分层实战)

一、前言

前面四篇,我们已经学会了:

复制代码
CRUD
建表
表关系
JOIN

但到这里,其实还只是:

复制代码
数据库层面

真正的企业开发,还差最后一步:

❗ SQL 如何接入 Spring Boot 项目

很多初学者学 SQL 时有个问题:

复制代码
会写 SQL
不会落项目

比如:

  • SQL 写在哪里?
  • JOIN 写在哪里?
  • Service 能不能直接写 SQL?
  • MyBatis-Plus 到底干嘛的?
  • XML 为什么企业还在用?

这一篇,我们把这些问题一次讲透。


二、企业里的真实调用链

先看真实项目里的结构:

复制代码
Controller
   ↓
Service(业务 + 事务 + 缓存)
   ↓
QueryMapper(复杂 JOIN)
   ↓
Mapper(单表 CRUD)
   ↓
数据库

这一套非常重要。

后面你做 Spring Boot 项目,基本都会围绕这个结构展开。


三、为什么 SQL 不能写在 Service?

很多新手最开始会这样写:

java 复制代码
@Service
public class UserService {

    @Resource
    private JdbcTemplate jdbcTemplate;

    public UserDetailVO getUserDetail(Long id) {

        String sql = """
            SELECT ...
        """;

        return jdbcTemplate.queryForObject(sql, ...);
    }
}

虽然能跑。但问题很大:


1️⃣ Service 职责混乱

Service 本来应该负责:

复制代码
业务逻辑
事务
缓存

结果现在:

复制代码
SQL 也塞进来了

会越来越乱。


2️⃣ SQL 无法复用

以后别的接口也要查:

复制代码
用户详情

你只能复制 SQL。


3️⃣ JOIN SQL 很快会失控

企业里的 JOIN:

复制代码
几十行
上百行

Service 根本没法看。


四、企业里的正确做法:Mapper 分层

所以企业里通常会这样分:


1️⃣ Mapper(单表 CRUD)

负责:

复制代码
简单增删改查

例如:

java 复制代码
userMapper.selectById(id);

userMapper.insert(user);

2️⃣ QueryMapper(复杂 JOIN)

负责:

复制代码
联表查询
复杂 SQL
统计查询

例如:

java 复制代码
userQueryMapper.selectUserDetailById(id);

五、企业真实结构(推荐)

这里给你一个接近企业的结构。


user 模块

复制代码
user/
├── controller/
├── service/
├── converter/
├── model/
│   ├── dto/
│   ├── vo/
│   └── entity/
└── infrastructure/
    └── persistence/
        └── mapper/
            ├── UserMapper.java
            ├── UserQueryMapper.java
            └── xml/
                └── UserQueryMapper.xml

六、Mapper 到底干什么?


UserMapper.java

java 复制代码
@Mapper
public interface UserMapper {

    int insert(User user);

    User selectById(Long id);

    int updateById(User user);

    int deleteById(Long id);
}

这里:

复制代码
只做单表 CRUD

七、MyBatis-Plus 为什么企业喜欢用?

因为:

复制代码
单表 CRUD 太重复了

比如:

复制代码
insert
delete
update
selectById

几乎每张表都有。

所以 MyBatis-Plus 帮你自动生成。


示例

java 复制代码
public interface UserMapper
        extends BaseMapper<User> {
}

然后直接:

java 复制代码
userMapper.selectById(id);

userMapper.insert(user);

就能用。


八、为什么复杂 JOIN 企业还是喜欢 XML?

很多人第一次学 MyBatis-Plus 会以为:

复制代码
以后不用写 SQL 了

其实不是。


企业真实情况

简单 CRUD:

复制代码
MyBatis-Plus

复杂查询:

复制代码
XML

原因

因为 JOIN 很复杂。

例如:

java 复制代码
SELECT
    u.id,
    u.username,
    d.real_name,
    a.receiver_name,
    a.phone
FROM user u
LEFT JOIN user_detail d
    ON u.id = d.user_id
LEFT JOIN user_address a
    ON u.id = a.user_id
WHERE u.id = #{id}

这种 SQL:

复制代码
XML 更清晰
更容易维护
更容易优化

九、企业里的 QueryMapper


接口

java 复制代码
@Mapper
public interface UserQueryMapper {

    UserDetailVO selectUserDetailById(Long id);
}

XML

XML 复制代码
<select id="selectUserDetailById"
        resultType="com.example.vo.UserDetailVO">

    SELECT
        u.id,
        u.username,
        d.real_name,
        a.receiver_name,
        a.phone,
        a.detail_address
    FROM user u
    LEFT JOIN user_detail d
        ON u.id = d.user_id
    LEFT JOIN user_address a
        ON u.id = a.user_id
    WHERE u.id = #{id}

</select>

十、Service 真正该做什么?

Service 不负责写 SQL。

Service 负责:

复制代码
业务逻辑
事务
缓存
调用 Mapper

示例

java 复制代码
@Service
public class UserServiceImpl {

    @Resource
    private UserQueryMapper userQueryMapper;

    public UserDetailVO getUserDetail(Long id) {

        return userQueryMapper
                .selectUserDetailById(id);
    }
}

十一、企业里的缓存(Redis)

企业里通常不会每次都查数据库。

例如:

复制代码
用户详情页

访问频率非常高。

所以会:

复制代码
先查 Redis
没有再查数据库

示例

java 复制代码
public UserDetailVO getUserDetail(Long userId) {

    String key = "user:detail:" + userId;

    // 1. 查缓存
    UserDetailVO cached = redis.get(key);

    if (cached != null) {
        return cached;
    }

    // 2. 查数据库
    UserDetailVO vo =
            userQueryMapper.selectUserDetailById(userId);

    // 3. 写缓存
    redis.set(key, vo);

    return vo;
}

十二、这一篇真正的核心

这一篇最重要的不是:

复制代码
MyBatis-Plus
XML

而是:

❗ SQL 在企业里不是单独存在的

而是:

👉 进入"分层架构"


十三、企业里的 SQL 最终分工


CRUD

复制代码
MyBatis-Plus

JOIN

复制代码
XML

业务逻辑

复制代码
Service

事务

复制代码
@Transactional

缓存

复制代码
Redis

十四、一句话总结

企业里的 SQL:

👉 不是"随便写"

而是:

"分层 + 分职责 + 分复杂度"


下一篇

SQL 第六篇:索引入门(为什么你的查询越来越慢)

我们会真正讲透:

复制代码
索引
B+树
user_id 为什么加索引
EXPLAIN

以及:企业里到底哪些字段需要索引

相关推荐
TheRouter15 分钟前
AI Agent 记忆体系建设实战:短期、长期与工作记忆的工程实现
数据库·人工智能·oracle
Omics Pro23 分钟前
首个!外源天然产物综合性代谢图谱
数据库·人工智能·算法·机器学习·r语言
唐青枫29 分钟前
MySQL EXISTS 详解:存在性判断、NOT EXISTS 与实战示例
sql·mysql
憧憬成为java架构高手的小白1 小时前
苍穹外卖--day09
java·spring boot·百度
JAVA面经实录9171 小时前
Hibernate面试题库
数据库·oracle·hibernate
Jasonakeke2 小时前
SpringBoot自动配置原理揭秘
java·spring boot·后端
迷枫7122 小时前
DM8 目录结构与常用排查入口梳理
服务器·数据库
Ramble_Naylor3 小时前
东方通(TongWeb)SpringBoot开发指导
java·spring boot
Mr.Daozhi3 小时前
RAG 进阶实战:跑通 Demo 后我连续翻了 6 次车,逐一修复才真正可用(含 Gradio Web 版)
前端·数据库·langchain·大模型·gradio·rag·科研工具
小程故事多_803 小时前
Claude Code自定义workflow skills用法
数据库·人工智能·智能体