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

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

相关推荐
dfdfadffa7 小时前
如何用模块化方案组织一个可扩展的前端组件库项目
jvm·数据库·python
2301_812539678 小时前
SQL中如何高效实现分组数据的批量更新_利用窗口函数与JOIN
jvm·数据库·python
2501_901200538 小时前
如何实现SQL存储过程存储过程参数标准化_统一命名规范
jvm·数据库·python
运气好好的8 小时前
Golang怎么用embed嵌入SQL文件_Golang如何将SQL迁移文件嵌入Go程序统一管理【技巧】
jvm·数据库·python
想学习java初学者8 小时前
SpringBoot整合Vertx-Mqtt多租户(优化版)
java·spring boot·后端
念何架构之路9 小时前
MySql常见ORM
数据库·mysql
xcLeigh9 小时前
KES数据库安全、权限、审计实战
数据库·安全·备份·权限·审计·ssl加密·密码策略
zjy2777710 小时前
c++如何实现日志文件的异步落盘功能_基于无锁队列方案【附代码】
jvm·数据库·python
河阿里10 小时前
SQL:深分页问题深度解析
数据库·sql