基础CRUD后端项目(使用MybatisPlus、springBoot3)


基础的CRUD项目

代码获取:
通过网盘分享的文件:electronicLibraryV1.zip https://pan.baidu.com/s/1yn4YhSAp7LThVc-we3EmRw?pwd=6666 提取码: 6666
项目结构

electroniclibraryv1
├─sql                                       SQL脚本及数据库图形化关系图
└──src
    └──main
       ├─java
       │  └─com.chyb.electroniclibraryv1    包
       │      ├─common                      公共模块
       │      │  ├─until                    存放一些配置类和过滤器等文件
       │      │  │  └─config                
       │      │  └─web                      三层架构中公共的类,以及返回的对象
       │      │      ├─Domain               
       │      │      ├─controller
       │      │      └─page                 封装的分页返回对象
       │      └─基础三层架构
       └─resources
           └──mapper

目标

  • 自动配置、多环境切换、Starter 原理。
  • 复习springBoot

基础功能

  • 增删改查

步骤

  1. 导入基础依赖
<!--导入mybatisPlus依赖-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
        <version>3.5.7</version>
    </dependency>
    <!--lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <!-- Knife4j(增强版Swagger)用于配置springDoc的依赖 -->
    <dependency>
        <groupId>com.github.xiaoymin</groupId>
        <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
        <version>4.4.0</version>
    </dependency>
  1. 配置mysql、mybatisPlus、springDoc
spring:
  application:
    name: 'electronicLibraryV1'
  #建立连接Mysql数据库的四要素
  datasource:
    #驱动类名称
    driver-class-name: com.mysql.cj.jdbc.Driver
    #数据库连接的url
    # 注意这里3306后面的mysqlMybatisTest是你创建表的所在的库
    url: jdbc:mysql://localhost:3306/electronic_library
    #账号密码
    username: root
    password: 123456
server:
  port: 8081
#    配置mybatisPlus
mybatis-plus:
  configuration:
    #    输出sql语句的日志,效果就是在每次进行执行sql语句时会输出在控制板中
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # springdoc-openapi项目配置
    springdoc:
      swagger-ui:
        path: /swagger-ui.html       # Swagger UI 的访问路径(默认即为此值)
        tags-sorter: alpha            # 按字母顺序对 API 的标签(Tags)进行排序
        operations-sorter: alpha      # 按字母顺序对每个标签下的接口(Operations)进行排序
      api-docs:
        path: /v3/api-docs            # OpenAPI 规范文档(JSON 格式)的访问路径(默认值)
      group-configs:
        - group: 'default'            # 分组名称(默认分组)
          paths-to-match: '/**'       # 匹配所有接口路径
          packages-to-scan: com.chyb.electroniclibraryv1.controller # 扫描指定包下的控制器类
    # knife4j的增强配置,不需要增强可以不配
    knife4j:
      enable: true                    # 启用 Knife4j 的增强功能(如离线文档下载、接口调试等)
      setting:
        language: zh_cn               # 将 Knife4j 的界面语言设置为简体中文
  1. 写三层架构的基本业务(CRUD)
  2. 测试

写项目时遇到的问题

1.mysql数据库的创建

创建数据库主要还是使用AI,自动帮我生成但是要注意许多的细节问题,列如:命名问题、软删除、索引等

2.mybatisPlus与springBoot整合

常见报错:在这里插入图片描述
依赖问题:要注意springBoot版本和mybatisPlus的版本是否匹配
列如springBoot3官方对应的版本为:

<dependency>
   <groupId>com.baomidou</groupId>
   <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
   <version>3.5.11</version>
</dependency>

3.springDoc的配置及应用(了解)

