SpringBoot从0写一个SSMP案例(基本的CRUD、条件查询和分页)后端篇

SSMP:基于SpringBoot,把spring、spring mvc、MyBatis plus 整合在一起
本案例不区分前端服务器后端服务器,整合在一起

本案例使用的如下技术如果不清楚请点下面的链接:

MyBatis plus

lombok

druid

目录

一 数据层

1.1 搭建项目,完成CRUD

1 pom文件添加MyBatis plus、druid、lombok的依赖

2 配置文件

3 实体类

4 dao

5 测试类

1.2 开启MyBatis plus的日志

1.3 分页

1 写拦截器配置类

2 测试类

 1.4 条件查询

二 业务层

 方法1 基础CRUD

 *方法2 基于MyBatis plus的快速开发

三 表现层

3.1 正常封装数据格式一致

1 表现层消息一致处理

2 controller

*3.2 出现异常改进

1 出现异常

 2 解决异常


开始

一 数据层


1.1 搭建项目,完成CRUD

创建新模块--spring initializr--勾选SQL里的 mysql driver,web里的spring web

步骤
1 pom文件添加MyBatis plus、druid、lombok的依赖
2 配置文件
3 实体类
4 dao
5 测试类

代码

1 pom文件添加MyBatis plus、druid、lombok的依赖

<dependency>
   <groupId>com.baomidou</groupId>
   <artifactId>mybatis-plus-boot-starter</artifactId>
   <version>3.4.3</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.6</version>
</dependency>
<dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
</dependency>


2 配置文件

yaml

server:
  port: 80

spring:
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
      username: root
      password: 123456

#主键不用MyBatis plus的雪花算法,用数据库的主键自增
mybatis-plus:
  global-config:
    db-config:
      id-type: auto


3 实体类

package com.qing.domain;

import lombok.*;

@Data
public class Book {
    private Integer id;
    private String name;
    private String type;
    private String description;


}


4 dao

package com.qing.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qing.domain.Book;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

@Repository
@Mapper
public interface BookDao extends BaseMapper<Book> {


}


5 测试类

package com.qing.dao;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qing.domain.Book;
import org.apache.logging.log4j.util.Strings;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
public class DaoTest {

    @Autowired
    BookDao bookDao;

    //通过id查询
    @Test
    public void testGetById() {
        System.out.println(bookDao.selectById(1));
    }

    //查询所有
    @Test
    public void testGetAll() {
        List<Book> books = bookDao.selectList(null);
        for (Book book : books) {
            System.out.println(book);
        }
    }

    //条件查询 写法1
    @Test
    public void testSelectBy() {
        QueryWrapper<Book> wrapper = new QueryWrapper<>();
        //查询type为教科书的所有书
        wrapper.like("type", "教科书");
        bookDao.selectList(wrapper);
    }

    //条件查询 写法2(推荐)
    @Test
    public void testSelectBy2() {
        LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<>();
        String bookType = "教科书";
        //查询type为教科书的所有书
        //这样就不会写错列名了
        //if(bookType!=null) wrapper.like(Book::getType,bookType);
//        wrapper.like(bookType!=null,Book::getType,bookType);
        wrapper.like(Strings.isNotEmpty(bookType), Book::getType, bookType);
        bookDao.selectList(wrapper);
    }

    //新增
    @Test
    public void testSave() {
        Book book = new Book();
        book.setName("小飞象");
        book.setDescription("小飞象的一生");
        book.setType("童话");
        System.out.println(bookDao.insert(book));
        testGetAll();
    }

    //删除
    @Test
    public void testDelete() {
        System.out.println(bookDao.deleteById(4));
        testGetAll();
    }

    //修改
    @Test
    public void testUpdate() {
        Book book = new Book();
        book.setId(1);
        book.setName("大学计算机基础");
        book.setDescription("计算机的原理");
        book.setType("教科书");
        System.out.println(bookDao.updateById(book));
        testGetAll();
    }

