MyBatis-plus (简称mp)是一款 Mybatis 增强工具,用来简化开发、增强效率。本文结合Spring Boot来实现mp的快速入门。
注:本文演示mp版本为当前最新的3.5.1
官方网站:https://baomidou.com/
1、创建SpringBoot项目
2、导入依赖
<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.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.7.2version>
<relativePath/>
parent>
<groupId>com.examplegroupId>
<artifactId>mybatis-plus-demoartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>mybatis-plus-demoname>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.5.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.20version>
<scope>runtimescope>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
exclude>
excludes>
configuration>
plugin>
plugins>
build>
project>
3、配置
application.yml配置文件
spring:
datasource:
#mysql驱动6.0版本以上的为com.mysql.cj.jdbc.Driver
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test
username: root
password: root1234
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启SQL语句打印
4、数据库脚本
DROP TABLE IF EXISTS user;
CREATE TABLE user
(
id BIGINT(20) NOT NULL COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT(11) NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);
DELETE FROM user;
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]');
5、编码
实体类:
package com.example.demo.po;
import lombok.Data;
/**
* 〈实体类,类名和属性名需要符合驼峰命名法,可以不用关联表名,mybatis会自动关联〉
* 否则需要使用mybatis的@TableName,@TableId,@TableField等注解,将实体类和表关联
*/
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
mapper接口:
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.po.User;
public interface UserMapper extends BaseMapper<User> {
}
service接口
package com.example.demo.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo.po.User;
public interface UserService extends IService<User> {
}
service实现类:
package com.example.demo.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.mapper.UserMapper;
import com.example.demo.po.User;
import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
Spring Boot 启动类:
package com.example.mybatisplusdemo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = "com.example")
@MapperScan("com.example.demo.mapper")
public class MybatisPlusDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusDemoApplication.class, args);
}
}
测试类
package com.example.mybatisplusdemo;
import com.example.demo.mapper.UserMapper;
import com.example.demo.po.User;
import com.example.demo.service.UserService;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
class MybatisPlusDemoApplicationTests {
@Autowired
private UserMapper userMapper;
@Autowired
private UserService userService;
@Test
void contextLoads() {
List<User> userList = userMapper.selectList(null);
userList.forEach(System.out::println);
}
@Test
void test(){
List<User> userList = userService.getBaseMapper().selectList(null);
userList.forEach(System.out::println);
}
}
运行测试方法结果:
项目结构:
mp的service里定义了mapper,我们在service里使用mapper时无需注入,直接使用this.baseMapper即可。
表名注解,标识实体类对应的表。如果类名使用驼峰命名法命名,可以不使用该注解。示例:ta_user表对应的实体类为taUser。或者表名与类名相同也无需使用该注解
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 表名 |
schema | String | 否 | "" | schema |
keepGlobalPrefix | boolean | 否 | false | 是否保持使用全局的 tablePrefix 的值(当全局 tablePrefix 生效时) |
resultMap | String | 否 | "" | xml 中 resultMap 的 id(用于满足特定类型的实体类对象绑定) |
autoResultMap | boolean | 否 | false | 是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建与注入) |
excludeProperty | String[] | 否 | {} | 需要排除的属性名 @since 3.3.1 |
主键注解,用在主键字段上
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 主键字段名 |
type | Enum | 否 | IdType.NONE | 指定主键类型 |
IdType的值
值 | 描述 |
---|---|
AUTO | 数据库 ID 自增 |
NONE | 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT) |
INPUT | insert 前自行 set 主键值 |
ASSIGN_ID | 分配 ID(主键类型为 Number(Long 和 Integer)或 String)(since 3.3.0),使用接口IdentifierGenerator 的方法nextId (默认实现类为DefaultIdentifierGenerator 雪花算法) |
ASSIGN_UUID | 分配 UUID,主键类型为 String(since 3.3.0),使用接口IdentifierGenerator 的方法nextUUID (默认 default 方法) |
分布式全局唯一 ID 长整型类型(please use ASSIGN_ID ) |
|
32 位 UUID 字符串(please use ASSIGN_UUID ) |
|
分布式全局唯一 ID 字符串类型(please use ASSIGN_ID ) |
字段注解(非主键)
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 数据库字段名 |
exist | boolean | 否 | true | 是否为数据库表字段 |
condition | String | 否 | "" | 字段 where 实体查询比较条件,有值设置则按设置的值为准,没有则为默认全局的 %s=#{%s} ,参考 (opens new window) |
update | String | 否 | "" | 字段 update set 部分注入,例如:当在version字段上注解update="%s+1" 表示更新时会 set version=version+1 (该属性优先级高于 el 属性) |
insertStrategy | Enum | 否 | FieldStrategy.DEFAULT | 举例:NOT_NULL insert into table_a( |
updateStrategy | Enum | 否 | FieldStrategy.DEFAULT | 举例:IGNORED update table_a set column=#{columnProperty} |
whereStrategy | Enum | 否 | FieldStrategy.DEFAULT | 举例:NOT_EMPTY where |
fill | Enum | 否 | FieldFill.DEFAULT | 字段自动填充策略 |
select | boolean | 否 | true | 是否进行 select 查询 |
keepGlobalFormat | boolean | 否 | false | 是否保持使用全局的 format 进行处理 |
jdbcType | JdbcType | 否 | JdbcType.UNDEFINED | JDBC 类型 (该默认值不代表会按照该值生效) |
typeHandler | Class extends TypeHandler> | 否 | UnknownTypeHandler.class | 类型处理器 (该默认值不代表会按照该值生效) |
numericScale | String | 否 | "" | 指定小数点后保留的位数 |
FieldStrategy
字段验证策略
值 | 描述 |
---|---|
IGNORED | 忽略判断 |
NOT_NULL | 非 NULL 判断 |
NOT_EMPTY | 非空判断(只对字符串类型字段,其他类型字段依然为非 NULL 判断) |
DEFAULT | 追随全局配置 |
NEVER | 不加入SQL |
FieldFill
字段填充策略
值 | 描述 |
---|---|
DEFAULT | 默认不处理 |
INSERT | 插入时填充字段 |
UPDATE | 更新时填充字段 |
INSERT_UPDATE | 插入和更新时填充字段 |
乐观锁注解、标记 @Verison 在字段上,作为版本号。
普通枚举类注解(注解在枚举字段上)
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 逻辑未删除值 |
delval | String | 否 | "" | 逻辑删除值 |
序列主键策略 (oracle)
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 序列名 |
clazz | Class | 否 | Long.class | id 的类型, 可以指定 String.class,这样返回的 Sequence 值是字符串"1" |
内置 SQL 默认指定排序,优先级低于 wrapper 条件查询
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
isDesc | boolean | 否 | true | 是否倒序查询 |
sort | short | 否 | Short.MAX_VALUE | 数字越小越靠前 |
插件过滤规则
mp封装了一些最基础的CRUD方法,只需要直接继承mp提供的接口,无需编写任何SQL,即可食用。mp提供了两套接口,分别是Mapper CRUD接口和Service CRUD接口。并且mp还提供了条件构造器Wrapper,可以方便地组装SQL语句中的WHERE条件。
只需定义好实体类,然后创建一个接口,继承mp提供的BaseMapper,即可使用。mp会在mybatis启动时,自动解析实体类和表的映射关系,并注入带有通用CRUD方法的mapper。
部分方法示例:
insert(T entity) 插入一条记录
deleteById(Serializable id) 根据主键id删除一条记录
delete(Wrapper<T> wrapper) 根据条件构造器wrapper进行删除
deleteByMap(Map<String, Object> columnMap) 根据多个列删除数据
deleteBatchIds(Collection<?> idList) 根据主键id进行批量删除
selectById(Serializable id) 根据主键id进行查找
selectBatchIds(Collection idList) 根据主键id进行批量查找
selectByMap(Map<String,Object> map) 根据map中指定的列名和列值进行等值匹配查找
selectMaps(Wrapper<T> wrapper) 根据 wrapper 条件,查询记录,将查询结果封装为一个Map,Map的key为结果的列,value为值
selectList(Wrapper<T> wrapper) 根据条件构造器wrapper进行查询
selectOne(Wrapper<T> queryWrapper) 根据条件查找第一条记录
update(T entity, Wrapper<T> wrapper) 根据条件构造器wrapper进行更新
updateById(T entity) 根据id更新记录
exists(Wrapper<T> queryWrapper) 根据条件查找是否存在记录
selectCount(Wrapper<T> queryWrapper) 查询行数
selectPage(P page, Wrapper<T> queryWrapper) 分页查询,结果是实体类
selectMapsPage(P page, Wrapper<T> queryWrapper) 分页查询,结果是map
selectObjs(Wrapper<T> queryWrapper) 只查询第一列数据
另外一套CRUD是Service层的,只需要编写一个接口,继承IService,并创建一个接口实现类即可使用。这个接口提供的CRUD方法,和Mapper接口提供的功能大同小异,比较明显的区别在于IService支持了更多的批量化操作,如saveBatch,saveOrUpdateBatch等方法。
// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量)
boolean saveBatch(Collection<T> entityList, int batchSize);
// TableId 注解存在更新记录,否插入一条记录
boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
// 根据 entity 条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
// 根据 columnMap 条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);
// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
boolean update(Wrapper<T> updateWrapper);
// 根据 whereWrapper 条件,更新记录
boolean update(T updateEntity, Wrapper<T> whereWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);
// 根据 ID 查询
T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
// 无条件分页查询
IPage<T> page(IPage<T> page);
// 条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 无条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);
// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询(根据 columnMap 条件)
Collection<T> listByMap(Map<String, Object> columnMap);
// 查询所有列表
List<Map<String, Object>> listMaps();
// 查询列表
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 查询全部记录
List<Object> listObjs();
// 查询全部记录
<V> List<V> listObjs(Function<? super Object, V> mapper);
// 根据 Wrapper 条件,查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
// 查询总记录数
int count();
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);
// 链式查询 普通
QueryChainWrapper<T> query();
// 链式查询 lambda 式。注意:不支持 Kotlin
LambdaQueryChainWrapper<T> lambdaQuery();
// 链式更改 普通
UpdateChainWrapper<T> update();
// 链式更改 lambda 式。注意:不支持 Kotlin
LambdaUpdateChainWrapper<T> lambdaUpdate();
mp提供了强大的条件构造器Wrapper,条件构造器主要涉及到3个类,AbstractWrapper,QueryWrapper,UpdateWrapper。条件构造器也支持lambda表达式,使用LambdaQueryChainWrapper、LambdaUpdateChainWrapper。
在AbstractWrapper中提供了非常多的方法用于构建WHERE条件,而QueryWrapper针对SELECT语句,提供了select()方法,可自定义需要查询的列,而UpdateWrapper针对UPDATE语句,提供了set()方法,用于构造set语句。
AbstractWrapper中用于构建SQL语句中的WHERE条件的方法进行部分列举
eq:equals,等于
allEq:all equals,全等于
ne:not equals,不等于
gt:greater than ,大于 >
ge:greater than or equals,大于等于≥
lt:less than,小于<
le:less than or equals,小于等于≤
between:相当于SQL中的BETWEEN
notBetween
like:模糊匹配。like("name","黄"),相当于SQL的name like '%黄%'
likeRight:模糊匹配右半边。likeRight("name","黄"),相当于SQL的name like '黄%'
likeLeft:模糊匹配左半边。likeLeft("name","黄"),相当于SQL的name like '%黄'
notLike:notLike("name","黄"),相当于SQL的name not like '%黄%'
isNull
isNotNull
in
and:SQL连接符AND
or:SQL连接符OR
apply:用于拼接SQL,该方法可用于数据库函数,并可以动态传参
last:无视优化规则直接拼接到 sql 的最后
使用案例:
// 案例先展示需要完成的SQL语句,后展示Wrapper的写法
// 1. 名字中包含佳,且年龄小于25
// SELECT * FROM user WHERE name like '%佳%' AND age < 25
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("name", "佳").lt("age", 25);
List<User> users = userMapper.selectList(wrapper);
// 下面展示SQL时,仅展示WHERE条件;展示代码时, 仅展示Wrapper构建部分
// 2. 姓名为黄姓,且年龄大于等于20,小于等于40,且email字段不为空
// name like '黄%' AND age BETWEEN 20 AND 40 AND email is not null
wrapper.likeRight("name","黄").between("age", 20, 40).isNotNull("email");
// 3. 姓名为黄姓,或者年龄大于等于40,按照年龄降序排列,年龄相同则按照id升序排列
// name like '黄%' OR age >= 40 order by age desc, id asc
wrapper.likeRight("name","黄").or().ge("age",40).orderByDesc("age").orderByAsc("id");
// 4.创建日期为2021年3月22日,并且直属上级的名字为李姓
// date_format(create_time,'%Y-%m-%d') = '2021-03-22' AND manager_id IN (SELECT id FROM user WHERE name like '李%')
wrapper.apply("date_format(create_time, '%Y-%m-%d') = {0}", "2021-03-22") // 建议采用{index}这种方式动态传参, 可防止SQL注入
.inSql("manager_id", "SELECT id FROM user WHERE name like '李%'");
// 上面的apply, 也可以直接使用下面这种方式做字符串拼接,但当这个日期是一个外部参数时,这种方式有SQL注入的风险
wrapper.apply("date_format(create_time, '%Y-%m-%d') = '2021-03-22'");
// 5. 名字为王姓,并且(年龄小于40,或者邮箱不为空)
// name like '王%' AND (age < 40 OR email is not null)
wrapper.likeRight("name", "王").and(q -> q.lt("age", 40).or().isNotNull("email"));
// 6. 名字为王姓,或者(年龄小于40并且年龄大于20并且邮箱不为空)
// name like '王%' OR (age < 40 AND age > 20 AND email is not null)
wrapper.likeRight("name", "王").or(
q -> q.lt("age",40)
.gt("age",20)
.isNotNull("email")
);
// 7. (年龄小于40或者邮箱不为空) 并且名字为王姓
// (age < 40 OR email is not null) AND name like '王%'
wrapper.nested(q -> q.lt("age", 40).or().isNotNull("email"))
.likeRight("name", "王");
// 8. 年龄为30,31,34,35
// age IN (30,31,34,35)
wrapper.in("age", Arrays.asList(30,31,34,35));
// 或
wrapper.inSql("age","30,31,34,35");
// 9. 年龄为30,31,34,35, 返回满足条件的第一条记录
// age IN (30,31,34,35) LIMIT 1
wrapper.in("age", Arrays.asList(30,31,34,35)).last("LIMIT 1");
// 10. 只选出id, name 列 (QueryWrapper 特有)
// SELECT id, name FROM user;
wrapper.select("id", "name");
// 11. 选出id, name, age, email, 等同于排除 manager_id 和 create_time
// 当列特别多, 而只需要排除个别列时, 采用上面的方式可能需要写很多个列, 可以采用重载的select方法,指定需要排除的列
wrapper.select(User.class, info -> {
String columnName = info.getColumn();
return !"create_time".equals(columnName) && !"manager_id".equals(columnName);
});
条件构造器的诸多方法中,均可以指定一个boolean类型的参数condition,用来决定该条件是否加入最后生成的WHERE语句中,比如
String name = "黄"; // 假设name变量是一个外部传入的参数
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like(StringUtils.hasText(name), "name", name);
// 仅当 StringUtils.hasText(name) 为 true 时, 会拼接这个like语句到WHERE中
// 其实就是对下面代码的简化
if (StringUtils.hasText(name)) {
wrapper.like("name", name);
}
实体对象作为条件
调用构造函数创建一个Wrapper对象时,可以传入一个实体对象。后续使用这个Wrapper时,会以实体对象中的非空属性,构建WHERE条件(默认构建等值匹配的WHERE条件,这个行为可以通过实体类里各个字段上的@TableField注解中的condition属性进行改变)例如:@TableField(condition = SqlCondition.LIKE) // 配置该字段使用like进行拼接
SqlCondition类中预定义了一些字符串以供选择
package com.baomidou.mybatisplus.annotation;
public class SqlCondition {
//下面的字符串中, %s 是占位符, 第一个 %s 是列名, 第二个 %s 是列的值
public static final String EQUAL = "%s=#{%s}";
public static final String NOT_EQUAL = "%s<>#{%s}";
public static final String LIKE = "%s LIKE CONCAT('%%',#{%s},'%%')";
public static final String LIKE_LEFT = "%s LIKE CONCAT('%%',#{%s})";
public static final String LIKE_RIGHT = "%s LIKE CONCAT(#{%s},'%%')";
}
SqlCondition中提供的配置比较有限,有时需要自己拼接
例如:
@TableField(condition = “%s > #{%s}”) 表示大于
lambda条件构造器,支持lambda表达式,可以不必像普通条件构造器一样,以字符串形式指定列名,它可以直接以实体类的方法引用来指定列。
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.like(User::getName, "黄").lt(User::getAge, 30);
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
lambda条件构造器可以链式调用,使代码更简洁
LambdaQueryChainWrapper<User> chainWrapper = new LambdaQueryChainWrapper<>(userMapper);
List<User> users = chainWrapper.like(User::getName, "黄").gt(User::getAge, 30).list();
users.forEach(System.out::println);
@Test
void selectTest(){
//QueryWrapper查询
List<User> userList = userService.getBaseMapper().selectList(
new QueryWrapper<User>().eq("name","Jack")
);
userList.forEach(System.out::println);
//LambdaQueryWrapper查询
List<User> userList1 = userService.getBaseMapper().selectList(
new LambdaQueryWrapper<User>().eq(User::getName,"Jack")
);
userList1.forEach(System.out::println);
//LambdaQueryChainWrapper查询
List<User> userList2 = userService.lambdaQuery().eq(User::getName,"Jack").list();
userList2.forEach(System.out::println);
}
@Test
void updateTest(){
//UpdateWrapper更新
boolean flag = userService.update(
new UpdateWrapper<User>()
.eq("name","Jack")
.set("age",20)
);
System.out.println(flag);
//LambdaUpdateWrapper更新
boolean flag1 = userService.update(
new LambdaUpdateWrapper<User>()
.in(User::getId,new int[]{1,2})
.set(User::getAge,18)
);
System.out.println(flag1);
boolean flag2 = userService.lambdaUpdate()
.in(User::getId,new String[]{"1","2"})
.set(User::getAge,17)
.update();
System.out.println(flag2);
}
@Test
void insertTest(){
User user1 = new User();
user1.setId(6L);
user1.setName("Mic");
user1.setAge(29);
user1.setEmail("[email protected]");
int count = userMapper.insert(user1);
System.out.println(count);
User user2 = new User();
user2.setId(7L);
user2.setName("Sam");
user2.setAge(23);
user2.setEmail("[email protected]");
boolean falg = userService.save(user2);
System.out.println(falg);
}
@Test
void deleteTest(){
int result = userMapper.delete(new QueryWrapper<User>().eq("id",6));
System.out.println(result);
int result2 = userMapper.delete(new LambdaQueryWrapper<User>().eq(User::getId,7));
System.out.println(result);
}
mp使用分页查询前,需要先把分页查询查插件注册到spring中
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.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
/** 新版mp **/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
/** 旧版mp 用 PaginationInterceptor **/
}
分页查询示例:
@Test
void selectpageTest(){
//QueryWrapper查询
IPage<User> pageList = userService.getBaseMapper().selectPage(
new Page<User>(0,2),
new QueryWrapper<User>()
);
List<User> userList = pageList.getRecords();
userList.forEach(System.out::println);
IPage<User> pageList1 = userService.getBaseMapper().selectPage(
new Page<User>(0,2),
new LambdaQueryWrapper<User>()
);
List<User> userList1 = pageList1.getRecords();
userList1.forEach(System.out::println);
IPage<User> pageList2 = userService.lambdaQuery().page(new Page<User>(0,2));
List<User> userList2 = pageList2.getRecords();
userList2.forEach(System.out::println);
分页查询默认会先查count总条数,如果不希望查count,可以通过Page的重载构造函数,指定isSearchCount为false即可
public Page(long current, long size, boolean isSearchCount)
使用mybatis原生的方式做查询时,如果需要使用分页,可以在接口上加上page参数:Param(“page”) Page<> page,即可使用分页方法,而无需在sql中写分页语句
mp在mybatis的基础上做了增强,提供许多简单的CRUD方法,我们拿来直接用即可。而且mp也保留了原生的mybatis的功能,我们也可以使用原生的在mapper.xml中写sql的方式执行crud。本文只是介绍了mybatis-plus的基础功能,方便新手快速入门,mybatis-plus还有许多有趣的功能,可以自行去官网查阅。