哈喽!我是话里人,相信伙伴们通过上篇Blog的步骤,后端环境搭建已经完成,话不多说,那咱们书接上回~ 
介绍
- 在线教育,是一个B2C模式的职业技能在线教育系统,分为前台用户系统和后台运营平台。
- B2C是指电子商务的一种模式,也是直接面向消费者销售产品和服务商业的零售模式。
- Business-to-Consumer :企业对客户
4.实现讲师列表接口
4.1 pojo

- 在zx-domain中创建实体类EduTeacher
package com.czxy.zx.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
@ApiModel(value = "EduTeacher对象",description = "讲师")
public class EduTeacher {
@TableId(value = "id",type = IdType.AUTO)
@ApiModelProperty(value = "讲师ID")
private String id;
@ApiModelProperty(value = "讲师姓名")
private String name;
@ApiModelProperty(value = "讲师资历,一句话说明讲师")
private String intro;
@ApiModelProperty(value = "讲师简介")
private String career;
@ApiModelProperty(value = "头衔 1高级讲师 2首席讲师")
private Integer level;
@ApiModelProperty(value = "讲师头像")
private String avatar;
@ApiModelProperty(value = "讲师排序")
private Integer sort;
@ApiModelProperty(value = "逻辑删除 1已删除, 0未删除")
@TableField(value = "is_deleted",fill = FieldFill.INSERT)
@TableLogic
private Integer isDeleted;
@ApiModelProperty(value = "创建时间")
@TableField(value = "gmt_create",fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date gmtCreate;
@ApiModelProperty(value = "更新时间")
@TableField(value = "gmt_modified",fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date gmtModified;
}
4.2 mapper

package com.czxy.zx.teacher.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.zx.domain.EduTeacher;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface EduTeacherMapper extends BaseMapper<EduTeacher> {
}
4.3 service

package com.czxy.zx.teacher.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.czxy.zx.domain.EduTeacher;
public interface EduTeacherService extends IService<EduTeacher> {
}
package com.czxy.zx.teacher.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czxy.zx.domain.EduTeacher;
import com.czxy.zx.teacher.mapper.EduTeacherMapper;
import com.czxy.zx.teacher.service.EduTeacherService;
import org.springframework.stereotype.Service;
@Service
public class EduTeacherServiceImpl extends ServiceImpl<EduTeacherMapper, EduTeacher> implements EduTeacherService {
}
4.4 Controller

TeacherController
package com.czxy.zx.teacher.controller;
import com.czxy.zx.domain.EduTeacher;
import com.czxy.zx.teacher.service.EduTeacherService;
import com.czxy.zx.vo.BaseResult;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@RestController
@RequestMapping("/teacher")
public class EduTeacherController {
@Resource
private EduTeacherService eduTeacherService;
@GetMapping
private BaseResult<List<EduTeacher>> getTeacherList(){
List<EduTeacher> list = eduTeacherService.list(null);
return BaseResult.ok("查询成功", list);
}
}
4.5 拷贝配置类

4.5.1 拷贝配置类:config-MyBatisPlusConfig
package com.czxy.zx.teacher.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return mybatisPlusInterceptor;
}
}
4.5.2 拷贝配置类:config-MyBatisPlusConfig
package com.czxy.zx.teacher.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableSwagger2
public class Swagger2ConfigurationV3 {
@Bean
public Docket createRestApi() {
Docket docket = new Docket(DocumentationType.SWAGGER_2);
docket.apiInfo(apiInfo());
docket = docket.select()
.apis(RequestHandlerSelectors.basePackage("com.czxy"))
.paths(PathSelectors.any())
.build();
docket.securitySchemes(securitySchemes());
docket.securityContexts(securityContexts());
return docket;
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("API")
.description("基于swagger接口文档")
.contact(new Contact("梁桐","http://www.javaliang.com","liangtong@itcast.cn"))
.version("1.0")
.build();
}
private List<ApiKey> securitySchemes() {
List<ApiKey> list = new ArrayList<>();
list.add(new ApiKey("Authorization", "Authorization", "header"));
return list;
}
private List<SecurityContext> securityContexts() {
List<SecurityContext> list = new ArrayList<>();
list.add(SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex("^(?!auth).*$"))
.build());
return list;
}
private List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
List<SecurityReference> list = new ArrayList();
list.add(new SecurityReference("Authorization", authorizationScopes));
return list;
}
}
4.6 处理Swagger接口
package com.czxy.zx.teacher.controller;
import com.czxy.zx.domain.EduTeacher;
import com.czxy.zx.teacher.service.EduTeacherService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@RestController
@RequestMapping("/teacher")
@Api(tags = "老师接口", description = "老师接口描述,完成增删改查操作")
public class EduTeacherController {
@Resource
private EduTeacherService eduTeacherService;
@ApiOperation(value = "查询所有老师")
@GetMapping
private BaseResult<List<EduTeacher>> getTeacherList(){
List<EduTeacher> list = eduTeacherService.list(null);
return BaseResult.ok("查询成功", list);
}
}
4.7 测试
http://localhost:9000/swagger-ui.html
http://localhost:10010/teacher-service/swagger-ui.html