    //分页
    @Test
    public void testPage() {
        //new Page():参数1为第几页,参数2为一页有几条
        IPage page = new Page(2, 3);
        bookDao.selectPage(page, null);
        System.out.println("当前是第" + page.getCurrent() + "页");
        System.out.println("每页" + page.getSize() + "条");
        System.out.println("总共" + page.getTotal() + "条数据");
        System.out.println("总共" + page.getPages() + "页");
        //返回当前page的列表信息
        List<Book> books = page.getRecords();
        for (Book book : books) {
            System.out.println(book);
        }

    }


}

1.2 开启MyBatis plus的日志

yaml

#主键不用MyBatis plus的雪花算法,用数据库的主键自增
mybatis-plus:
  global-config:
    db-config:
      id-type: auto
  #开启MyBatis plus的日志
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

1.3 分页

1 写拦截器配置类

添加MyBatis plus提供的拦截器

package com.qing.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

//MyBatis plus分页拦截器的配置
//指定该类为配置类
@Configuration
public class MpConfig {

    //注入当前方法的 返回值 ,存入spring 的IOC 容器中
    @Bean
    public MybatisPlusInterceptor lanjie(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加分页拦截器
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}

2 测试类

 测试类

    //分页
    @Test
    public void testPage() {
        //new Page():参数1为第几页,参数2为一页有几条
        IPage page = new Page(2,3);
        bookDao.selectPage(page, null);
        System.out.println("当前是第"+page.getCurrent()+"页");
        System.out.println("每页"+page.getSize()+"条");
        System.out.println("总共"+page.getTotal()+"条数据");
        System.out.println("总共"+page.getPages()+"页");
        //返回当前page的列表信息
        List<Book> books = page.getRecords();
        for (Book book:books) {
            System.out.println(book);
        }

    }

结果

 1.4 条件查询

//条件查询 写法1
    @Test
    public void testSelectBy() {
        QueryWrapper<Book> wrapper = new QueryWrapper<>();
        //查询type为教科书的所有书
        wrapper.like("type","教科书");
        bookDao.selectList(wrapper);
    }

    //条件查询 写法2(推荐)
    @Test
    public void testSelectBy2() {
        LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<>();
        String bookType = "教科书";
        //查询type为教科书的所有书
        //这样就不会写错列名了
        //if(bookType!=null) wrapper.like(Book::getType,bookType);
//        wrapper.like(bookType!=null,Book::getType,bookType);
        wrapper.like(Strings.isNotEmpty(bookType),Book::getType,bookType);
        bookDao.selectList(wrapper);
    }

二 业务层

 方法1 基础CRUD

service

package com.qing.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.qing.domain.Book;

import java.util.List;

public interface BookService {
    Boolean save(Book book);
    Boolean update(Book book);
    Boolean delete(Integer id);
    Book getById(Integer id);
    List<Book> getAll();
    List<Book> getByName(String name);
    IPage<Book> getPage(int currentPage,int pageSize);

}

impl

package com.qing.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qing.dao.BookDao;
import com.qing.domain.Book;
import com.qing.service.BookService;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class BookServiceImpl implements BookService {

    @Autowired
    private BookDao bookDao;

    //增
    @Override
    public Boolean save(Book book) {
        return bookDao.insert(book) > 0;
    }

    //改
    @Override
    public Boolean update(Book book) {
        return bookDao.updateById(book)>0;
    }


    //删
    @Override
    public Boolean delete(Integer id) {
        return bookDao.deleteById(id)>0;
    }

    //查1
    @Override
    public Book getById(Integer id) {
        return bookDao.selectById(id);
    }

    //条件查询--通过书名查询
    @Override
    public List<Book> getByName(String name) {
        LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(Strings.isNotEmpty(name),Book::getName,name);
        return bookDao.selectList(wrapper);
    }

    //查所有
    @Override
    public List<Book> getAll() {
        return bookDao.selectList(null);
    }

    //分页
    @Override
    public IPage<Book> getPage(int currentPage, int pageSize) {
        return bookDao.selectPage(new Page(currentPage,pageSize),null);
    }
}

测试类

package com.qing.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qing.domain.Book;
import com.qing.service.impl.BookServiceImpl;
import org.apache.logging.log4j.util.Strings;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
public class BookServiceTest {

