添加依赖
添加MyBatis-plus依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>配置
初始化数据库
演示SQL脚本如下
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)
)INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');配置数据库连接
在 application.yml 配置文件中添加 MySql 数据库的相关配置。
spring:
datasource:
url: jdbc:mysql://localhost:3306/mybatisplus
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹
@SpringBootApplication
@MapperScan("cc.lisen.mybatisplussample.mapper")
public class MyBatisPlusSampleApplication {
public static void main(String[] args) {
SpringApplication.run(MyBatisPlusSampleApplication.class, args);
}
}快速开始
编写实体类 User.java
@Data
@TableName(value = "`user`")
public class User implements Serializable {
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 姓名
*/
@TableField(value = "`name`")
private String name;
/**
* 年龄
*/
@TableField(value = "age")
private Integer age;
/**
* 邮箱
*/
@TableField(value = "email")
private String email;
private static final long serialVersionUID = 1L;
public static final String COL_ID = "id";
public static final String COL_NAME = "name";
public static final String COL_AGE = "age";
public static final String COL_EMAIL = "email";
}编写mapper类UserMapper.java
public interface UserMapper extends BaseMapper<User> {
}编写service类IUserService.java
public interface IUserService extends IService<User>{
}编写impl类UserServiceImpl.java
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}编写controller类UserController.java
@RestController
@RequestMapping("user")
public class UserController {
@Resource
private IUserService userService;
@GetMapping("list")
public List<User> list(){
return userService.list();
}
}MyBatis-Plus常见注解
@TableName
- 描述:表名注解
| 属性 | 类型 | 必须指定 | 默认值 | 描述 |
|---|---|---|---|---|
| value | String | 否 | "" | 表名 |
| schema | String | 否 | "" | schema |
| keepGlobalPrefix | boolean | 否 | false | 是否保持使用全局的 tablePrefix 的值(如果设置了全局 tablePrefix 且自行设置了 value 的值) |
| resultMap | String | 否 | "" | xml 中 resultMap 的 id |
| autoResultMap | boolean | 否 | false | 是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建并注入) |
| excludeProperty | String[] | 否 | {} | 需要排除的属性名(@since 3.3.1) |
@TableId
- 描述:主键注解
| 属性 | 类型 | 必须指定 | 默认值 | 描述 |
|---|---|---|---|---|
| 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_WORKER | 分布式全局唯一ID 长整型类型(please use ASSIGN_ID) |
| UUID | 32位UUID字符串(please use ASSIGN_UUID) |
| ID_WORKER_STR | 分布式全局唯一ID 字符串类型(please use ASSIGN_ID) |
@TableField
- 描述:字段注解(非主键)
| 属性 | 类型 | 必须指定 | 默认值 | 描述 |
|---|---|---|---|---|
| value | String | 否 | "" | 数据库字段名 |
| el | String | 否 | "" | 映射为原生 #{ ... } 逻辑,相当于写在 xml 里的 #{ ... } 部分 |
| exist | boolean | 否 | true | 是否为数据库表字段 |
@TableLogic
- 描述:表字段逻辑处理注解(逻辑删除)
| 属性 | 类型 | 必须指定 | 默认值 | 描述 |
|---|---|---|---|---|
| value | String | 否 | "" | 逻辑未删除值 |
| delval | String | 否 | "" | 逻辑删除值 |
CRUD接口
Service CRUD 接口
说明:
- 通用 Service CRUD 封装IService接口,进一步封装 CRUD 采用
get 查询单行remove 删除list 查询集合page 分页前缀命名方式区分Mapper层避免混淆, - 泛型
T为任意实体对象 - 建议如果存在自定义通用 Service 方法的可能,请创建自己的
IBaseService继承Mybatis-Plus提供的基类 - 对象
Wrapper为 条件构造器
Save
// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量)
boolean saveBatch(Collection<T> entityList, int batchSize);参数说明
| 类型 | 参数名 | 描述 |
|---|---|---|
| T | entity | 实体对象 |
| Collection | entityList | 实体对象集合 |
| int | batchSize | 插入批次数量 |
SaveOrUpdate
// 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);参数说明
| 类型 | 参数名 | 描述 |
|---|---|---|
| T | entity | 实体对象 |
| Wrapper | updateWrapper | 实体对象封装操作类 UpdateWrapper |
| Collection | entityList | 实体对象集合 |
| int | batchSize | 插入批次数量 |
Remove
// 根据 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);参数说明
| 类型 | 参数名 | 描述 |
|---|---|---|
| Wrapper | queryWrapper | 实体包装类 QueryWrapper |
| Serializable | id | 主键ID |
| Map<String, Object> | columnMap | 表字段 map 对象 |
| Collection<? extends Serializable> | idList | 主键ID列表 |
Update
// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
boolean update(Wrapper<T> updateWrapper);
// 根据 whereEntity 条件,更新记录
boolean update(T entity, Wrapper<T> updateWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);参数说明
| 类型 | 参数名 | 描述 |
|---|---|---|
| Wrapper | updateWrapper | 实体对象封装操作类 UpdateWrapper |
| T | entity | 实体对象 |
| Collection | entityList | 实体对象集合 |
| int | batchSize | 更新批次数量 |
Get
// 根据 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);参数说明
| 类型 | 参数名 | 描述 |
|---|---|---|
| Serializable | id | 主键ID |
| Wrapper | queryWrapper | 实体对象封装操作类 QueryWrapper |
| boolean | throwEx | 有多个 result 是否抛出异常 |
| T | entity | 实体对象 |
| Function<? super Object, V> | mapper | 转换函数 |
List
// 查询所有
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);参数说明
| 类型 | 参数名 | 描述 |
|---|---|---|
| Wrapper | queryWrapper | 实体对象封装操作类 QueryWrapper |
| Collection<? extends Serializable> | idList | 主键ID列表 |
| Map<?String, Object> | columnMap | 表字段 map 对象 |
| Function<? super Object, V> | mapper | 转换函数 |
Page
// 无条件分页查询
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);参数说明
| 类型 | 参数名 | 描述 |
|---|---|---|
| IPage | page | 翻页对象 |
| Wrapper | queryWrapper | 实体对象封装操作类 QueryWrapper |
Count
// 查询总记录数
int count();
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);参数说明
| 类型 | 参数名 | 描述 |
|---|---|---|
| Wrapper | queryWrapper | 实体对象封装操作类 QueryWrapper |
Chain
query
// 链式查询 普通
QueryChainWrapper<T> query();
// 链式查询 lambda 式。注意:不支持 Kotlin
LambdaQueryChainWrapper<T> lambdaQuery();
// 示例:
query().eq("column", value).one();
lambdaQuery().eq(Entity::getId, value).list();update
// 链式更改 普通
UpdateChainWrapper<T> update();
// 链式更改 lambda 式。注意:不支持 Kotlin
LambdaUpdateChainWrapper<T> lambdaUpdate();
// 示例:
update().eq("column", value).remove();
lambdaUpdate().eq(Entity::getId, value).update(entity);Mapper CRUD 接口
说明:
- 通用 CRUD 封装BaseMapper接口,为
Mybatis-Plus启动时自动解析实体表关系映射转换为Mybatis内部对象注入容器 - 泛型
T为任意实体对象 - 参数
Serializable为任意类型主键Mybatis-Plus不推荐使用复合主键约定每一张表都有自己的唯一id主键 - 对象
Wrapper为 条件构造器
Insert
// 插入一条记录
int insert(T entity);参数说明
| 类型 | 参数名 | 描述 |
|---|---|---|
| T | entity | 实体对象 |
Delete
// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
// 删除(根据ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 ID 删除
int deleteById(Serializable id);
// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);参数说明
| 类型 | 参数名 | 描述 |
|---|---|---|
| Wrapper | wrapper | 实体对象封装操作类(可以为 null) |
| Collection<? extends Serializable> | idList | 主键ID列表(不能为 null 以及 empty) |
| Serializable | id | 主键ID |
| Map<String, Object> | columnMap | 表字段 map 对象 |
Update
// 根据 whereEntity 条件,更新记录
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
// 根据 ID 修改
int updateById(@Param(Constants.ENTITY) T entity);参数说明
| 类型 | 参数名 | 描述 |
|---|---|---|
| T | entity | 实体对象 (set 条件值,可为 null) |
| Wrapper | updateWrapper | 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句) |
Select
// 根据 ID 查询
T selectById(Serializable id);
// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 entity 条件,查询全部记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据 columnMap 条件)
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
// 根据 Wrapper 条件,查询全部记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);参数说明
| 类型 | 参数名 | 描述 |
|---|---|---|
| Serializable | id | 主键ID |
| Wrapper | queryWrapper | 实体对象封装操作类(可以为 null) |
| Collection<? extends Serializable> | idList | 主键ID列表(不能为 null 以及 empty) |
| Map<String, Object> | columnMap | 表字段 map 对象 |
| IPage | page | 分页查询条件(可以为 RowBounds.DEFAULT) |
mapper 层 选装件
说明:
选装件位于 com.baomidou.mybatisplus.extension.injector.methods 包下 需要配合Sql 注入器使用,案例(opens new window)
使用详细见
AlwaysUpdateSomeColumnById
int alwaysUpdateSomeColumnById(T entity);insertBatchSomeColumn
int insertBatchSomeColumn(List<T> entityList);deleteByIdWithFill
int deleteByIdWithFill(T entity);条件构造器
说明:
- 以下出现的第一个入参
boolean condition表示该条件是否加入最后生成的sql中,例如:query.like(StringUtils.isNotBlank(name), Entity::getName, name) .eq(age!=null && age >= 0, Entity::getAge, age) - 以下代码块内的多个方法均为从上往下补全个别
boolean类型的入参,默认为true - 以下出现的泛型
Param均为Wrapper的子类实例(均具有AbstractWrapper的所有方法) - 以下方法在入参中出现的
R为泛型,在普通wrapper中是String,在LambdaWrapper中是函数(例:Entity::getId,Entity为实体类,getId为字段id的getMethod) - 以下方法入参中的
R column均表示数据库字段,当R具体类型为String时则为数据库字段名(字段名是数据库关键字的自己用转义符包裹!)。而不是实体类数据字段名!,另当R具体类型为SFunction时项目runtime不支持eclipse自家的编译器。 - 以下举例均为使用普通wrapper,入参为
Map和List的均以json形式表现! - 使用中如果入参的
Map或者List为空,则不会加入最后生成的sql中!!!
警告:
不支持以及不赞成在 RPC 调用中把 Wrapper 进行传输
- wrapper 很重
- 传输 wrapper 可以类比为你的 controller 用 map 接收值(开发一时爽,维护火葬场)
- 正确的 RPC 调用姿势是写一个 DTO 进行传输,被调用方再根据 DTO 执行相应的操作
AbstractWrapper
说明:
QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类,用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件。
注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为
allEq
allEq(Map<R, V> params)
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)- 全部
eq或个别isNull
个别参数说明:
params : key为数据库字段名,value为字段值null2IsNull : 为true则在map的value为null时调用 isNull方法,为false时则忽略value为null的
- 例1:
allEq({id:1,name:"老王",age:null})--->id = 1 and name = '老王' and age is null - 例2:
allEq({id:1,name:"老王",age:null}, false)--->id = 1 and name = '老王'
allEq(BiPredicate<R, V> filter, Map<R, V> params)
allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) 个别参数说明:
filter : 过滤函数,是否允许字段传入比对条件中params 与 null2IsNull : 同上
- 例1:
allEq((k,v) -> k.indexOf("a") >= 0, {id:1,name:"老王",age:null})--->name = '老王' and age is null - 例2:
allEq((k,v) -> k.indexOf("a") >= 0, {id:1,name:"老王",age:null}, false)--->name = '老王'
eq
eq(R column, Object val)
eq(boolean condition, R column, Object val)- 等于 =
- 例:
eq("name", "老王")--->name = '老王'
ne
ne(R column, Object val)
ne(boolean condition, R column, Object val)- 不等于 <>
- 例:
ne("name", "老王")--->name <> '老王'
gt
gt(R column, Object val)
gt(boolean condition, R column, Object val)- 大于 >
- 例:
gt("age", 18)--->age > 18
ge
ge(R column, Object val)
ge(boolean condition, R column, Object val)- 大于等于 >=
- 例:
ge("age", 18)--->age >= 18
lt
lt(R column, Object val)
lt(boolean condition, R column, Object val)- 小于 <
- 例:
lt("age", 18)--->age < 18
le
le(R column, Object val)
le(boolean condition, R column, Object val)- 小于等于 <=
- 例:
le("age", 18)--->age <= 18
between
between(R column, Object val1, Object val2)
between(boolean condition, R column, Object val1, Object val2)- BETWEEN 值1 AND 值2
- 例:
between("age", 18, 30)--->age between 18 and 30
notBetween
notBetween(R column, Object val1, Object val2)
notBetween(boolean condition, R column, Object val1, Object val2)- NOT BETWEEN 值1 AND 值2
- 例:
notBetween("age", 18, 30)--->age not between 18 and 30
like
like(R column, Object val)
like(boolean condition, R column, Object val)- LIKE '%值%'
- 例:
like("name", "王")--->name like '%王%'
notLike
notLike(R column, Object val)
notLike(boolean condition, R column, Object val)- NOT LIKE '%值%'
- 例:
notLike("name", "王")--->name not like '%王%'
likeLeft
likeLeft(R column, Object val)
likeLeft(boolean condition, R column, Object val)- LIKE '%值'
- 例:
likeLeft("name", "王")--->name like '%王'
likeRight
likeRight(R column, Object val)
likeRight(boolean condition, R column, Object val)- LIKE '值%'
- 例:
likeRight("name", "王")--->name like '王%'
isNull
isNull(R column)
isNull(boolean condition, R column)- 字段 IS NULL
- 例:
isNull("name")--->name is null
isNotNull
isNotNull(R column)
isNotNull(boolean condition, R column)- 字段 IS NOT NULL
- 例:
isNotNull("name")--->name is not null
in
in(R column, Collection<?> value)
in(boolean condition, R column, Collection<?> value)- 字段 IN (value.get(0), value.get(1), ...)
- 例:
in("age",{1,2,3})--->age in (1,2,3)
in(R column, Object... values)
in(boolean condition, R column, Object... values)- 字段 IN (v0, v1, ...)
- 例:
in("age", 1, 2, 3)--->age in (1,2,3)
notIn
notIn(R column, Collection<?> value)
notIn(boolean condition, R column, Collection<?> value)- 字段 NOT IN (value.get(0), value.get(1), ...)
- 例:
notIn("age",{1,2,3})--->age not in (1,2,3)
notIn(R column, Object... values)
notIn(boolean condition, R column, Object... values)- 字段 NOT IN (v0, v1, ...)
- 例:
notIn("age", 1, 2, 3)--->age not in (1,2,3)
inSql
inSql(R column, String inValue)
inSql(boolean condition, R column, String inValue)- 字段 IN ( sql语句 )
- 例:
inSql("age", "1,2,3,4,5,6")--->age in (1,2,3,4,5,6) - 例:
inSql("id", "select id from table where id < 3")--->id in (select id from table where id < 3)
notInSql
notInSql(R column, String inValue)
notInSql(boolean condition, R column, String inValue)- 字段 NOT IN ( sql语句 )
- 例:
notInSql("age", "1,2,3,4,5,6")--->age not in (1,2,3,4,5,6) - 例:
notInSql("id", "select id from table where id < 3")--->id not in (select id from table where id < 3)
groupBy
groupBy(R... columns)
groupBy(boolean condition, R... columns)- 分组:GROUP BY 字段, ...
- 例:
groupBy("id", "name")--->group by id,name
orderByAsc
orderByAsc(R... columns)
orderByAsc(boolean condition, R... columns)- 排序:ORDER BY 字段, ... ASC
- 例:
orderByAsc("id", "name")--->order by id ASC,name ASC
orderByDesc
orderByDesc(R... columns)
orderByDesc(boolean condition, R... columns)- 排序:ORDER BY 字段, ... DESC
- 例:
orderByDesc("id", "name")--->order by id DESC,name DESC
orderBy
orderBy(boolean condition, boolean isAsc, R... columns)- 排序:ORDER BY 字段, ...
- 例:
orderBy(true, true, "id", "name")--->order by id ASC,name ASC
having
having(String sqlHaving, Object... params)
having(boolean condition, String sqlHaving, Object... params)- HAVING ( sql语句 )
- 例:
having("sum(age) > 10")--->having sum(age) > 10 - 例:
having("sum(age) > {0}", 11)--->having sum(age) > 11
func
func(Consumer<Children> consumer)
func(boolean condition, Consumer<Children> consumer)- func 方法(主要方便在出现if...else下调用不同方法能不断链)
- 例:
func(i -> if(true) {i.eq("id", 1)} else {i.ne("id", 1)})
or
or()
or(boolean condition)- 拼接 OR
注意事项:
主动调用or表示紧接着下一个方法不是用and连接!(不调用or则默认为使用and连接)
- 例:
eq("id",1).or().eq("name","老王")--->id = 1 or name = '老王'
or(Consumer<Param> consumer)
or(boolean condition, Consumer<Param> consumer)- OR 嵌套
- 例:
or(i -> i.eq("name", "李白").ne("status", "活着"))--->or (name = '李白' and status <> '活着')
and
and(Consumer<Param> consumer)
and(boolean condition, Consumer<Param> consumer)- AND 嵌套
- 例:
and(i -> i.eq("name", "李白").ne("status", "活着"))--->and (name = '李白' and status <> '活着')
nested
nested(Consumer<Param> consumer)
nested(boolean condition, Consumer<Param> consumer)- 正常嵌套 不带 AND 或者 OR
- 例:
nested(i -> i.eq("name", "李白").ne("status", "活着"))--->(name = '李白' and status <> '活着')
apply
apply(String applySql, Object... params)
apply(boolean condition, String applySql, Object... params)- 拼接 sql
注意事项:
该方法可用于数据库函数 动态入参的params对应前面applySql内部的{index}部分.这样是不会有sql注入风险的,反之会有!
- 例:
apply("id = 1")--->id = 1 - 例:
apply("date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'") - 例:
apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
last
last(String lastSql)
last(boolean condition, String lastSql)- 无视优化规则直接拼接到 sql 的最后
注意事项:
只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用
- 例:
last("limit 1")
exists
exists(String existsSql)
exists(boolean condition, String existsSql)- 拼接 EXISTS ( sql语句 )
- 例:
exists("select id from table where age = 1")--->exists (select id from table where age = 1)
notExists
notExists(String notExistsSql)
notExists(boolean condition, String notExistsSql)- 拼接 NOT EXISTS ( sql语句 )
- 例:
notExists("select id from table where age = 1")--->not exists (select id from table where age = 1)
QueryWrapper
说明:
继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件
及 LambdaQueryWrapper, 可以通过 new QueryWrapper().lambda() 方法获取
select
select(String... sqlSelect)
select(Predicate<TableFieldInfo> predicate)
select(Class<T> entityClass, Predicate<TableFieldInfo> predicate)- 设置查询字段
说明:
以上方法分为两类.
第二类方法为:过滤查询字段(主键除外),入参不包含 class 的调用前需要wrapper内的entity属性有值! 这两类方法重复调用以最后一次为准
- 例:
select("id", "name", "age") - 例:
select(i -> i.getProperty().startsWith("test"))
UpdateWrapper
说明:
继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件
及 LambdaUpdateWrapper, 可以通过 new UpdateWrapper().lambda() 方法获取!
set
set(String column, Object val)
set(boolean condition, String column, Object val)- SQL SET 字段
- 例:
set("name", "老李头") - 例:
set("name", "")--->数据库字段值变为空字符串 - 例:
set("name", null)--->数据库字段值变为null
setSql
setSql(String sql)- 设置 SET 部分 SQL
- 例:
setSql("name = '老李头'")
lambda
- 获取
LambdaWrapper
在QueryWrapper中是获取LambdaQueryWrapper
在UpdateWrapper中是获取LambdaUpdateWrapper
使用 Wrapper 自定义SQL
注意事项:
需要mybatis-plus版本 >= 3.0.7 param 参数名要么叫ew,要么加上注解@Param(Constants.WRAPPER) 使用${ew.customSqlSegment} 不支持 Wrapper 内的entity生成where语句
用注解
@Select("select * from mysql_data ${ew.customSqlSegment}")
List<MysqlData> getAll(@Param(Constants.WRAPPER) Wrapper wrapper);用XML
List<MysqlData> getAll(Wrapper ew);
<select id="getAll" resultType="MysqlData">
SELECT * FROM mysql_data ${ew.customSqlSegment}
</select>链式调用 lambda 式
// 区分:
// 链式调用 普通
UpdateChainWrapper<T> update();
// 链式调用 lambda 式。注意:不支持 Kotlin
LambdaUpdateChainWrapper<T> lambdaUpdate();
// 等价示例:
query().eq("id", value).one();
lambdaQuery().eq(Entity::getId, value).one();
// 等价示例:
update().eq("id", value).remove();
lambdaUpdate().eq(Entity::getId, value).remove();分页插件
配置依赖
<!-- 添加MyBatis-plus依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.4.1</version>
</dependency>增加配置文件
@Configuration
public class MybatisPlusConfig {
// 最新版
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
@Bean
public ConfigurationCustomizer configurationCustomizer() {
return configuration -> configuration.setUseDeprecatedExecutor(false);
}
}编写mapper类
@Mapper
public interface UserMapper extends BaseMapper<User> {
/**
* 分页查询
*
* @param page 分页对象,xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位(你可以继承Page实现自己的分页对象)
* @return
*/
Page<User> selectUserList(IPage<User> page);
}xml编写Sql
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cc.lisen.mybatisplussample.mapper.UserMapper">
<resultMap id="BaseResultMap" type="cc.lisen.mybatisplussample.domain.User">
<!--@Table `user`-->
<id column="id" jdbcType="BIGINT" property="id"/>
<result column="name" jdbcType="VARCHAR" property="name"/>
<result column="age" jdbcType="INTEGER" property="age"/>
<result column="email" jdbcType="VARCHAR" property="email"/>
</resultMap>
<sql id="Base_Column_List">
id, `name`, age, email
</sql>
<select id="selectUserList" resultMap="BaseResultMap">
select <include refid="Base_Column_List"/> from user
</select>
</mapper>编写service类
public interface IUserService extends IService<User>{
/**
* 分页查询
*
* @param page 分页对象,xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位(你可以继承Page实现自己的分页对象)
* @return
*/
Page<User> selectUserList(IPage<User> page);
}编写impl类
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
@Resource
UserMapper userMapper;
/**
* 分页查询
*
* @param page 分页对象,xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位(你可以继承Page实现自己的分页对象)
* @return
*/
@Override
public Page<User> selectUserList(IPage<User> page) {
return userMapper.selectUserList(page);
}
}编写controller类
@RestController
@RequestMapping("user")
public class UserController {
@Resource
private IUserService userService;
@GetMapping("list")
public List<User> list(){
return userService.list();
}
@GetMapping("list1")
public List<User> list1(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id",1).or().eq("name","Tom");
return userService.list(queryWrapper);
}
@GetMapping("page")
public Page<User> page(){
IPage<User> userPage = new Page<>(1,3);
return userService.selectUserList(userPage);
}
}
能用