5.讲师逻辑删除
5.1 在Controller中添加删除方法
@ApiOperation(value = "根据ID删除讲师")
@ApiImplicitParams(value = {
})
@DeleteMapping("/{id}")
public boolean removeById(
@ApiParam(name = "id", value = "讲师ID", required = true)
@PathVariable("id") String id){
return eduTeacherService.removeById(id);
}
5.2 在EduTeacher.java文件中

@ApiModelProperty(value = "逻辑删除 1(true)已删除, 0(false)未删除")
@TableLogic
@TableField(fill = FieldFill.INSERT, value = "is_deleted")
private Boolean isDeleted;
5.3 完善:配置Handler
- 创建 com.czxy.zx.teacher.handler.TeacherMetaObjectHandler.java

package com.czxy.zx.teacher.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
@Component
public class TeacherMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("isDeleted",0 , metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
}
}
5.4 完善:配置application.yaml文件
-
配置指定删除和不删除的状态 
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
logic-delete-value: 1
logic-not-delete-value: 0
5.5 讲师逻辑删除测试
ok
6.分页和条件查询
6.1 基本查询
6.1.1 创建 vo

package com.czxy.zx.teacher.vo;
import lombok.Data;
@Data
public class TeacherVo {
}
6.1.2 controller
@ApiOperation(value = "所有老师:条件 + 分页")
@ApiImplicitParams({
@ApiImplicitParam(name = "size",value = "每页个数",required = true,paramType = "path", dataType = "int"),
@ApiImplicitParam(name = "current",value = "当前页",required = true,paramType = "path", dataType = "int")
})
@PostMapping("/condition/{size}/{current}")
public BaseResult<Page<EduTeacher>> condition(
@PathVariable("size") Integer size,
@PathVariable("current") Integer current,
@RequestBody TeacherVo teacherVo
){
Page<EduTeacher> page = eduTeacherService.condition(size,current,teacherVo);
return BaseResult.ok("查询成功", page);
}
6.1.3 service
-
接口 package com.czxy.zx.teacher.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.czxy.zx.domain.EduTeacher;
import com.czxy.zx.teacher.vo.TeacherVo;
public interface EduTeacherService extends IService<EduTeacher> {
Page<EduTeacher> condition(Integer size, Integer current, TeacherVo teacherVo);
}
-
实现类 package com.czxy.zx.teacher.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czxy.zx.domain.EduTeacher;
import com.czxy.zx.teacher.mapper.EduTeacherMapper;
import com.czxy.zx.teacher.service.EduTeacherService;
import com.czxy.zx.teacher.vo.TeacherVo;
import org.springframework.stereotype.Service;
@Service
public class EduTeacherServiceImpl extends ServiceImpl<EduTeacherMapper, EduTeacher> implements EduTeacherService {
@Override
public Page<EduTeacher> condition(Integer size, Integer current, TeacherVo teacherVo) {
return null;
}
}
6.2 分页
package com.czxy.zx.teacher.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czxy.zx.domain.EduTeacher;
import com.czxy.zx.teacher.mapper.EduTeacherMapper;
import com.czxy.zx.teacher.service.EduTeacherService;
import com.czxy.zx.teacher.vo.TeacherVo;
import org.springframework.stereotype.Service;
@Service
public class EduTeacherServiceImpl extends ServiceImpl<EduTeacherMapper, EduTeacher> implements EduTeacherService {
@Override
public Page<EduTeacher> condition(Integer size, Integer current, TeacherVo teacherVo) {
QueryWrapper<EduTeacher> queryWrapper = new QueryWrapper<>();
Page<EduTeacher> page = new Page<>(current,size);
this.baseMapper.selectPage(page, queryWrapper);
return page;
}
}
6.3 条件查询
-
需求:
- 根据讲师姓名模糊查询
- 根据讲师头衔精准查询
- 根据时间范围查询(开始时间、结束时间)
-
完善vo package com.czxy.zx.teacher.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "封装了Teacher条件查询的参数")
public class TeacherVo {
@ApiModelProperty(value = "讲师姓名,模糊查询")
private String name;
@ApiModelProperty(value = "讲师头衔:1 高级讲师 2 首席讲师")
private String level;
@ApiModelProperty(value = "查询开始时间",example = "2020-02-01 10:12:30")
private String beginDate;
@ApiModelProperty(value = "查询截止时间",example = "2020-02-01 10:12:30")
private String endDate;
}
-
完善service package com.czxy.zx.teacher.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czxy.zx.domain.EduTeacher;
import com.czxy.zx.teacher.mapper.EduTeacherMapper;
import com.czxy.zx.teacher.service.EduTeacherService;
import com.czxy.zx.teacher.vo.TeacherVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
@Service
public class EduTeacherServiceImpl extends ServiceImpl<EduTeacherMapper, EduTeacher> implements EduTeacherService {
@Override
public Page<EduTeacher> condition(Integer size, Integer current, TeacherVo teacherVo) {
QueryWrapper<EduTeacher> queryWrapper = new QueryWrapper<>();
queryWrapper.like(StringUtils.isNotBlank(teacherVo.getName()), "name", teacherVo.getName());
queryWrapper.eq(StringUtils.isNotBlank(teacherVo.getLevel()), "level", teacherVo.getLevel());
queryWrapper.ge(StringUtils.isNotBlank(teacherVo.getBeginDate()), "gmt_create", teacherVo.getBeginDate()+ " 00:00:00" );
queryWrapper.le(StringUtils.isNotBlank(teacherVo.getEndDate()), "gmt_create", teacherVo.getEndDate() + " 23:59:59");
Page<EduTeacher> page = new Page<>(current,size);
this.baseMapper.selectPage(page, queryWrapper);
return page;
}
}
6.4 测试
ok
7.讲师新增和修改
7.1 新增
在Controller中编写代码
@ApiOperation(value = "新增讲师")
@PostMapping
public BaseResult save(
@ApiParam(name = "teacher", value = "讲师对象", required = true)
@RequestBody EduTeacher teacher){
boolean save = eduTeacherService.save(teacher);
if(save) {
return BaseResult.ok("添加成功");
}
return BaseResult.error("添加失败");
}
{
"avatar": "https://czxy-lt.oss-cn-shanghai.aliyuncs.com/avatar/449972ccd28a41d6a8317c97a9c2319e.png",
"career": "讲师简介",
"gmtCreate": "2022-06-27 08:16:32",
"gmtModified": "2022-06-27 08:16:32",
"intro": "讲师资历",
"level": 1,
"name": "张三",
"sort": 0
}
7.2 根据id查询
@ApiOperation(value = "根据ID查询讲师")
@GetMapping("{id}")
public BaseResult getById(
@ApiParam(name = "id", value = "讲师ID", required = true)
@PathVariable String id){
EduTeacher teacher = eduTeacherService.getById(id);
return BaseResult.ok("查询成功", teacher);
}
7.3 根据id查询 + 通过id修改
-
通过id查询
@GetMapping("/{teacherId}")
public BaseResult<EduTeacher> findById(@PathVariable("teacherId") Integer teacherId ) {
EduTeacher eduTeacher = eduTeacherService.getById(teacherId);
if(eduTeacher != null) {
return BaseResult.ok("查询成功", eduTeacher);
}
return BaseResult.error("查询失败");
}
-
通过id修改 @ApiOperation(value = "根据ID修改讲师")
@PutMapping
public BaseResult updateById(
@ApiParam(name = "teacher", value = "讲师对象", required = true)
@RequestBody EduTeacher teacher){
boolean update = eduTeacherService.updateById(teacher);
if(update) {
return BaseResult.ok("更新成功");
}
return BaseResult.error("更新失败");
}
7.4 批量删除
@PostMapping("/batchDelete")
public BaseResult batchDelete(@RequestBody List<Integer> ids) {
boolean result = eduTeacherService.removeByIds(ids);
if(result) {
return BaseResult.ok("批量删除成功");
}
return BaseResult.error("批量删除失败");
}
7.5 修改处理类:自动填充
package com.czxy.zx.teacher.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class TeacherMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("isDeleted", 0 , metaObject);
this.setFieldValByName("gmtCreate", new Date(), metaObject);
this.setFieldValByName("gmtModified", new Date(), metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("gmtModified", new Date(), metaObject);
}
}
8.统一异常处理
8.1 测试系统对错误的响应
8.2 全局异常处理
-
我们想让异常结果也统一,并且在集中的地方处理系统的异常信息,那么需要统一异常处理。 -
spring mvc 提供 @ControllerAdvice 就可以完成此需求。  -
@ControllerAdvice 是对Controller进行增强的注解,主要作用有三个:
-
全局异常处理【重点】 -
全局数据绑定 -
全局数据预处理 -
zx-common中创建统一异常处理类: 
package com.czxy.zx.exception;
import com.czxy.zx.vo.BaseResult;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public BaseResult error(Exception e){
e.printStackTrace();
return BaseResult.error("系统错误");
}
}
-
注意:启动类的位置
- 启动类必须放在
com.czxy.zx 包下面才可以加载到com.czxy.zx.exception 包下面的内容 - 如果放在
com.czxy.zx.teacher 下面,将无法加载到com.czxy.zx.exception 包下面的内容  -
测试,返回统一错误结果