    @Autowired
    BookServiceImpl bookServiceImpl;

    //查1
    @Test
    public void testGetById(){
        System.out.println(bookServiceImpl.getById(5));

    }
    //查询所有
    @Test
    public void testGetAll() {
        List<Book> books = bookServiceImpl.getAll();
        for (Book book : books) {
            System.out.println(book);
        }
    }


    //条件查询 -- 通过书名查询
    @Test
    public void testSelectByName() {

        bookServiceImpl.getByName("jav");
    }

    //新增
    @Test
    public void testSave() {
        Book book = new Book();
        book.setName("怎样写故事");
        book.setDescription("学写生动的故事");
        book.setType("工具书");
        System.out.println(bookServiceImpl.save(book));
        testGetAll();
    }

    //删除
    @Test
    public void testDelete() {
        System.out.println(bookServiceImpl.delete(3));
        testGetAll();
    }

    //修改
    @Test
    public void testUpdate() {
        Book book = new Book();
        book.setId(1);
        book.setName("英语1");
        book.setDescription("好好学英语");
        book.setType("教科书");
        System.out.println(bookServiceImpl.update(book));
        testGetAll();
    }

    //分页
    @Test
    public void testPage() {
        IPage<Book> page = bookServiceImpl.getPage(2,4);
        //返回当前page的列表信息
        System.out.println("当前是第"+page.getCurrent()+"页");
        System.out.println("每页"+page.getSize()+"条");
        System.out.println("总共"+page.getTotal()+"条数据");
        System.out.println("总共"+page.getPages()+"页");

        List<Book> books = page.getRecords();
        for (Book book:books) {
            System.out.println(book);
        }

    }

}

部分测试结果

 

 *方法2 基于MyBatis plus的快速开发

步骤
1 service 继承IService<bean类>
2 Serviceimpl 继承ServiceImpl<Dao, bean类> 实现 service

备注:如果有MyBatis plus 没提供的方法,自己手动在service 和 impl添加就好了(添加的方法注意不要和已有的重名)

service

package com.qing.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.qing.domain.Book;

public interface IBookService extends IService<Book> {

}

impl

package com.qing.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qing.dao.BookDao;
import com.qing.domain.Book;
import com.qing.service.IBookService;
import org.springframework.stereotype.Service;

@Service
public class BookServiceImpl extends ServiceImpl<BookDao, Book> implements IBookService {
}

测试类

package com.qing.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qing.domain.Book;
import com.qing.service.impl.BookServiceImpl;
import org.apache.logging.log4j.util.Strings;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
public class BookServiceTest {

    @Autowired
    BookServiceImpl bookServiceImpl;

    //查1
    @Test
    public void testGetById() {
        System.out.println(bookServiceImpl.getById(8));

    }

    //查询所有
    @Test
    public void testGetAll() {
        List<Book> books = bookServiceImpl.list();
        for (Book book : books) {
            System.out.println(book);
        }
    }


    //条件查询
    @Test
    public void testSelectByName() {

        String bookName="怎样";
        LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(Strings.isNotEmpty(bookName),Book::getName,bookName);
        List<Book> books = bookServiceImpl.list(wrapper);
        for (Book book:books) {
            System.out.println(book);
        }

    }

    //新增
    @Test
    public void testSave() {
        Book book = new Book();
        book.setName("怎样找对象");
        book.setDescription("泡妹子方法大全");
        book.setType("工具书");
        System.out.println(bookServiceImpl.save(book));
        testGetAll();
    }

    //删除
    @Test
    public void testDelete() {
        System.out.println(bookServiceImpl.removeById(1));
        testGetAll();
    }

    //修改
    @Test
    public void testUpdate() {
        Book book = new Book();
        book.setId(6);
        book.setName("英语1");
        book.setDescription("好好学英语");
        book.setType("教科书");
        System.out.println(bookServiceImpl.updateById(book));
        testGetAll();
    }

