Browse Source

perf:【INFRA 基础设施】vben5-antd-schema 主主子表inner代码生成时,可生成批量删除

puhui999 5 tháng trước cách đây
mục cha
commit
05bf229a3c

+ 124 - 0
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/inner/Demo03StudentInnerController.java

@@ -0,0 +1,124 @@
+package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.inner;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.inner.vo.Demo03StudentInnerPageReqVO;
+import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.inner.vo.Demo03StudentInnerRespVO;
+import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.inner.vo.Demo03StudentInnerSaveReqVO;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO;
+import cn.iocoder.yudao.module.infra.service.demo.demo03.inner.Demo03StudentInnerService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 学生")
+@RestController
+@RequestMapping("/infra/demo03-student-inner")
+@Validated
+public class Demo03StudentInnerController {
+
+    @Resource
+    private Demo03StudentInnerService demo03StudentInnerService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建学生")
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:create')")
+    public CommonResult<Long> createDemo03Student(@Valid @RequestBody Demo03StudentInnerSaveReqVO createReqVO) {
+        return success(demo03StudentInnerService.createDemo03Student(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新学生")
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:update')")
+    public CommonResult<Boolean> updateDemo03Student(@Valid @RequestBody Demo03StudentInnerSaveReqVO updateReqVO) {
+        demo03StudentInnerService.updateDemo03Student(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除学生")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
+    public CommonResult<Boolean> deleteDemo03Student(@RequestParam("id") Long id) {
+        demo03StudentInnerService.deleteDemo03Student(id);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete-batch")
+    @Parameter(name = "ids", description = "编号", required = true)
+    @Operation(summary = "批量删除学生")
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')")
+    public CommonResult<Boolean> deleteDemo03Student(@RequestParam("ids") List<Long> ids) {
+        demo03StudentInnerService.deleteDemo03StudentByIds(ids);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得学生")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
+    public CommonResult<Demo03StudentInnerRespVO> getDemo03Student(@RequestParam("id") Long id) {
+        Demo03StudentDO demo03Student = demo03StudentInnerService.getDemo03Student(id);
+        return success(BeanUtils.toBean(demo03Student, Demo03StudentInnerRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得学生分页")
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
+    public CommonResult<PageResult<Demo03StudentInnerRespVO>> getDemo03StudentPage(@Valid Demo03StudentInnerPageReqVO pageReqVO) {
+        PageResult<Demo03StudentDO> pageResult = demo03StudentInnerService.getDemo03StudentPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, Demo03StudentInnerRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出学生 Excel")
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportDemo03StudentExcel(@Valid Demo03StudentInnerPageReqVO pageReqVO,
+                                         HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<Demo03StudentDO> list = demo03StudentInnerService.getDemo03StudentPage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "学生.xls", "数据", Demo03StudentInnerRespVO.class,
+                BeanUtils.toBean(list, Demo03StudentInnerRespVO.class));
+    }
+
+    // ==================== 子表(学生课程) ====================
+
+    @GetMapping("/demo03-course/list-by-student-id")
+    @Operation(summary = "获得学生课程列表")
+    @Parameter(name = "studentId", description = "学生编号")
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
+    public CommonResult<List<Demo03CourseDO>> getDemo03CourseListByStudentId(@RequestParam("studentId") Long studentId) {
+        return success(demo03StudentInnerService.getDemo03CourseListByStudentId(studentId));
+    }
+
+    // ==================== 子表(学生班级) ====================
+
+    @GetMapping("/demo03-grade/get-by-student-id")
+    @Operation(summary = "获得学生班级")
+    @Parameter(name = "studentId", description = "学生编号")
+    @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')")
+    public CommonResult<Demo03GradeDO> getDemo03GradeByStudentId(@RequestParam("studentId") Long studentId) {
+        return success(demo03StudentInnerService.getDemo03GradeByStudentId(studentId));
+    }
+
+}

+ 33 - 0
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/inner/vo/Demo03StudentInnerPageReqVO.java

@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.inner.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 学生分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class Demo03StudentInnerPageReqVO extends PageParam {
+
+    @Schema(description = "名字", example = "芋艿")
+    private String name;
+
+    @Schema(description = "性别")
+    private Integer sex;
+
+    @Schema(description = "简介", example = "随便")
+    private String description;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 42 - 0
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/inner/vo/Demo03StudentInnerRespVO.java

@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.inner.vo;
+
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 学生 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class Demo03StudentInnerRespVO {
+
+    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8525")
+    @ExcelProperty("编号")
+    private Long id;
+
+    @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
+    @ExcelProperty("名字")
+    private String name;
+
+    @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty(value = "性别", converter = DictConvert.class)
+    @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+    private Integer sex;
+
+    @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("出生日期")
+    private LocalDateTime birthday;
+
+    @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "随便")
+    @ExcelProperty("简介")
+    private String description;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 42 - 0
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/inner/vo/Demo03StudentInnerSaveReqVO.java

@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.inner.vo;
+
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Schema(description = "管理后台 - 学生新增/修改 Request VO")
+@Data
+public class Demo03StudentInnerSaveReqVO {
+
+    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8525")
+    private Long id;
+
+    @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
+    @NotEmpty(message = "名字不能为空")
+    private String name;
+
+    @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "性别不能为空")
+    private Integer sex;
+
+    @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "出生日期不能为空")
+    private LocalDateTime birthday;
+
+    @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "随便")
+    @NotEmpty(message = "简介不能为空")
+    private String description;
+
+    @Schema(description = "学生课程列表")
+    private List<Demo03CourseDO> demo03Courses;
+
+    @Schema(description = "学生班级")
+    private Demo03GradeDO demo03Grade;
+
+}

+ 29 - 0
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/inner/Demo03CourseInnerMapper.java

@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.inner;
+
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 学生课程 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface Demo03CourseInnerMapper extends BaseMapperX<Demo03CourseDO> {
+
+    default List<Demo03CourseDO> selectListByStudentId(Long studentId) {
+        return selectList(Demo03CourseDO::getStudentId, studentId);
+    }
+
+    default int deleteByStudentId(Long studentId) {
+        return delete(Demo03CourseDO::getStudentId, studentId);
+    }
+
+    default int deleteByStudentIds(List<Long> studentIds) {
+        return delete(Demo03CourseDO::getStudentId, studentIds);
+    }
+
+}

+ 29 - 0
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/inner/Demo03GradeInnerMapper.java

@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.inner;
+
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 学生班级 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface Demo03GradeInnerMapper extends BaseMapperX<Demo03GradeDO> {
+
+    default Demo03GradeDO selectByStudentId(Long studentId) {
+        return selectOne(Demo03GradeDO::getStudentId, studentId);
+    }
+
+    default int deleteByStudentId(Long studentId) {
+        return delete(Demo03GradeDO::getStudentId, studentId);
+    }
+
+    default int deleteByStudentIds(List<Long> studentIds) {
+        return delete(Demo03GradeDO::getStudentId, studentIds);
+    }
+
+}

+ 27 - 0
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/inner/Demo03StudentInnerMapper.java

@@ -0,0 +1,27 @@
+package cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.inner;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.inner.vo.Demo03StudentInnerPageReqVO;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 学生 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface Demo03StudentInnerMapper extends BaseMapperX<Demo03StudentDO> {
+
+    default PageResult<Demo03StudentDO> selectPage(Demo03StudentInnerPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<Demo03StudentDO>()
+                .likeIfPresent(Demo03StudentDO::getName, reqVO.getName())
+                .eqIfPresent(Demo03StudentDO::getSex, reqVO.getSex())
+                .eqIfPresent(Demo03StudentDO::getDescription, reqVO.getDescription())
+                .betweenIfPresent(Demo03StudentDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(Demo03StudentDO::getId));
+    }
+
+}

+ 85 - 0
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo03/inner/Demo03StudentInnerService.java

@@ -0,0 +1,85 @@
+package cn.iocoder.yudao.module.infra.service.demo.demo03.inner;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.inner.vo.Demo03StudentInnerPageReqVO;
+import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.inner.vo.Demo03StudentInnerSaveReqVO;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO;
+import jakarta.validation.Valid;
+
+import java.util.List;
+
+/**
+ * 学生 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface Demo03StudentInnerService {
+
+    /**
+     * 创建学生
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createDemo03Student(@Valid Demo03StudentInnerSaveReqVO createReqVO);
+
+    /**
+     * 更新学生
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateDemo03Student(@Valid Demo03StudentInnerSaveReqVO updateReqVO);
+
+    /**
+     * 删除学生
+     *
+     * @param id 编号
+     */
+    void deleteDemo03Student(Long id);
+
+    /**
+     * 批量删除学生
+     *
+     * @param ids 编号
+     */
+    void deleteDemo03StudentByIds(List<Long> ids);
+
+    /**
+     * 获得学生
+     *
+     * @param id 编号
+     * @return 学生
+     */
+    Demo03StudentDO getDemo03Student(Long id);
+
+    /**
+     * 获得学生分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 学生分页
+     */
+    PageResult<Demo03StudentDO> getDemo03StudentPage(Demo03StudentInnerPageReqVO pageReqVO);
+
+    // ==================== 子表(学生课程) ====================
+
+    /**
+     * 获得学生课程列表
+     *
+     * @param studentId 学生编号
+     * @return 学生课程列表
+     */
+    List<Demo03CourseDO> getDemo03CourseListByStudentId(Long studentId);
+
+    // ==================== 子表(学生班级) ====================
+
+    /**
+     * 获得学生班级
+     *
+     * @param studentId 学生编号
+     * @return 学生班级
+     */
+    Demo03GradeDO getDemo03GradeByStudentId(Long studentId);
+
+}

+ 175 - 0
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo03/inner/Demo03StudentInnerServiceImpl.java

@@ -0,0 +1,175 @@
+package cn.iocoder.yudao.module.infra.service.demo.demo03.inner;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.inner.vo.Demo03StudentInnerPageReqVO;
+import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.inner.vo.Demo03StudentInnerSaveReqVO;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO;
+import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO;
+import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.inner.Demo03CourseInnerMapper;
+import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.inner.Demo03GradeInnerMapper;
+import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.inner.Demo03StudentInnerMapper;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.DEMO03_STUDENT_NOT_EXISTS;
+
+/**
+ * 学生 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class Demo03StudentInnerServiceImpl implements Demo03StudentInnerService {
+
+    @Resource
+    private Demo03StudentInnerMapper demo03StudentInnerMapper;
+    @Resource
+    private Demo03CourseInnerMapper demo03CourseInnerMapper;
+    @Resource
+    private Demo03GradeInnerMapper demo03GradeInnerMapper;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Long createDemo03Student(Demo03StudentInnerSaveReqVO createReqVO) {
+        // 插入
+        Demo03StudentDO demo03Student = BeanUtils.toBean(createReqVO, Demo03StudentDO.class);
+        demo03StudentInnerMapper.insert(demo03Student);
+
+        // 插入子表
+        createDemo03CourseList(demo03Student.getId(), createReqVO.getDemo03Courses());
+        createDemo03Grade(demo03Student.getId(), createReqVO.getDemo03Grade());
+        // 返回
+        return demo03Student.getId();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateDemo03Student(Demo03StudentInnerSaveReqVO updateReqVO) {
+        // 校验存在
+        validateDemo03StudentExists(updateReqVO.getId());
+        // 更新
+        Demo03StudentDO updateObj = BeanUtils.toBean(updateReqVO, Demo03StudentDO.class);
+        demo03StudentInnerMapper.updateById(updateObj);
+
+        // 更新子表
+        updateDemo03CourseList(updateReqVO.getId(), updateReqVO.getDemo03Courses());
+        updateDemo03Grade(updateReqVO.getId(), updateReqVO.getDemo03Grade());
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteDemo03Student(Long id) {
+        // 校验存在
+        validateDemo03StudentExists(id);
+        // 删除
+        demo03StudentInnerMapper.deleteById(id);
+
+        // 删除子表
+        deleteDemo03CourseByStudentId(id);
+        deleteDemo03GradeByStudentId(id);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteDemo03StudentByIds(List<Long> ids) {
+        // 校验存在
+        validateDemo03StudentExists(ids);
+        // 删除
+        demo03StudentInnerMapper.deleteByIds(ids);
+
+        // 删除子表
+        deleteDemo03CourseByStudentIds(ids);
+        deleteDemo03GradeByStudentIds(ids);
+    }
+
+    private void validateDemo03StudentExists(List<Long> ids) {
+        List<Demo03StudentDO> list = demo03StudentInnerMapper.selectByIds(ids);
+        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
+            throw exception(DEMO03_STUDENT_NOT_EXISTS);
+        }
+    }
+
+    private void validateDemo03StudentExists(Long id) {
+        if (demo03StudentInnerMapper.selectById(id) == null) {
+            throw exception(DEMO03_STUDENT_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public Demo03StudentDO getDemo03Student(Long id) {
+        return demo03StudentInnerMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<Demo03StudentDO> getDemo03StudentPage(Demo03StudentInnerPageReqVO pageReqVO) {
+        return demo03StudentInnerMapper.selectPage(pageReqVO);
+    }
+
+    // ==================== 子表(学生课程) ====================
+
+    @Override
+    public List<Demo03CourseDO> getDemo03CourseListByStudentId(Long studentId) {
+        return demo03CourseInnerMapper.selectListByStudentId(studentId);
+    }
+
+    private void createDemo03CourseList(Long studentId, List<Demo03CourseDO> list) {
+        list.forEach(o -> o.setStudentId(studentId));
+        demo03CourseInnerMapper.insertBatch(list);
+    }
+
+    private void updateDemo03CourseList(Long studentId, List<Demo03CourseDO> list) {
+        deleteDemo03CourseByStudentId(studentId);
+        list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新
+        createDemo03CourseList(studentId, list);
+    }
+
+    private void deleteDemo03CourseByStudentId(Long studentId) {
+        demo03CourseInnerMapper.deleteByStudentId(studentId);
+    }
+
+    private void deleteDemo03CourseByStudentIds(List<Long> studentIds) {
+        demo03CourseInnerMapper.deleteByStudentIds(studentIds);
+    }
+
+    // ==================== 子表(学生班级) ====================
+
+    @Override
+    public Demo03GradeDO getDemo03GradeByStudentId(Long studentId) {
+        return demo03GradeInnerMapper.selectByStudentId(studentId);
+    }
+
+    private void createDemo03Grade(Long studentId, Demo03GradeDO demo03Grade) {
+        if (demo03Grade == null) {
+            return;
+        }
+        demo03Grade.setStudentId(studentId);
+        demo03GradeInnerMapper.insert(demo03Grade);
+    }
+
+    private void updateDemo03Grade(Long studentId, Demo03GradeDO demo03Grade) {
+        if (demo03Grade == null) {
+            return;
+        }
+        demo03Grade.setStudentId(studentId);
+        demo03Grade.setUpdater(null).setUpdateTime(null); // 解决更新情况下:updateTime 不更新
+        demo03GradeInnerMapper.insertOrUpdate(demo03Grade);
+    }
+
+    private void deleteDemo03GradeByStudentId(Long studentId) {
+        demo03GradeInnerMapper.deleteByStudentId(studentId);
+    }
+
+    private void deleteDemo03GradeByStudentIds(List<Long> studentIds) {
+        demo03GradeInnerMapper.deleteByStudentIds(studentIds);
+    }
+
+}