MyBatis-Plus使用心得
最近,在整理一些自己的知识。像mybatis在持久层框架中还是比较火的,一般项目都是基于ssm。虽然mybatis可以直接在xml中通过SQL语句操作数据库,很是灵活。但操作都要通过SQL语句进行,就必须写大量的xml文件,很是麻烦。mybatis-plus就很好的解决了这个问题。
MyBatis-Plus简介
Mybatis-Plus(简称MP)是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
具体可以参考mybatis-plus官网
MyBatis-Plus特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
支持数据库
任何能使用
mybatis
进行 crud, 并且支持标准 sql 的数据库
框架结构
SpringBoot整合MyBatis-Plus
导入依赖 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ls</groupId>
<artifactId>mybatis-plus-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mybatis-plus-demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- mysql 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- druid 连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<!--lang3 依赖-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
连接数据库 application.yml
server:
port: 8086
servlet:
context-path: /
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.110.88:3306/study?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8
username: root
password: root
mybatis-plus:
mapper-locations: /mapper/*Mapper.xml
type-aliases-package: com.ls.entity*
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # sql日志打印
实体类
package com.ls.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
@TableId(type = IdType.AUTO)
private Long userId; //主键ID
private String name; //姓名
private String telephone; //电话号码
private String password; //登录密码
private String company; //公司名称
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") //后台到前台的时间格式转换
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") //前台到后台的时间格式转换
private Date createDate; //创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateDate; //修改时间
}
mapper接口
package com.ls.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ls.entity.User;
public interface UserMapper extends BaseMapper<User> {
}
分页插件
package com.ls.common;
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;
@Configuration
@MapperScan("com.ls.mapper*")
public class MyBatisPlusConfig {
/**
* 分页插件
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
测试一波
查询操作
- controller
/**
* list查询
* @return
*/
@GetMapping("/list")
@ResponseBody
public Map<String,Object> getUserList() {
Map<String,Object> map = new HashMap<>();
List<User> list = userService.getUserList();
if (CollUtil.isNotEmpty(list)){
map.put("code",200);
map.put("msg","数据查询成功");
map.put("data",list);
}else {
map.put("code",-400);
map.put("msg","数据查询失败");
}
return map;
}
- service
@Override
public List<User> getUserList() {
return userMapper.selectList(null);
}
- 测试效果
- 查看执行sql的日志信息
插入操作
- controller
/**
* 数据插入
* @param user
* @return
*/
@PostMapping("/add")
@ResponseBody
public Map<String,Object> addUser(User user) {
Map<String,Object> map = new HashMap<>();
if(user != null){
User u = userService.addUser(user);
if(u != null){
map.put("code",200);
map.put("data",u);
map.put("msg","数据插入成功");
}else {
map.put("code",-400);
map.put("msg","数据插入失败");
}
}else {
map.put("code",-400);
map.put("msg","数据为空,插入失败");
}
return map;
}
- service
@Override
public User addUser(User user) {
Date date = new Date();
user.setCreateDate(date);
int insert = userMapper.insert(user);
if(insert == 1 ){
return user;
}else {
return null;
}
}
- 效果展示
- 查看执行sql的日志信息
更新操作
- controller
/**
* 数据更新
* @param userId
* @param name
* @return
*/
@GetMapping("/update")
@ResponseBody
public Map<String,Object> updateUser(String userId , String name){
Map<String,Object> map = new HashMap<>();
User user = new User();
user.setUserId(Long.valueOf(userId));
user.setName(name);
Boolean flag = userService.updateUser(user);
if(flag){
map.put("code",200);
map.put("msg","数据更新成功");
}else {
map.put("code",-400);
map.put("msg","数据更新失败");
}
return map;
}
- service
@Override
public Boolean updateUser(User user) {
Boolean flag = false;
Date date = new Date();
user.setUpdateDate(date);
int i = userMapper.updateById(user);
if(i == 1 ){
flag = true;
}
return flag;
}
- 测试效果
- 查看执行sql的日志信息
删除操作
- controller
/**
* 数据删除
* @param userId
* @return
*/
@DeleteMapping("/del")
@ResponseBody
public Map<String,Object> deleteUser(Long userId){
Map<String,Object> map = new HashMap<>();
Boolean flag = userService.deleteUser(userId);
if(flag){
map.put("code",200);
map.put("msg","数据删除成功");
}else {
map.put("code",-400);
map.put("msg","数据删除失败");
}
return map;
}
- service
@Override
public Boolean deleteUser(Long userId) {
Boolean flag = false;
int i = userMapper.deleteById(userId);
if(i == 1 ){
flag = true;
}
return flag;
}
- 测试效果
- 查看执行sql的日志信息
分页查询
- controller
/**
* 分页查询
* @param current
* @param limit
* @return
*/
@GetMapping("/page/list")
@ResponseBody
public Map<String,Object> getPageList(int current , int limit){
Map<String, Object> map = new HashMap<>();
Map<String, Object> pageMap = userService.getPageList(current, limit);
if(pageMap.isEmpty()){
map.put("code",300);
map.put("msg","数据为空");
}else {
map.put("code",200);
map.put("total",pageMap.get("total"));
map.put("data",pageMap.get("list"));
map.put("msg","总数据:"+ pageMap.get("total") +"条,当前第"+ current +"页,每页"+ limit +"条。");
}
return map;
}
- service
@Override
public Map<String,Object> getPageList(int current, int limit) {
Map<String,Object> map = new HashMap<>();
Page<User> page = new Page<>(current,limit);
userMapper.selectPage(page, null);
List<User> userList = page.getRecords();
long total = page.getTotal();
map.put("list",userList);
map.put("total",total);
return map;
}
- 测试效果
- 查看执行sql的日志信息
条件查询
- controller
/**
* 条件查询
* @param user
* @return
*/
@GetMapping("/user")
@ResponseBody
public Map<String,Object> getUser(User user){
Map<String, Object> map = new HashMap<>();
User u = userService.getUser(user);
if(u != null){
map.put("code",200);
map.put("data",u);
map.put("msg","条件查询成功");
}else {
map.put("code",-400);
map.put("msg","条件查询失败");
}
return map;
}
- service
@Override
public User getUser(User user) {
QueryWrapper<User> wrapper = new QueryWrapper();
if(StringUtils.isNotEmpty(user.getName())){
wrapper.eq("name",user.getName());
}
if(StringUtils.isNotEmpty(user.getCompany())){
wrapper.eq("company",user.getCompany());
}
User u = userMapper.selectOne(wrapper);
if(u != null){
return u;
}else {
return null;
}
}
- 测试效果
- 查看执行sql的日志信息
条件构造器(Wrapper)
以上的条件查询,这里不再多多测试演示了,平时会分页查询中用到,登录中用到,条件信息查询中也会用到,等等。
这里我就列举一些常用的条件词:
条件词 | 解释 | 条件词 | 解释 |
---|---|---|---|
eq(键,值) | 匹配与键值相等的数据 | ne(键,值) | 匹配与键值不相等的数据 |
gt(键,值) | 匹配大于键值的数据 | ge(键,值) | 匹配大于等于键值的数据 |
lt(键,值) | 匹配小于键值的数据 | le(键,值) | 匹配小于等于键值的数据 |
between(键,值1,值2) | 匹配区间内的数据 BETWEEN 值1 AND 值2 | notBetween(键,值1,值2) | 匹配区间外的数据 NOT BETWEEN 值1 AND 值2 |
like(键,值) | 模糊查询 前后模糊 %值% | notLike(键,值) | 排除值的模糊查询 |
isNull(键,值) | 匹配键值为空的数据 | isNotNull(键,值) | 匹配键值不为空的数据 |
in(键,值1,值2,…) | 根据匹配的键值批量查询 | notIn(键,值1,值2,…) | 根据不匹配的键值批量查询 |
groupBy(键1,键2,…) | 分组查询 | orderByAsc(键1,键2,…) | 根据键值升序排列 |
orderByDesc(键1,键2,…) | 根据键值降序排列 | having(sql语句) | 在由GROUP BY子句创建的分组上设置条件 |
具体详细见官方文档:条件构造器 | MyBatis-Plus
代码自动生成器
这个代码生成器,个人不喜,勿喷。
具体详细见官方文档:代码自动生成器 | MyBatis-Plus
最后
感谢你看到这里,文章有什么不足还请指正,觉得文章对你有帮助的话记得给我点个赞,欢迎大家关注和转发文章!