    //分页
    @Test
    public void testPage() {
        IPage<Book> page = new Page<Book>(2, 3);
        bookServiceImpl.page(page);
        //返回当前page的列表信息
        System.out.println("当前是第" + page.getCurrent() + "页");
        System.out.println("每页" + page.getSize() + "条");
        System.out.println("总共" + page.getTotal() + "条数据");
        System.out.println("总共" + page.getPages() + "页");

        List<Book> books = page.getRecords();
        for (Book book : books) {
            System.out.println(book);
        }

    }

}

部分测试结果

 

三 表现层

基于restful进行表现层接口开发,使用postman测试表现层功能

关于restful

业务层重新写了分页的方法 → 便于controller 使用

package com.qing.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qing.dao.BookDao;
import com.qing.domain.Book;
import com.qing.service.IBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BookServiceImpl extends ServiceImpl<BookDao, Book> implements IBookService {

    @Autowired
    BookDao bookDao;

    @Override
    public IPage<Book> getPage(int currentPage, int pageSize) {
        IPage<Book> page = new Page(currentPage, pageSize);
        bookDao.selectPage(page,null);
        return page;
    }
}

3.1 正常封装数据格式一致

1 表现层消息一致处理

 工具类,用于统一返回的数据格式

package com.qing.utils;

import lombok.Data;

//用于统一数据格式
@Data
public class R {
    private Boolean flag;
    private Object data;

    public R() {
    }

    public R(Boolean flag) {
        this.flag = flag;
    }

    public R(Boolean flag, Object data) {
        this.flag = flag;
        this.data = data;
    }
}

2 controller

package com.qing.controller;

import com.qing.domain.Book;
import com.qing.service.IBookService;
import com.qing.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/books")
public class BookController {

    @Autowired
    private IBookService bookService;

    //查1
    @GetMapping("{id}")
    public R getById(@PathVariable Integer id) {
        return new R(true,bookService.getById(id));
    }

    //查询所有
    @GetMapping
    public R getAll() {
        return new R(true,bookService.list());
    }

    //增 @RequestBody用于获取请求体数据
    @PostMapping
    public R save(@RequestBody Book book) {
        return new R(bookService.save(book));
    }

    //改
    @PutMapping
    public R update(@RequestBody Book book) {
        return new R(bookService.updateById(book));
    }

    //删
    @DeleteMapping("{id}")
    public R delete(@PathVariable Integer id) {
        return new R(bookService.removeById(id));
    }

    //分页
    @GetMapping("{currentPage}/{pageSize}")
    public R getPage(@PathVariable int currentPage, @PathVariable int pageSize) {
         return new R(true,bookService.getPage(currentPage, pageSize));

    }


}

部分测试

添加

 查询所有

 分页

 修改

 

 

*3.2 出现异常改进

1 出现异常

controller

 postman测试:出现异常后,返回的数据格式又不统一了,不是flag和data了

 2 解决异常

 异常处理工具类

package com.qing.utils;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

//作为spring mvc的异常处理器
//@ControllerAdvice 和 @RestControllerAdvice两个注解都行
@RestControllerAdvice
public class ProjectExceptionAdvice {

    //用这个方法 拦截所有的异常信息
    @ExceptionHandler(Exception.class)
    public R doException(Exception exception){
        //记录日志
        //通知运维
        //通知开发
        //在命令行打印异常信息在程序中出错的位置及原因
        exception.printStackTrace();
        return new R(false,"服务器故障,请稍后再试!");
    }
}

表现层消息一致处理工具类

package com.qing.utils;

import lombok.Data;

//用于统一数据格式
@Data
public class R {
    private Boolean flag;
    private Object data;
    private String message;

    public R() {
    }

    public R(Boolean flag) {
        this.flag = flag;
    }

    public R(Boolean flag, Object data) {
        this.flag = flag;
        this.data = data;
    }

    public R(Boolean flag, String message) {
        this.flag = flag;
        this.message = message;
    }
}

测试

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值