SpringBoot+mybatis-plus+mysql实现简单后台管理demo
使用SpringBoot+mybatis-plus+mysql实现简单demo(后台管理增删改查)
一、使用idea新建Springboot项目
选择打开方式,我这里选择新窗口打开
这样基础的项目创建好了。
二、配置pom.xml 和 application.yml
pom.xml配置如下:
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--mybatis-plus自动的维护了mybatis以及mybatis-spring的依赖,
在springboot中这三者不能同时的出现,避免版本的冲突,表示:跳进过这个坑-->
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- alibaba的druid数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.20</version>
</dependency>
<!-- alibaba的druid数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.20</version>
</dependency>
application.yml(若没有,则在src/main/resources/下面新建此文件):
# 服务端口
server:
port: 8083
# 数据源配置
spring:
datasource:
name: test
url: jdbc:mysql://localhost:3306/db_test?&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSl=false
username: root
password:
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
## 配置连接池信息
## 初始化大小,最小,最大
initialSize: 5
minIdle: 5
maxActive: 30
## 配置获取连接等待超时的时间
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 超过时间限制是否回收
removeAbandoned: true
# 超时时间;单位为秒。180秒=3分钟
removeAbandonedTimeout: 180
# 关闭abanded连接时输出错误日志
logAbandoned: true
# mybatis-plus 默认扫描mapper.xml的目录
mybatis-plus:
mapper-locations: classpath*:/mapper/*.xml
#配置sql打印日志
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
三、编写简单的增删改查
在src/main/java/com.example.demo新建下面几个包:
entity:实体类
controller:控制器
dao:映射文件
service:业务处理
以商品管理为例:
1.数据表:
CREATE TABLE `t_product` (
`product_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) DEFAULT NULL COMMENT '标题',
`sub_title` varchar(255) DEFAULT NULL COMMENT '副标题',
`sale_price` decimal(10,2) DEFAULT NULL COMMENT '商品售价',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`create_by` int(11) DEFAULT NULL COMMENT '创建者',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`update_by` int(11) DEFAULT NULL COMMENT '修改者',
PRIMARY KEY (`product_id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COMMENT='商品表';
2.编写商品实体,使用@Data注解
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @author qzz
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_product")
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 商品id
*/
@TableId(value="product_id", type = IdType.AUTO)
private Integer product_id;
/**
* 商品标题
*/
@TableField("title")
private String title;
/**
* 商品标题
*/
@TableField("sub_title")
private String sub_title;
/**
* 商品售价
*/
@TableField("sale_price")
private Double sale_price;
/**
* 创建者
*/
@TableField(value = "create_by",fill = FieldFill.INSERT)
private Integer create_by;
/**
* 创建时间
* timezone:是时间设置为东八区,避免时间在转换中有误差
* @DateTimeFormat:从前台页面将时间类型的数据传入数据库中
* @JsonFormat:从数据库中获取日期类型的数据传到前台展示
*/
@TableField(value = "create_time",fill = FieldFill.INSERT)
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date create_time;
/**
* 修改时间
*/
@TableField(value = "update_time",fill = FieldFill.UPDATE)
private Date update_time;
/**
* 修改者id
*/
@TableField(value = "update_by",fill = FieldFill.UPDATE)
private Integer update_by;
}
3.编写ProductDao
package com.example.demo.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.Product;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
/**
* @author qzz
*/
@Repository
public interface ProductDao extends BaseMapper<Product> {
/**
* 分页获取列表:执行自己编写的sql
* @param page
* @param product
* @return
*/
List<Map<String,Object>> getProductListByPage(Page page, @Param("product") Product product);
}
由于项目中整合了mybatis-plus,所以基本的增删改查sql不需要手动编写,只需要继承BaseMapper即可。
需要手动编写sql的需要在ProductDao 自行定义。
4.编写Service以及Service的实现类
ProductService:
package com.example.demo.service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.Product;
import java.util.List;
import java.util.Map;
/**
* @author qzz
*/
public interface ProductService{
/**
* 添加商品信息
* @param product
* @return
*/
int addProduct(Product product);
/**
* 编辑商品信息
* @param product
* @return
*/
int updateProduct(Product product);
/**
* 获取商品列表信息
* @param queryWrapper
* @return
*/
List<Product> selectList(Wrapper<Product> queryWrapper);
/**
* 获取商品列表信息
* @param queryWrapper
* @return
*/
List<Map<String,Object>> selectListMaps(Wrapper<Product> queryWrapper);
/**
* 分页获取商品列表信息
* @return
*/
IPage<Map<String,Object>> selectListByPage(Page page, Wrapper<Product> queryWrapper);
/**
* 批量删除商品
* @param ids
* @return
*/
int deleteBatchProduct(Integer[] ids);
/**
* 分页获取列表:执行自己编写的sql
* @param page
* @param product
* @return
*/
List<Map<String,Object>> getProductListByPage(Page page, Product product);
}
ProductServiceImpl:
package com.example.demo.service.impl;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.dao.ProductDao;
import com.example.demo.entity.Product;
import com.example.demo.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* @author qzz
*/
@Service("ProductService")
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductDao productDao;
/**
* 添加商品信息
* @param product
* @return
*/
@Override
public int addProduct(Product product) {
return productDao.insert(product);
}
/**
* 编辑商品信息
* @param product
* @return
*/
@Override
public int updateProduct(Product product) {
return productDao.updateById(product);
}
/**
* 获取商品列表信息
* @param queryWrapper
* @return
*/
@Override
public List<Product> selectList(Wrapper<Product> queryWrapper) {
return productDao.selectList(queryWrapper);
}
/**
* 获取商品列表信息
* @param queryWrapper
* @return
*/
@Override
public List<Map<String, Object>> selectListMaps(Wrapper<Product> queryWrapper) {
return productDao.selectMaps(queryWrapper);
}
/**
* 分页获取商品列表信息
* @return
*/
@Override
public IPage<Map<String,Object>> selectListByPage(Page page, Wrapper<Product> queryWrapper) {
return productDao.selectMapsPage(page,queryWrapper);
}
/**
* 批量删除商品
* @param ids
* @return
*/
@Override
public int deleteBatchProduct(Integer[] ids) {
return productDao.deleteBatchIds(Arrays.asList(ids));
}
/**
* 分页获取列表:执行自己编写的sql
* @param page
* @param product
* @return
*/
@Override
public List<Map<String,Object>> getProductListByPage(Page page,Product product) {
return productDao.getProductListByPage(page,product);
}
}
4.编写Controller
package com.example.demo.controller;
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.example.demo.entity.Product;
import com.example.demo.service.ProductService;
import com.example.demo.utils.PageData;
import com.example.demo.utils.Result;
import com.example.demo.utils.Tools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* @author qzz
*/
@RestController
@RequestMapping("/product")
public class ProductController {
@Autowired
private ProductService productService;
/**
* 分页获取商品列表
*/
@GetMapping("/page")
public Result page(HttpServletRequest request){
Page<Product> page = new Page<>(1,5);
QueryWrapper<Product> queryWrapper = new QueryWrapper();
//分页查看商品列表
IPage<Map<String,Object>> pageInfo = productService.selectListByPage(page,queryWrapper);
//返回结果集
return new Result().ok(new PageData<>(pageInfo.getRecords(),pageInfo.getTotal()));
}
/**
* 根据条件获取列表
*/
@GetMapping("/list")
public Result getProductList(@RequestParam String title, HttpServletRequest request){
QueryWrapper<Product> queryWrapper = new QueryWrapper();
queryWrapper.like(Tools.notEmpty(title),"title",title);
//此方法 sql有结果,但是返回数据除了title列,其他列都是null
// List<Product> list = productService.selectList(queryWrapper);
List<Map<String,Object>> list = productService.selectListMaps(queryWrapper);
return new Result().ok(list);
}
/**
* 添加商品信息
*/
@PostMapping("add")
public Result addProduct(@RequestBody Product product){
product.setCreate_by(1);
product.setCreate_time(new Date());
int n = productService.addProduct(product);
if(n>0){
return new Result().ok(product.getProduct_id());
}else{
return new Result().error(400,"添加商品失败");
}
}
/**
* 编辑商品信息
*/
@PostMapping("update")
public Result updateProduct(@RequestBody Product product){
product.setUpdate_by(1);
product.setUpdate_time(new Date());
int n = productService.updateProduct(product);
if(n>0){
return new Result();
}else{
return new Result().error(400,"编辑商品失败");
}
}
/**
* 根据ids删除商品信息
*/
@PostMapping("del")
public Result delProduct(@RequestBody Integer[] ids){
int n = productService.deleteBatchProduct(ids);
if(n>0){
return new Result();
}else{
return new Result().error(400,"删除商品失败");
}
}
/**
* 分页获取商品列表:执行自己的sql
* @param product 条件
* @param currentPage 当前页
* @param pageSize 每页个数
* @return
*/
@PostMapping("/productList")
public Result productList(@RequestBody Product product ,@RequestParam Integer currentPage,@RequestParam Integer pageSize){
Page<Product> page = new Page<>(currentPage,pageSize);
//分页查看商品列表
List<Map<String,Object>> list = productService.getProductListByPage(page,product);
//返回结果集
return new Result().ok(new PageData<>(list,page.getTotal()));
}
}
6.在启动类上,添加dao的扫描
响应数据做了相关的处理:封装了一个类
package com.example.demo.utils;
import java.io.Serializable;
/**
* 响应数据
* @author qzz
*/
public class Result<T> implements Serializable {
private static final long serialVersionUID=1L;
/**
* 编码 0:成功 其他值代表失败
*/
private int code = 0;
/**
* 消息内容
*/
private String msg = "success";
/**
* 响应数据
*/
private T data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Result<T> ok (T data){
this.setData(data);
return this;
}
public Result<T> error(){
this.code = 500;
this.msg="网络出错,请联系系统管理员";
return this;
}
public Result<T> error(int code,String msg){
this.code = code;
this.msg=msg;
return this;
}
public boolean success(){
return code == 0 ? true : false;
}
}
另外,有关分页查询,mybatis-plus有提供分页插件,使用如下:
(1)添加配置类
package com.example.demo.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 新建一个MybatisPlus配置类 返回一个分页拦截器
* @author qzz
*/
@Configuration
@MapperScan(basePackages = {"com.example.demo.dao"})
public class MybatisPlusConfig {
/**
* Mybatis Plus 3.4.0版本及其之后的版本采用新的分页:
* 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//向Mybatis过滤器链中添加分页拦截器
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//还可以添加其他的拦截器
return mybatisPlusInterceptor;
}
}
(2)使用
其中分页工具类PageData:
package com.example.demo.utils;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 分页工具类
* @author qzz
*/
@Data
public class PageData<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 总记录数
*/
private int total;
/**
* 列表数据
*/
private List<T> list;
public PageData(List<T> list, long total){
this.list = list ;
this.total = (int) total;
}
}
这样一个简单的增删改查demo就编写好了。
四、测试
使用postman进行测试:
1.商品添加(product/add)
注意点:
请求方式:POST
请求头:Content-Type:application/json
请求参数:
点击测试,返回结果:
数据库新增了一条记录:
使用添加接口多添加几条数据,如下:
2.商品编辑(product/update)
把product_id=2的title修改为 家局创意垃圾桶。
编辑接口的请求方式和请求头 与 商品添加接口 相同。
数据库数据:
3.分页查询商品列表(product/page)
4.分页获取商品列表:执行自己编写的sql(product/productList)
相关文章
- MySQL 优化案例 - select count(*)
- JavaWeb-SpringBoot_使用MySQL管理用户登录注册+接入腾讯短信SDK_demo
- JavaWeb-SpringBoot_使用MySQL数据库实现用户管理_demo
- Mysql授权允许远程访问解决Navicat for MySQL连接mysql提示客户端不支持服务器请求的身份验证协议;考虑升级MySQL客户端
- mysql索引常见问题
- mysql数据库-进阶-长期维护
- Mysql + keepalived 实现双主热备读写分离
- sql server 模仿mysql的方法
- ^全^ 获取SQL SERVER2000/2005、MySql、Oracle元数据的SQL语句 [SQL语句来自CodeSmith]
- Linux重置Mysql密码_解决MySQL for Linux错误 ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost
- MySQL ADDTIME(t,n)时间 t 加上 n 秒的时间
- 【高可用MySQL解决方案】centos7配置mysql主从复制
- ERROR 2002 (HY000): Can‘t connect to local MySQL server through socket ‘/tmp/mysql.sock‘
- 基于注解SpringAOP,AfterReturning,Before,Around__springboot工程 @Around 简单的使用__SpringBoot:AOP 自定义注解实现日志管理
- MySQL 聚簇索引和非聚簇索引 & mysql 索引为啥用b 树
- file /usr/share/mysql/charsets/README from install of MySQL-server-5.1.73-1.glibc23.i386 conflicts with file from package mysql-libs-5.1.73-8.el6_8.i686
- Mysql的mysqldump详解 mysql数据库备份和导入
- MySQL技术内幕读书笔记(一)——Mysql体系结构和存储引擎
- Groonga开源搜索引擎——列存储做聚合,没有内建分布式,分片和副本是随mysql或者postgreSQL作为存储引擎由MySQL自身来做分片和副本的
- MySQL中的位类型
- Mysql查看版本
- MySQL LEFT/RIGHT JOIN:外连接查询