苍穹外卖Day04笔记

一、前端拼接的动态参数

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 参数,返回不同分类的菜品;
  • 同一个分页接口,通过 pagepageSize 参数,返回不同页的数据。

二、@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. 完整使用流程

  1. 定义注解:@AutoFill 标记需要填充的Mapper方法;

  2. 定义枚举:OperationType 区分INSERT/UPDATE;

  3. AOP切面拦截:通过反射为实体字段赋值;

  4. 标注使用:

    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)。

总结

  1. 事务与自动填充:@Transactional 保证数据一致性,@AutoFill 简化公共字段赋值;
  2. MyBatis 核心:XML属性需根据操作类型(增/查)合理配置,分页依赖PageHelper自动拦截SQL;
  3. 框架层面:SSM是基础框架组合,SpringBoot是其简化版,核心是自动配置和快速开发。
相关推荐
今儿敲了吗5 小时前
46| FBI树
数据结构·c++·笔记·学习·算法
苦瓜小生6 小时前
【黑马点评学习笔记 | 实战篇 】| 6-Redis消息队列
redis·笔记·后端
sheeta19987 小时前
LeetCode 每日一题笔记 日期:2025.03.19 题目:3212.统计X和Y频数相等的子矩阵数量
笔记·leetcode·矩阵
巧克力味的桃子8 小时前
国名排序题笔记(字符串函数 + fgets 详解)
笔记
四谎真好看8 小时前
Redis学习笔记(实战篇3)
redis·笔记·学习·学习笔记
bennybi8 小时前
Openclaw 实践笔记
笔记·ai·openclaw
AI视觉网奇8 小时前
aigc 生成几何图 整理笔记
笔记·aigc
今儿敲了吗9 小时前
python基础学习笔记第五章——容器
笔记·python·学习
三水不滴9 小时前
Elasticsearch 实战系列(二):SpringBoot 集成 Elasticsearch,从 0 到 1 实现商品搜索系统
经验分享·spring boot·笔记·后端·elasticsearch·搜索引擎