损耗小:启动即会自动注入基本 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-Plus的原理是通过扩展MyBatis的功能来实现的。它通过自定义的Mapper接口和Mapper XML文件,使用MyBatis的注解和动态SQL等特性,来实现更加灵活和高效的数据库访问。
MyBatis-Plus的核心原理包括代码生成和SQL解析两个方面
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybatis plus和springboot整合-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
server.port=8081
#==============================数据库相关配置========================================
spring.datasource.driver-class-name =com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/shop?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username =root
spring.datasource.password =123456
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor //会生成一个包含所有变量
@NoArgsConstructor //生成一个无参数的构造方法
public class JsonData {
/**
* 状态码 0 表示成功,1表示处理中,-1表示失败
*/
private Integer code;
/**
* 数据
*/
private Object data;
/**
* 描述
*/
private String msg;
// 成功,传入数据
public static JsonData buildSuccess() {
return new JsonData(0, null, null);
}
// 成功,传入数据
public static JsonData buildSuccess(Object data) {
return new JsonData(0, data, null);
}
// 失败,传入描述信息
public static JsonData buildError(String msg) {
return new JsonData(-1, null, msg);
}
// 失败,传入描述信息,状态码
public static JsonData buildError(String msg, Integer code) {
return new JsonData(code, null, msg);
}
}
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("banner") // 指定数据库的表名,如果类名和数据库表名不一致需要指定
public class BannerDO {
private Integer id;
private String img;
private String url;
private Integer weight;
}
/**
* 创建mapper接口,继承BaseMapper,并指定bean
*/
public interface BannerMapper extends BaseMapper<BannerDO> {
}
创建接口
import java.util.List;
public interface BannerService {
public List<BannerDO> list();
}
创建接口实现类
import java.util.List;
@Service
public class BannerServiceImpl implements BannerService {
@Autowired
private BannerMapper bannerMapper;
@Override
public List<BannerDO> list() {
//查询全部
List<BannerDO> list = bannerMapper.selectList(new QueryWrapper<BannerDO>());
return list;
}
}
@RestController
@RequestMapping("/api/banner/v1")
public class BannerController {
@Autowired
private BannerService bannerService;
@RequestMapping("list")
public JsonData list(){
return JsonData.buildSuccess(bannerService.list());
}
}
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
添加单元测试类
@SpringBootTest(classes = MybatisplusLombokSwagger3Application.class)
@Slf4j
class BannerTests {
@Autowired
private BannerService bannerService;
@Test
public void testBannerList(){
List<BannerDO> list = bannerService.list();
log.info("轮播图列表:{}",list);
}
}
添加打印sql的配置
#配置mybatis plus打印sql日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
BaseMapper是MyBatis-Plus提供的一个通用Mapper接口,可以用于快速开发数据访问层。它提供了常见的CRUD操作方法,如插入、修改、删除和查询等,适用于各种实体类的操作。
方法很多:记住常用的几个就行。可以查看源码的说明,如下
/**
* Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
* 这个 Mapper 支持 id 泛型
*
* @author hubin
* @since 2016-01-23
*/
public interface BaseMapper<T> extends Mapper<T> {
/**
* 插入一条记录
*
* @param entity 实体对象
*/
int insert(T entity);
/**
* 根据 ID 删除
*
* @param id 主键ID
*/
int deleteById(Serializable id);
/**
* 根据 columnMap 条件,删除记录
*
* @param columnMap 表字段 map 对象
*/
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
/**
* 根据 entity 条件,删除记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
*/
int delete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 删除(根据ID 批量删除)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
/**
* 根据 ID 修改
*
* @param entity 实体对象
*/
int updateById(@Param(Constants.ENTITY) T entity);
/**
* 根据 whereEntity 条件,更新记录
*
* @param entity 实体对象 (set 条件值,可以为 null)
* @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
*/
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
/**
* 根据 ID 查询
*
* @param id 主键ID
*/
T selectById(Serializable id);
/**
* 查询(根据ID 批量查询)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
/**
* 查询(根据 columnMap 条件)
*
* @param columnMap 表字段 map 对象
*/
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
/**
* 根据 entity 条件,查询一条记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询总记录数
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
* 注意: 只返回第一个字段的值
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
<E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件
* @param queryWrapper 实体对象封装操作类
*/
<E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
}
QueryWrapper是MyBatis Plus中非常方便的查询封装类,可以大大简化查询语句的编写,提高开发效率。可以封装多数查询条件,泛型指定返回的实体类
List<BannerDO> list = bannerMapper.selectList(new QueryWrapper<BannerDO>());
在测试类中测试这些API
@SpringBootTest
@Slf4j
public class BaseMapperTest {
@Autowired
private BannerMapper bannerMapper;
/**
* 主键id查找
*/
@Test
public void selectByIdTest(){
BannerDO bannerDO = bannerMapper.selectById(1);
log.info("bannerDO:{}",bannerDO);
}
/**
* 主键批量查找
*/
@Test
public void selectBatchIdsTest(){
List<BannerDO> list = bannerMapper.selectBatchIds(Arrays.asList("1","2"));
log.info("list:{}",list);
}
/**
* 查询一条
*/
@Test
public void selectOneTest(){
BannerDO bannerDO = bannerMapper.selectOne(new QueryWrapper<BannerDO>().eq("id",1));
log.info("bannerDO:{}",bannerDO);
}
/**
* 查询条数
*/
@Test
public void selectCountTest(){
int count = bannerMapper.selectCount(null);
log.info("bannerDO:{}",count);
}
}
IdType.AUTO 主键自增,系统分配,不需要手动输入
IdType.NONE 未设置主键
IdType.INPUT 需要自己输入 主键值
IdType.ASSIGN_ID 系统分配 ID,用于数值型数据(Long,对应 mysql 中 BIGINT 类型)
IdType.ASSIGN_UUID 系统分配 UUID,用于字符串型数据(String,对应 mysql 中 varchar(32) 类型)
mybatis-plus.global-config.db-config.id-type=auto
字段填充策略:一般用于填充 创建时间、修改时间等字段
FieldFill.DEFAULT 默认不填充
FieldFill.INSERT 插入时填充
FieldFill.UPDATE 更新时填充
FieldFill.INSERT_UPDATE 插入、更新时填充。
/**
* 新增
*/
@Test
public void insertTest(){
BannerDO bannerDO = new BannerDO();
bannerDO.setImg("img");
bannerDO.setUrl("URL");
int count = bannerMapper.insert(bannerDO);
log.info("bannerDO:{}",count);
}
@Test
public void deleteByIdTest(){
int rows = bannerMapper.deleteById(4);
log.info("rows:{}",rows);
}
/**
* 通用删除操作 deleteByMap map要写列名条件 不能是实体属性名
*/
@Test
public void commonDeleteByMapTest() {
Map<String, Object> columnMap = new HashMap<>();
columnMap.put("weight",12);
columnMap.put("url","bbb");
int result=bannerMapper.deleteByMap(columnMap);
System.out.println("*******************"+result);
}
/**
* 根据主键更新
*/
@Test
public void updateByIdTest() {
BannerDO bannerDO = new BannerDO();
bannerDO.setId(2);
bannerDO.setImg("jjjjjj");
//空字段不会更新
bannerMapper.updateById(bannerDO);
}
/**
* 条件更新
*/
@Test
public void updateTest() {
BannerDO bannerDO = new BannerDO();
bannerDO.setImg("iiiii");
//空字段不会更新
bannerMapper.update(bannerDO,new QueryWrapper<BannerDO>().eq("id","1"));
}
/**
* 使用updateWrapper更新
*/
@Test
public void updateWrapperTest() {
UpdateWrapper updateWrapper = new UpdateWrapper();
//设置要更新的字段和值,key是db的属性名称
updateWrapper.set("img","uuuu");
//条件
updateWrapper.eq("id",1);
bannerMapper.update(null,updateWrapper);
}
List<BannerDO> list = bannerMapper.selectList(new QueryWrapper<BannerDO>());
配置分页插件
@Configuration
public class MybatisPlusPageConfig {
/**
* 新的分页插件
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
测试分页代码
/***
* 测试分页
*/
@Test
public void testPage() {
QueryWrapper<BannerDO> wrapper = new QueryWrapper<>();
wrapper.eq("weight",4);
//第1页,每页2条
Page<BannerDO> page = new Page<>(1, 2);
IPage<BannerDO> bannerDOIPage = bannerMapper.selectPage(page, wrapper);
System.out.println("总条数"+bannerDOIPage.getTotal());
System.out.println("总页数"+bannerDOIPage.getPages());
//获取当前数据
System.out.println(bannerDOIPage.getRecords().toString());
}