8.3 特殊异常配置
如果是除数为0的异常;那么需要如下配置,精确匹配异常:
package com.czxy.zx.exception;
import com.czxy.zx.vo.BaseResult;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public BaseResult error(Exception e){
e.printStackTrace();
return BaseResult.error("系统错误");
}
@ExceptionHandler(ArithmeticException.class)
@ResponseBody
public BaseResult error(ArithmeticException e){
e.printStackTrace();
return BaseResult.error("除数不能为0");
}
}
8.4 自定义异常
8.4.1 EduException通用异常类
- 在zx-common中创建Exception的异常类

package com.czxy.zx.exception;
import io.swagger.annotations.ApiModel;
@ApiModel(value = "自定义异常")
public class EduException extends RuntimeException {
public EduException(String message) {
super(message);
}
public EduException(String message, Throwable cause) {
super(message, cause);
}
public EduException(Throwable cause) {
super(cause);
}
protected EduException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
8.4.2 创建捕获自定义异常类
- 在 GlobalExceptionHandler类中添加自定义处理方法
@ExceptionHandler(EduException.class)
@ResponseBody
public BaseResult error(EduException e){
e.printStackTrace();
if(e.getMessage() == null) {
return BaseResult.error("空指针异常");
}
return BaseResult.error(e.getMessage());
}
- 测试:在业务中需要的位置抛出EduException,举例子在查询列表中出错:
@ApiOperation(value = "查询所有老师")
@GetMapping
private BaseResult<List<EduTeacher>> getTeacherList(){
List<EduTeacher> list = eduTeacherService.list(null);
if(list.size() > 0) {
throw new EduException("数据异常");
}
return BaseResult.ok("查询成功", list);
}
8.4.3 异常工具类
-
编写 ExceptionUtils 类,方便异常的抛出  package com.czxy.zx.exception;
public class ExceptionUtils {
public static void cast(String message) {
throw new EduException(message);
}
}
-
测试: @ApiOperation(value = "查询所有老师")
@GetMapping
private BaseResult<List<EduTeacher>> getTeacherList(){
List<EduTeacher> list = eduTeacherService.list(null);
if(list.size() > 0) {
ExceptionUtils.cast("数据异常");
}
return BaseResult.ok("查询成功", list);
}
9.附:创建MP代码生成器
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
在test/java目录下创建包com.zx.edu,创建代码生成器:CodeGenerator.java
package com.zx;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.junit.Test;
public class CodeGenerator {
@Test
public void run() {
AutoGenerator mpg = new AutoGenerator();
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("lt");
gc.setOpen(false);
gc.setFileOverride(false);
gc.setServiceName("%sService");
gc.setIdType(IdType.ID_WORKER_STR);
gc.setDateType(DateType.ONLY_DATE);
gc.setSwagger2(true);
mpg.setGlobalConfig(gc);
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/zx_edu_teacher");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("1234");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
PackageConfig pc = new PackageConfig();
pc.setModuleName("teacher");
pc.setParent("com.zx");
pc.setController("controller");
pc.setEntity("entity");
pc.setService("service");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("edu_teacher");
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setTablePrefix(pc.getModuleName() + "_");
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true);
strategy.setControllerMappingHyphenStyle(true);
mpg.setStrategy(strategy);
mpg.execute();
}
}
执行代码生成器方法
说明:
XxxServiceImpl 继承了 ServiceImpl 类,并且MP为我们注入了 XxxMapper
这样可以使用 service 层默认为我们提供的很多方法,当然也可以调用我们自己在 dao 层编写的方法。
end
 ok,以上就是后端讲师管理的全部内容了, 如果各位看官觉得满意的话,求各位点赞、收藏、转发, 您的支持就是话里人前进的巨大动力~
我是话里人,我们下期见~
|