MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
愿景
我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。-
● 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
● 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防 误操作
● MySQL,Oracle,DB2,H2,HSQL,SQLite,PostgreSQL,SQLServer,Phoenix,Gauss , ClickHouse,Sybase,OceanBase,Firebird,Cubrid,Goldilocks,csiidb
● 达梦数据库,虚谷数据库,人大金仓数据库,南大通用(华库)数据库,南大通用数据库,神通数据 库,瀚高数据库
官方地址: http://mp.baomidou.com
文档发布地址: https://baomidou.com/pages/24112f
CREATE TABLE `user` (
`id` bigint(20) NOT NULL COMMENT '主键ID', `name` varchar(30) DEFAULT NULL COMMENT '姓名', `age` int(11) DEFAULT NULL COMMENT '年龄', `email` varchar(50) DEFAULT NULL COMMENT '邮箱', PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.xiaowengroupId>
<artifactId>springBootDemoartifactId>
<version>1.0-SNAPSHOTversion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.6.6version>
<relativePath/>
parent>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.5.1version>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-generatorartifactId>
<version>3.5.2version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
dependencies>
project>
server:
port: 8081
spring:
# 配置数据源信息
datasource:
# 配置数据源类型
type: com.zaxxer.hikari.HikariDataSource
# 配置连接数据库信息
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springbootdemo?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
# 加入日志功能
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Long id;
private String name;
private Integer age;
private String email;
package com.xiaowen;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan(basePackages = "com.xiaowen.mapper")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class);
}
}
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xiaowen.entity.User;
import java.util.Map;
public interface UserMapper extends BaseMapper<User> {
}
@SpringBootTest
public class UserTest {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectList() {
// 通过条件构造器查询一个List集合,若没有条件,则可以设置null为参数
List<User> userList = userMapper.selectList(null);
userList.forEach(System.out::println);
}
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.baomidou.mybatisplus.core.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Param;
public interface BaseMapper<T> extends Mapper<T> {
//插入一条记录
int insert(T entity);
/**
* 根据 ID 删除
*
* @param id 主键ID
*/
int deleteById(Serializable id);
/**
* 根据实体(ID)删除
*
* @param entity 实体对象
*/
int deleteById(T entity);
/**
* 根据 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<?> 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 条件,查询一条记录
* 查询一条记录,例如 qw.last("limit 1") 限制取一条记录, 注意:多条数据会报异常
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
default T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper) {
List<T> ts = this.selectList(queryWrapper);
if (CollectionUtils.isNotEmpty(ts)) {
if (ts.size() != 1) {
throw ExceptionUtils.mpe("One record is expected, but the query result is multiple records");
}
return ts.get(0);
}
return null;
}
/**
* 根据 Wrapper 条件,判断是否存在记录
*
* @param queryWrapper 实体对象封装操作类
* @return
*/
default boolean exists(Wrapper<T> queryWrapper) {
Long count = this.selectCount(queryWrapper);
return null != count && count > 0;
}
/**
* 根据 Wrapper 条件,查询总记录数
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
Long 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)
*/
<P extends IPage<T>> P selectPage(P page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件
* @param queryWrapper 实体对象封装操作类
*/
<P extends IPage<Map<String, Object>>> P selectMapsPage(P page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
}
@Autowired
private UserMapper userMapper;
@Test
public void testSelectList() {
// 通过条件构造器查询一个List集合,若没有条件,则可以设置null为参数
List<User> userList = userMapper.selectList(null);
userList.forEach(System.out::println);
}
/**
* 通过id查询用户信息
*/
@Test
public void testSelectById(){
User user = userMapper.selectById(1L);
System.out.println("user = "+ user);
}
/**
* 批量查询多个用户信息
*/
@Test
public void testSelectBatchIds(){
List<Long> list = Arrays.asList(1L, 2L, 3L);
List<User> users = userMapper.selectBatchIds(list);
users.forEach(System.out::println);
}
/**
* 根据map集合中的条件查询用户信息
*/
@Test
public void testSelectByMap(){
// 根据map集合中的条件查询用户信息
Map<String, Object> map = new HashMap<>();
map.put("name", "Jack");
map.put("age", 18);
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
/**
* 新增功能
*/
@Test
public void testInsert() {
User user = new User();
user.setName("张三");
user.setAge(10);
user.setEmail("[email protected]");
int result = userMapper.insert(user);
}
/**
* 通过id删除用户信息
*/
@Test
public void testDeleteById(){
int result = userMapper.deleteById(1L);
}
/**
* 通过多个id批量删除
*/
@Test
public void testDeleteBatchIds(){
List<Long> idList = Arrays.asList(1L, 2L, 3L);
int result = userMapper.deleteBatchIds(idList);
}
/**
* 通过map条件删除记录
*/
@Test
public void testDeleteByMap(){
Map<String, Object> map = new HashMap<>(); map.put("age", 16);
map.put("name", "张三");
int result = userMapper.deleteByMap(map);
}
/**
* 通过id更新
*/
@Test
public void testUpdate() {
User user = new User();
user.setId(1L);
user.setName("赵六");
user.setEmail("[email protected]");
userMapper.updateById(user);
}
public interface UserService extends IService<User> {
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
package com.xiaowen;
import com.xiaowen.entity.User;
import com.xiaowen.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.ArrayList;
import java.util.List;
@SpringBootTest
public class Demo {
@Autowired
private UserService userService;
/** 查询总记录数 **/
@Test
public void testGetCount() {
long count = userService.count();
System.out.println("总记录数 = " + count);
}
/** 批量添加的功能 **/
@Test
public void testInsertMore() {
List<User> users = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
User user = new User();
user.setName("test" + i);
user.setAge(10 + i);
users.add(user);
}
boolean b = userService.saveBatch(users);
}
}
package com.xiaowen;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xiaowen.entity.User;
import com.xiaowen.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import java.util.Map;
@SpringBootTest
public class WrapperTest {
@Autowired
private UserMapper userMapper;
/** 查询用户包含a,年龄在20到30之间,邮箱信息不为null的用户信息 **/
@Test
public void test01() {
/*
SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user
WHERE is_deleted=0 AND (user_name LIKE ?
AND age BETWEEN ? AND ? AND email IS NOT NULL)
*/
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name", "a")
.between("age", 20, 30)
.isNotNull("email");
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
/** 组装排序条件 查询用户信息,按照年龄的降序排序,若年龄相同,则按照id升序排序 **/
@Test
public void test02() {
/*
SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user
WHERE is_deleted=0 ORDER BY age DESC,uid ASC
*/
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("age")
.orderByAsc("id");
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
/** 组装删除条件 删除邮箱地址为null的用户信息 **/
@Test
public void test03() {
/*
UPDATE t_user SET is_deleted=1 WHERE is_deleted=0 AND (email IS NOT NULL)
*/
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.isNull("email");
int result = userMapper.delete(queryWrapper);
System.out.println("result = " + result);
}
/** 组装修改条件 将(年龄大于20并且用户名中包含有a)或邮箱为null的用户信息修改 **/
@Test
public void test04() {
/*
UPDATE t_user SET user_name=?, email=?
WHERE is_deleted=0 AND (age > ? AND user_name LIKE ? OR email IS NOT NULL)
*/
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 20)
.like("name", "a")
.or()
.isNotNull("email");
User user = new User();
user.setName("小明");
user.setEmail("[email protected]");
int result = userMapper.update(user, queryWrapper);
System.out.println("result = " + result);
}
/** 条件优先级 将用户名中包含a并且(年龄大于20或邮箱为null)的用户信息修改 **/
@Test
public void test05() {
// lambda中条件优先级
/*
UPDATE t_user SET user_name=?, email=?
WHERE is_deleted=0 AND (user_name LIKE ? AND (age > ? OR email IS NULL))
*/
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name", "a")
.and(i -> i.gt("age", 20).or().isNull("email"));
User user = new User();
user.setName("小红");
user.setEmail("[email protected]");
int result = userMapper.update(user, queryWrapper);
System.out.println("result = " + result);
}
/** 组装select字句 查询用户名的用户名、年龄、邮箱信息 **/
@Test
public void test06() {
/*
SELECT user_name,age,email FROM t_user WHERE is_deleted=0
*/
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select("name", "age", "email");
List<Map<String, Object>> users = userMapper.selectMaps(queryWrapper);
users.forEach(System.out::println);
}
/** 组装子查询 查询id小于100的用户信息**/
@Test
public void test07() {
/*
SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user
WHERE is_deleted=0 AND (uid IN (select uid from t_user where uid <= 100))
*/
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.inSql("id", "select id from user where id <= 100");
List<User> list = userMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}
/** 使用UpdateWrapper实现修改功能 将用户名中包含a并且(年龄大于20或邮箱为null)的用户信息修改 **/
@Test
public void test08() {
/*
UPDATE t_user SET user_name=?,email=?
WHERE is_deleted=0 AND (user_name LIKE ? AND (age > ? OR email IS NULL))
*/
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.like("name", "a")
.and(i -> i.gt("age", 20).or().isNull("email"));
updateWrapper.set("name", "小黑").set("email", "[email protected]");
int result = userMapper.update(null, updateWrapper);
System.out.println("result = " + result);
}
/** 模拟开发中组装条件的情况 **/
@Test
public void test09() {
/*
SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user
WHERE is_deleted=0 AND (user_name LIKE ? AND age <= ?)
*/
String username = "a";
Integer ageBegin = null;
Integer ageEnd = 30;
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
if (StringUtils.isNotBlank(username)) {
// isNotBlank判断某个字符串是否不为空字符串、不为null、不为空白符
queryWrapper.like("name", username);
}
if (ageBegin != null) {
queryWrapper.gt("age", ageBegin);
}
if (ageEnd != null) {
queryWrapper.le("age", ageEnd);
}
List<User> list = userMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}
/** 使用condition组装条件 **/
@Test
public void test10() {
/*
SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user
WHERE is_deleted=0 AND (user_name LIKE ? AND age <= ?)
*/
String username = "a";
Integer ageBegin = null;
Integer ageEnd = 30;
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like(StringUtils.isNotBlank(username), "name", username)
.gt(ageBegin != null, "age", ageBegin)
.le(ageEnd != null, "age", ageEnd);
List<User> list = userMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}
/** LambdaQueryWrapper **/
@Test
public void test11() {
/*
SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user
WHERE is_deleted=0 AND (user_name LIKE ? AND age <= ?)
*/
String username = "a";
Integer ageBegin = null;
Integer ageEnd = 30;
//组装set子句
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
//避免使用字符串表示字段,防止运行时错误
queryWrapper.like(StringUtils.isNotBlank(username), User::getName, username)
.gt(ageBegin != null, User::getAge, ageBegin)
.le(ageEnd != null, User::getAge, ageEnd);
List<User> list = userMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}
/** LambdaUpdateWrapper **/
@Test
public void test12() {
/*
UPDATE t_user SET user_name=?,email=?
WHERE is_deleted=0 AND (user_name LIKE ? AND (age > ? OR email IS NULL))
*/
LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.like(User::getName, "a")
//lambda表达式内的逻辑优先运算
.and(i -> i.gt(User::getAge, 20).or().isNull(User::getEmail));
updateWrapper.set(User::getName, "小黑").set(User::getEmail, "[email protected]");
int result = userMapper.update(null, updateWrapper);
System.out.println("result = " + result);
}
}
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>
spring:
datasource:
# 配置数据源信息 datasource:
dynamic:
# 设置默认的数据源或者数据源组,默认值即为master
primary: master
# 严格匹配数据源,默认false.true未匹配到指定数据源时抛异常,false使用默认数据源
strict: false
datasource:
master:
url: jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
slave_1:
url: jdbc:mysql://localhost:3306/mybatis_plus_1?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
public interface UserService extends IService<User> {
}
@Service
@DS("master") // 指定所操作的数据源
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
@SpringBootTest
class MybatisPlusDatasourceApplicationTests {
@Autowired
private UserService userService;
@Autowired
private ProductService productService;
@Test
public void test() {
// 测试
System.out.println(userService.getById(1L));
System.out.println(productService.getById(1L));
}
}