MyBatis Plus(简称MP)是一个在MyBatis基础上进行增强的工具,它保留了MyBatis的所有特性,并通过提供额外的功能和简化操作来提高开发效率。以下是对MyBatis Plus的详细介绍:
一、基本概述
- 定义:MyBatis Plus是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,旨在简化开发、提高效率。
- 官网:https://mybatis.plus/ 或 Redirect
二、主要特性
- 简化CRUD操作:
- MyBatis Plus提供了通用的Mapper接口和Service接口,简化了常见的CRUD(增删改查)操作。
- 无需编写XML文件和手动编写SQL语句,只需继承通用Mapper接口或Service接口,即可使用常见的CRUD方法。
- 代码自动生成:
- MyBatis Plus内置了代码生成器,可以根据数据库表自动生成实体类、Mapper接口和XML文件,大大减少了手动编写代码的工作量。
- 分页查询:
- 提供了分页插件,可以在查询数据时直接指定分页参数,方便进行分页查询。
- 条件构造器:
- 提供了条件构造器,可以通过链式调用的方式生成查询条件,使得查询条件更加清晰易读。
- 乐观锁支持:
- 提供了乐观锁的支持,可以在更新数据时进行版本校验,避免数据冲突问题。
- 自动填充:
- 提供了自动填充功能,可以在插入或更新数据时自动填充某些字段,如创建时间和更新时间等。
- 多租户支持:
- 提供了多租户的支持,可以在查询数据时自动根据租户ID添加过滤条件,实现多租户数据隔离。
- 其他特性:
- 支持Lambda形式调用,通过Lambda表达式方便地编写各类查询条件。
- 支持主键自动生成,提供了多达4种主键策略(内含分布式唯一ID生成器)。
- 支持ActiveRecord模式,实体类只需继承Model类即可进行强大的CRUD操作。
- 提供了性能分析插件,可输出SQL语句及其执行时间,帮助开发者优化查询。
三、架构与原理
- 核心组件:MyBatis Plus的核心组件包括mybatis-plus-boot-starter(Spring Boot场景启动器)、注解(用于更高效地完成持久层开发)、extension(提供分页、逻辑删除、自动填充等扩展功能)、generator(代码生成器)以及core(核心功能)。
- 运行原理:MyBatis Plus通过自动扫描实体,将数据库表中的列名和表名通过反射机制自动生成对应的代码,包括持久层的CRUD操作。
四、与MyBatis的区别
- 语法简化:MyBatis Plus通过使用注解和API简化了MyBatis的配置和操作,减少了开发者的编码量。
- 自动代码生成:MyBatis Plus提供了代码生成器,而MyBatis需要手动编写所有代码。
- 分页插件:MyBatis Plus内置了分页插件,而MyBatis需要手动实现分页逻辑。
-
条件查询:MyBatis Plus提供了强大的条件查询功能,而MyBatis则需要编写复杂的SQL语句来实现。
五、核心注解
1. @TableName
用途:用于指定实体类对应的数据库表名。
作用:告诉MyBatis Plus在进行SQL操作时应该使用哪个表。
详细说明:当实体类名与数据库表名不一致时,可以使用@TableName注解来指定实体类对应的数据库表名。这样,MyBatis Plus在执行SQL操作时就会使用指定的表名。
例如:
package com.cjq.holiday1.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@TableName(value="t_goods")
public class Goods {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Integer goodsId;
/**
* 商品名字
*/
private String goodsName;
/**
* 商品时间
*/
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
private Date goodsTime;
/**
* 商品类型
*/
private Integer typeId;
}
在这个示例中,Goods
类将映射到数据库中的t_goods
表。
package com.cjq.holiday1.domain.request;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
@Data
public class GoodsReq {
private String goodsName;
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
private Date startTime;
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
private Date endTime;
private Integer typeId;
}
这个是用来查询的。
2. @TableId
用途:用于标识主键字段,并指定主键生成策略。
详细说明:@TableId注解不仅可以指定实体类中的哪个字段是主键,还可以指定主键的生成策略。MyBatis Plus提供了多种主键生成策略,如自增(IdType.AUTO)、手动输入(IdType.INPUT)、分布式全局唯一ID(IdType.ASSIGN_ID)等。
常用属性:
value
:指定主键字段名(默认值就是属性名)。type
:指定主键生成策略,如IdType.AUTO
(自动增长)、IdType.INPUT
(手动输入)、IdType.ASSIGN_ID
(分配ID,默认使用雪花算法)等。
在这个示例中,id字段被标识为主键,并且采用自动增长的方式生成主键值。
package com.cjq.holiday1.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@TableName(value="t_goods")
public class Goods {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Integer goodsId;
/**
* 商品名字
*/
private String goodsName;
/**
* 商品时间
*/
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
private Date goodsTime;
/**
* 商品类型
*/
private Integer typeId;
}
3. @TableField
用途:用于标识实体类中的字段与数据库表中的字段的映射关系。
详细说明:@TableField注解可以指定字段名、是否为数据库字段、自定义字段填充策略等。当实体类中的字段名与数据库表中的字段名不一致时,可以使用@TableField注解的value属性来指定数据库表中的字段名。此外,@TableField还可以用于指定字段的填充策略,如插入时填充、更新时填充等。
常用属性:
value
:指定数据库表中的字段名(默认值就是属性名)。exist
:用于指明该字段是否是数据库表中的字段,默认为true
。fill
:用于指定字段填充策略,如FieldFill.INSERT
(插入时填充)、FieldFill.UPDATE
(更新时填充)等。@TableField(value = "user_name", exist = true, fill = FieldFill.INSERT) private String userName;
在这个示例中,
userName
字段映射到数据库表中的user_name
字段,且在插入数据时由自定义的填充策略进行填充。
六、控制层(Controller)
package com.cjq.holiday1.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cjq.holiday1.domain.Goods;
import com.cjq.holiday1.domain.request.GoodsReq;
import com.cjq.holiday1.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
public class GoodsController {
@Autowired
private GoodsService goodsService;
/**
* 根据ID查询
* @param goodsId
* @return
*/
@GetMapping("/findById/{goodsId}")
public Goods findById(@PathVariable String goodsId){
Goods goods = goodsService.getById(goodsId);
return goods;
}
/**
* 列表查询(模糊、区间、精确)
* @param goodsReq
* @return
*/
@GetMapping("/goodsList")
public List<Goods> goodsList(@RequestBody GoodsReq goodsReq){
QueryWrapper<Goods> queryWrapper = new QueryWrapper<>();
queryWrapper
.like(goodsReq.getGoodsName()!=null&&goodsReq.getGoodsName()!="","goods_name",goodsReq.getGoodsName())
.gt(goodsReq.getStartTime()!=null,"goods_time",goodsReq.getStartTime())
.lt(goodsReq.getEndTime()!=null,"goods_time",goodsReq.getEndTime())
.eq(goodsReq.getTypeId()!=null,"type_id",goodsReq.getTypeId());
return goodsService.list(queryWrapper);
}
/**
* 添加
* @param goods
* @return
*/
@PostMapping("/insert")
public boolean insert(@RequestBody Goods goods){
return goodsService.save(goods);
}
/**
* 修改
* @param goods
* @return
*/
@PutMapping("/update")
public boolean update(@RequestBody Goods goods){
return goodsService.updateById(goods);
}
/**
* 单删
* @param goodsId
* @return
*/
@DeleteMapping("/delete/{goodsId}")
public boolean delete(@PathVariable String goodsId){
return goodsService.removeById(goodsId);
}
}
七、业务层(Service)
1. IService<T>和ServiceIMpl<M extends BaseMapper<T>,T> 是对BaseMapper的进一步封装,一般很少用,但是很方便。
package com.cjq.holiday1.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.cjq.holiday1.domain.Goods;
public interface GoodsService extends IService<Goods> {
}
package com.cjq.holiday1.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cjq.holiday1.domain.Goods;
import com.cjq.holiday1.mapper.GoodsMapper;
import com.cjq.holiday1.service.GoodsService;
import org.springframework.stereotype.Service;
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper,Goods> implements GoodsService {
}
八、持久层(Mapper)
1. BaseMapper<T>是mybatis-plus设计的一个接口,里面包含了单表的CRUD,用起来非常方便。
<T>表示实体类
package com.cjq.holiday1.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cjq.holiday1.domain.Goods;
public interface GoodsMapper extends BaseMapper<Goods> {
}
九、启动类
package com.cjq.holiday1;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan(basePackages = "com.cjq.holiday1.mapper")
public class GoodsApplication {
public static void main(String[] args) {
SpringApplication.run(GoodsApplication.class, args);
}
}
十、application.yml配置文件
注意:直接顶头粘贴
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #日志
map-underscore-to-camel-case: true #开启驼峰命名
##应用服务 WEB 访问端口
server:
port: 8081
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/holiday1
username: root
password: root
#下面这些内容是为了让MyBatis映射
#指定Mybatis的Mapper文件
mybatis:
mapper-locations: classpath:mappers/*xml
#指定Mybatis的实体目录
type-aliases-package: com.cjq.goods.domain
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #日志
map-underscore-to-camel-case: true #开启驼峰命名
十一、结果
1.模糊查询
2.区间查询
3.精确查询