一、前端拼接的动态参数
1. 核心概念
前端拼接的动态参数,指前端在发起请求时,将可变的业务数据(如用户ID、菜品ID、页码等)以指定格式拼接到请求中,传递给后端接口,让后端能根据不同参数返回对应结果。
2. 常见拼接方式
| 请求方式 | 拼接形式 | 示例 |
|---|---|---|
| GET | URL查询参数(?key=value) | http://localhost:8080/dish/list?categoryId=1001&status=1 |
| POST/PUT | 请求体JSON(最常用) | {"name":"番茄炒蛋","price":18.9,"categoryId":1001} |
| 路径参数 | URL路径中(RESTful风格) | http://localhost:8080/dish/1001(1001为菜品ID) |
3. 核心作用
让同一个后端接口可以处理不同的业务场景,比如:
- 同一个菜品列表接口,通过不同的
categoryId参数,返回不同分类的菜品; - 同一个分页接口,通过
page和pageSize参数,返回不同页的数据。
二、@Transactional 注解
1. 核心作用
@Transactional 是 Spring 提供的事务管理注解,用于声明式事务控制,加在方法/类上,可让方法内的所有数据库操作满足「ACID」特性:
- 原子性(Atomicity):方法内的所有SQL操作要么全部成功,要么全部回滚;
- 一致性(Consistency):事务执行前后,数据的完整性约束不被破坏;
- 隔离性(Isolation):多个事务并发执行时,相互不干扰;
- 持久性(Durability):事务提交后,数据永久保存到数据库。
2. 关键使用规则
- 作用范围 :
- 加在方法上:仅该方法开启事务;
- 加在类上:该类所有方法都开启事务;
- 触发回滚 :默认只有抛出
RuntimeException(运行时异常)才会回滚,可通过rollbackFor指定异常类型(如@Transactional(rollbackFor = Exception.class)); - 适用场景:涉及多步数据库操作的业务(如下单:扣库存+生成订单、转账:扣A账户+加B账户)。
3. 示例
java
@Service
public class OrderServiceImpl implements OrderService {
// 下单方法开启事务,任意步骤失败则全部回滚
@Transactional(rollbackFor = Exception.class)
public void createOrder(OrderDTO orderDTO) {
// 1. 扣减库存
stockMapper.reduceStock(orderDTO.getDishId(), orderDTO.getNum());
// 2. 生成订单
orderMapper.insert(orderDTO);
// 3. 记录日志
logMapper.insert(orderDTO.getId());
}
}
三、@AutoFill(OperationType.INSERT) 注解
1. 核心含义
这是项目自定义的注解 (非Spring原生),结合AOP实现「公共字段自动填充」,OperationType.INSERT 表示当前标注的方法是插入操作,切面会自动为实体类填充指定公共字段。
2. 字段填充规则
| 操作类型 | 自动填充的字段 | 填充值来源 |
|---|---|---|
| INSERT | createTime、updateTime | 当前系统时间(LocalDateTime.now()) |
| INSERT | createUser、updateUser | 当前登录用户ID(从ThreadLocal中获取) |
| UPDATE | updateTime、updateUser | 同上(仅更新这两个字段) |
3. 完整使用流程
-
定义注解:
@AutoFill标记需要填充的Mapper方法; -
定义枚举:
OperationType区分INSERT/UPDATE; -
AOP切面拦截:通过反射为实体字段赋值;
-
标注使用:
java// Mapper接口中,插入菜品方法标注INSERT @AutoFill(OperationType.INSERT) void insert(Dish dish);
四、MyBatis XML 中 resultType/parameterType
1. parameterType="Dish"
-
含义 :指定Mapper方法传入参数的类型为
Dish实体类; -
使用场景 :
- 当参数是自定义实体类/复杂对象时,建议显式声明(增强可读性);
- 当参数是简单类型(int、String、Long)时,可省略(MyBatis自动识别);
-
示例 :
xml<!-- 传入参数为Dish对象,parameterType指定类型 --> <insert id="insert" parameterType="Dish"> INSERT INTO dish (name, price, category_id) VALUES (#{name}, #{price}, #{categoryId}) </insert>
2. resultType="Dish"
-
含义 :指定Mapper方法返回值的类型为
Dish实体类(MyBatis会将查询结果映射为该类的对象); -
使用场景 :
- 必须声明(除非用resultMap),否则MyBatis无法知道如何封装查询结果;
- 如果返回List(如
List<Dish>),resultType仍写泛型类型(Dish),而非List;
-
示例 :
xml<!-- 返回结果封装为Dish对象,resultType指定类型 --> <select id="selectById" parameterType="Long" resultType="Dish"> SELECT * FROM dish WHERE id = #{id} </select>
五、分页原理 & PageHelper 使用
1. 分页核心原理
数据库层面通过 LIMIT 关键字实现分页,公式:
LIMIT 起始偏移量, 每页条数
起始偏移量 = (页码 - 1) * 每页条数
示例:查询第2页、每页10条数据 → LIMIT 10, 10(跳过前10条,取10条)。
2. PageHelper 详细使用步骤
步骤1:引入依赖(SpringBoot)
xml
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.6</version>
</dependency>
步骤2:代码中使用
java
@Service
public class DishServiceImpl implements DishService {
@Override
public PageInfo<Dish> pageQuery(Integer page, Integer pageSize, Long categoryId) {
// 1. 设置分页参数(核心:必须放在查询方法前)
PageHelper.startPage(page, pageSize);
// 2. 执行普通查询(PageHelper自动拦截并拼接LIMIT)
List<Dish> dishList = dishMapper.selectByCategoryId(categoryId);
// 3. 封装分页结果(包含总条数、总页数、当前页数据等)
PageInfo<Dish> pageInfo = new PageInfo<>(dishList);
return pageInfo;
}
}
步骤3:关键说明
- PageHelper 是自动拦截 的:它是MyBatis的插件,通过拦截器(Interceptor)在SQL执行前拼接
LIMIT关键字; - 仅对紧邻的下一条查询语句 生效(多次查询需多次调用
startPage); - 支持多数据库(MySQL/Oracle等),自动适配分页语法。
六、MyBatis XML 核心属性(useGeneratedKeys/keyProperty等)
1. 各属性作用 & 使用场景
| 属性 | 作用 | 何时需要 | 何时不需要 |
|---|---|---|---|
| parameterType | 指定入参类型 | 1. 入参是自定义实体类;2. 增强代码可读性 | 1. 入参是简单类型(int/String);2. 用注解指定参数 |
| useGeneratedKeys | 开启主键自增回写 | 插入操作,且数据库主键是自增(如MySQL的AUTO_INCREMENT) | 1. 非插入操作;2. 主键手动赋值(如UUID) |
| keyProperty | 指定自增主键回写到实体的哪个字段 | 开启useGeneratedKeys后必须指定 | 未开启useGeneratedKeys时 |
| resultType | 指定返回值类型 | 所有查询操作(select) | 1. 用resultMap替代;2. 非查询操作(insert/update/delete) |
2. 示例(插入并回写自增ID)
xml
<!-- 插入菜品,自增ID回写到Dish的id字段 -->
<insert id="insert" parameterType="Dish" useGeneratedKeys="true" keyProperty="id">
INSERT INTO dish (name, price, category_id) VALUES (#{name}, #{price}, #{categoryId})
</insert>
3. XML 文件归属
MyBatis 的 XML 文件是SQL映射文件 ,隶属于MyBatis框架,作用是将SQL与Java代码解耦,通常放在 resources/mapper 目录下,与Mapper接口一一对应。
七、SSM & SpringBoot 核心说明
1. SSM 组成
SSM是三个Java后端框架的整合:
- S:Spring → 核心容器,负责对象创建、依赖注入(IOC)、事务管理等;
- S:SpringMVC → Web层框架,处理HTTP请求、参数接收、响应返回;
- M:MyBatis → 持久层框架,简化数据库操作(替代JDBC)。
2. SpringBoot 核心作用
SpringBoot是Spring的快速开发脚手架,解决SSM整合的痛点:
| 核心优势 | 具体说明 |
|---|---|
| 自动配置 | 无需手动编写XML配置(如数据源、MyBatis、SpringMVC),框架自动适配; |
| 起步依赖 | 一个依赖(如spring-boot-starter-web)包含所有相关jar包,避免版本冲突; |
| 内置服务器 | 内置Tomcat,无需手动部署,直接运行jar包即可启动项目; |
| 简化开发 | 快速搭建、快速部署、快速调试,大幅降低SSM整合的复杂度。 |
3. 核心区别
- SSM:需要手动整合三大框架,编写大量XML配置,开发效率低;
- SpringBoot:零配置/少配置,开箱即用,是目前Java后端主流开发方式(苍穹外卖基于SpringBoot)。
总结
- 事务与自动填充:
@Transactional保证数据一致性,@AutoFill简化公共字段赋值; - MyBatis 核心:XML属性需根据操作类型(增/查)合理配置,分页依赖PageHelper自动拦截SQL;
- 框架层面:SSM是基础框架组合,SpringBoot是其简化版,核心是自动配置和快速开发。