springDoc可以快速的将我们开发的API接口进行测试,就不需要使用postman进行一个一个的输入网址测试
配置好后直接访问:http://localhost:8081/doc.html (这里的端口写自己配置的端口)

  • springDoc的配置:
    # springdoc-openapi项目配置
    springdoc:
      swagger-ui:
        path: /swagger-ui.html       # Swagger UI 的访问路径(默认即为此值)
        tags-sorter: alpha            # 按字母顺序对 API 的标签(Tags)进行排序
        operations-sorter: alpha      # 按字母顺序对每个标签下的接口(Operations)进行排序
      api-docs:
        path: /v3/api-docs            # OpenAPI 规范文档(JSON 格式)的访问路径(默认值)
      group-configs:
        - group: 'default'            # 分组名称(默认分组)
          paths-to-match: '/**'       # 匹配所有接口路径
          packages-to-scan: com.chyb.libraryManage.controllers # 扫描指定包下的控制器类
    # knife4j的增强配置,不需要增强可以不配
    knife4j:
      enable: true                    # 启用 Knife4j 的增强功能(如离线文档下载、接口调试等)
      setting:
        language: zh_cn               # 将 Knife4j 的界面语言设置为简体中文
  • springDoc的规范(controller)
@RestController
@RequestMapping("body")
@Tag(name = "body参数")
public class BodyController {

   @Operation(summary = "普通body请求")
   @PostMapping("/body")
   public ResponseEntity<FileResp> body(@RequestBody FileResp fileResp){
       return ResponseEntity.ok(fileResp);
   }

   @Operation(summary = "普通body请求+Param+Header+Path")
   @Parameters({
           @Parameter(name = "id",description = "文件id",in = ParameterIn.PATH),
           @Parameter(name = "token",description = "请求token",required = true,in = ParameterIn.HEADER),
           @Parameter(name = "name",description = "文件名称",required = true,in=ParameterIn.QUERY)
   })
   @PostMapping("/bodyParamHeaderPath/{id}")
   public ResponseEntity<FileResp> bodyParamHeaderPath(@PathVariable("id") String id,@RequestHeader("token") String token, @RequestParam("name")String name,@RequestBody FileResp fileResp){
       fileResp.setName(fileResp.getName()+",receiveName:"+name+",token:"+token+",pathID:"+id);
       return ResponseEntity.ok(fileResp);
   }
}

素材来源

4.分页查询

方法一(使用mybatis中提供的分页插件):

1、配置Page分页插件
(注意这里的Page插件是mybatisPlus中内置的)

public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
   MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
   interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
   return interceptor;
}
}

分页配置的作用是:

  • 1:增加代码的灵活性,可以个性化的配置分页插件
  • 2:应对一些难以适配的特殊环境
  • 3:利用后期的维护和理解

2、在Service层中使用分页

@Override
public List<BookContent> selectPage(BookContent bookContent) {
  /*创建Page用于在调用pageList时进行传值*/
  Page<BookContent> page = new Page<>();
  /*开始进行查询*/
  Page<BookContent> tempPage = bookContentMapper.pageList(page, bookContent);
  /*将返回的类型转换为List*/
  List<BookContent> records = tempPage.getRecords();
  return records;
} 

3、Mapper中创建pageList方法

   Page<BookContent> pageList(Page<BookContent> page,@Param("bookContent") BookContent bookContent); 

4、xml中调用属性的值,并做条件判断

<select id="pageList" resultMap="bookContentResult" parameterType="BookContent">
    <include refid="bookContentVO"/>
    <where>
        <if test="bookContent.bookId != null">and book_id = #{bookContent.bookId}</if>
        <if test="bookContent.chapterTitle != null and bookContent.chapterTitle != ''">and chapter_title like concat('%',#{bookContent.chapterTitle},'%')</if>
        <if test="bookContent.chapterContent != null and bookContent.chapterContent != ''">and chapter_content like concat('%',#{bookContent.chapterContent},'%')</if>
    </where>
</select>

注意:此方法在xml中调用bookContent参数时,需要使用@Param("bookContent“)进行标记一下,在xml调用bookContent.~

方法二(直接使用xml进行编写):

1、xml中编写代码

<select id="selectPageTwo" resultMap="bookContentResult" parameterType="BookContent">
<include refid="bookContentVO"/>
<where>
    <if test="bookId != null">and book_id = #{bookId}</if>
    <if test="chapterTitle != null and chapterTitle != ''">and chapter_title like
        concat('%',#{chapterTitle},'%')
    </if>
    <if test="chapterContent != null and chapterContent != ''">and chapter_content like
        concat('%',#{chapterContent},'%')
    </if>
</where>
limit #{pageNum},#{pageSize}
</select>

这里的Service中直接调用此方法即可,在mapper中传参只需要传输一个bookContent参数(因为这个类中有封装page中所需的属性)

注意:当项目多的时候xml中会很繁琐,因为每当想要使用分页的时候都需要手动的去写sql很不便捷

方法三(仿写若依框架中的分页查询)【推荐】

在若依框架中原理也是使用您的PageHelper这个插件,但是它只需要执行BaseController.startPage方法进行分页,在根据业务进行条件判断即可

!!!这里使用的Page和上面MybatisPlus中内置的Page不一样!!!

1、导入PageHelper及所用到的jsqlparser依赖

<!-- pagehelper 分页插件-->
<dependency>
  <groupId>com.github.pagehelper</groupId>
  <artifactId>pagehelper-spring-boot-starter</artifactId>
  <version>2.0.0</version>
</dependency>

<!--导入pageHelper所用到的依赖-->
<dependency>
  <groupId>com.github.jsqlparser</groupId>
  <artifactId>jsqlparser</artifactId>
  <version>4.6</version> <!-- 可根据需要选择合适的版本 -->
</dependency>

2、创建一个BaseController用于存放每一个controller中共用的方法例如:分页

import com.chyb.electroniclibraryv1.common.web.Domain.BaseDomain;
import com.github.pagehelper.PageHelper;
public class BaseController {
   /**
       * 普通合理化的分页
       */
      public static void startPage(BaseDomain bd){
          /**
           count:是否进行 count 查询。
           reasonable:启用合理化时,如果pageNum < 1会查询第一页,如果pageNum > 总页数会查询最后一页;禁用合理化时,如果pageNum < 1或pageNum > 总页数会返回空数据。
           pageSizeZero:pageSize = 0时是否进行查询,如果为true,当pageSize = 0时会查询全部结果,否则返回空数据。
           orderBy:排序字段,格式为 “字段名 1 排序方式 1, 字段名 2 排序方式 2”,例如 “id desc, name asc”。
           */
          PageHelper.startPage(bd.getPageNum(), bd.getPageSize(), false, true, false);
      }
      /**
       * 加入排序进行分页
       */
      public static void startPageOrderBy(BaseDomain bd){
          /**
           这里的orderby参数可以使用BaseDomain中的IsAsc、orderByColumn,
           但是要注意传值的方式,使得BaseController中的order参数不会显得那么臃肿,
           我这里就直接写成字符串了*/
          PageHelper.startPage(bd.getPageNum(), bd.getPageSize(), "create_time desc, update_time desc").setReasonable(true);
      }
  }

BaseDomain:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class BaseDomain {
    /*修改为自增*/
    @TableId(type = IdType.AUTO)
    private Long id;
    /*标记为软删除*/
    @TableLogic(value = "0", delval = "1")
    private Integer isDeleted;
    /*设置排序*/
    @OrderBy(asc = true, sort = 0)
    private Date createTime;
    @OrderBy(asc = true, sort = 1)
    private Date updateTime;
    /*分页*/
    @TableField(exist = false)
    private Integer pageSize;
    @TableField(exist = false)
    private Integer pageNum;
    @TableField(exist = false)
    private Boolean isAsc = true;
    @TableField(exist = false)
    private String orderByColumn;
}

3、在对应的Controller中继承BaseController并调用startPageByOrder方法

public class BookContentController extends BaseController {
    @Autowired
    private IBookContentService bookContentService;
    /*仿写若依框架的分页*/
    @PostMapping("/ryPage")
    @Operation(summary = "仿写若依框架的分页")
    public TableDataInfo ryPage(@RequestBody BookContent bookContent) {
        startPageOrderBy(bookContent);
        return TableDataInfo.getPageInfo(bookContentService.ryPage(bookContent));
    }
}

后面就和正常的调用查询一样,查完之后返回的值创建一个对象进行接受如TableDataInfo

这里只是简单的去仿写达到了此效果若是想了解一下源码的话可以去 若依官网

若是还是看不太懂的话推荐去看一下这一篇文章:《分析若依的分页实现逻辑》,个人觉得写的挺细节的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值