目录
前言
快速入门
简介
特性
框架结构
代码托管
快速开始
初始化工程
添加依赖
配置
编码
开始使用
小结
安装
Release
Snapshot
配置
核心功能
代码生成器
添加依赖
切换模板引擎
自定义模板引擎
CRUD 接口
Mapper CRUD 接口
Service CRUD 接口
updateBatchById
条件构造器
AbstractWrapper
groupBy
last
QueryWrapper
UpdateWrapper
使用 Wrapper 自定义SQL
分页插件
XML 自定义分页
Sequence主键
如何使用Sequence作为主键,但是实体主键类型是String
最近在学习了MyBatis Plus,认真详细查看了官方文档,确实写得非常清楚,就不专门去写MyBatis Plus入门基础博文,直接将官网知识贴在博客里面。个人非常推荐查看这篇文章
当然,除了这篇文章之后,个人也会总结一些MP启动注入原理分析、AQ支持、几个插件底层原理分析等文章。有兴趣可以看一下哦
这一篇当做是文档+基础哦
版本在3.0+,2.3版本跟这个有小小区别哦!
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
愿景
我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。
Gitee | Github
我们将通过一个简单的 Demo 来阐述 MyBatis-Plus 的强大功能,在此之前,我们假设您已经:
现有一张 User
表,其表结构如下:
id | name | age | |
---|---|---|---|
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] |
其对应的数据库 Schema 脚本如下:
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)
);
其对应的数据库 Data 脚本如下:
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]');
Question
如果从零开始用 MyBatis-Plus 来实现该表的增删改查我们需要做什么呢?
创建一个空的 Spring Boot 工程(工程将以 H2 作为默认数据库进行演示)
TIP
可以使用 Spring Initializr 快速初始化一个 Spring Boot 工程
引入 Spring Boot Starter 父工程:
org.springframework.boot
spring-boot-starter-parent
2.0.3.RELEASE
引入 spring-boot-starter
、spring-boot-starter-test
、mybatis-plus-boot-starter
、lombok
、h2
依赖:
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
org.projectlombok
lombok
true
com.baomidou
mybatis-plus-boot-starter
3.0.6
com.h2database
h2
runtime
在 application.yml
配置文件中添加 H2 数据库的相关配置:
# DataSource Config
spring:
datasource:
driver-class-name: org.h2.Driver
schema: classpath:db/schema-h2.sql
data: classpath:db/data-h2.sql
url: jdbc:h2:mem:test
username: root
password: test
在 Spring Boot 启动类中添加 @MapperScan
注解,扫描 Mapper 文件夹:
@SpringBootApplication
@MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(QuickStartApplication.class, args);
}
}
编写实体类 User.java
(此处使用了 Lombok 简化代码)
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
编写Mapper类 UserMapper.java
public interface UserMapper extends BaseMapper {
}
添加测试类,进行功能测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class SampleTest {
@Autowired
private UserMapper userMapper;
@Test
public void testSelect() {
System.out.println(("----- selectAll method test ------"));
List userList = userMapper.selectList(null);
Assert.assertEquals(5, userList.size());
userList.forEach(System.out::println);
}
}
TIP
UserMapper 中的
selectList()
方法的参数为 MP 内置的条件封装器Wrapper
,所以不填写就是无任何条件
控制台输出:
User(id=1, name=Jone, age=18, [email protected])
User(id=2, name=Jack, age=20, [email protected])
User(id=3, name=Tom, age=28, [email protected])
User(id=4, name=Sandy, age=21, [email protected])
User(id=5, name=Billie, age=24, [email protected])
TIP
完整的代码示例请移步:Spring Boot 快速启动示例 | Spring MVC 快速启动示例
通过以上几个简单的步骤,我们就实现了 User 表的 CRUD 功能,甚至连 XML 文件都不用编写!
从以上步骤中,我们可以看到集成MyBatis-Plus
非常的简单,只需要引入 starter 工程,并配置 mapper 扫描路径即可。
但 MyBatis-Plus 的强大远不止这些功能,想要详细了解 MyBatis-Plus 的强大功能?那就继续往下看吧!
全新的 MyBatis-Plus
3.0 版本基于 JDK8,提供了 lambda
形式的调用,所以安装集成 MP3.0 要求如下:
TIP
JDK7 以及下的请参考 MP2.0 版本,地址:2.0 文档
Spring Boot
Maven:
com.baomidou
mybatis-plus-boot-starter
3.0.6
Gradle:
compile group: 'com.baomidou', name: 'mybatis-plus-boot-starter', version: '3.0.6'
Spring MVC
Maven:
com.baomidou
mybatis-plus
3.0.6
Gradle:
compile group: 'com.baomidou', name: 'mybatis-plus', version: '3.0.6'
WARNING
引入
MyBatis-Plus
之后请不要再次引入MyBatis
以及MyBatis-Spring
,以避免因版本差异导致的问题。
快照 SNAPSHOT 版本需要添加仓库,且版本号为快照版本。
Maven:
snapshots
https://oss.sonatype.org/content/repositories/snapshots/
Gradle:
repositories {
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}
MyBatis-Plus 的配置异常的简单,我们仅需要一些简单的配置即可使用 MyBatis-Plus 的强大功能!
TIP
在讲解配置之前,请确保您已经安装了 MyBatis-Plus,如果您尚未安装,请查看 安装 一章。
Spring Boot 工程:
配置 MapperScan 注解
@SpringBootApplication
@MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(QuickStartApplication.class, args);
}
}
Spring MVC 工程:
配置 MapperScan
调整 SqlSessionFactory 为 MyBatis-Plus 的 SqlSessionFactory
通常来说,一般的简单工程,通过以上配置即可正常使用 MyBatis-Plus,具体可参考以下项目:Spring Boot 快速启动示例、Spring MVC 快速启动示例。
同时 MyBatis-Plus 提供了大量的个性化配置来满足不同复杂度的工程,大家可根据自己的项目按需取用,详细配置请参考配置一文
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
// 演示例子,执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
public class CodeGenerator {
/**
*
* 读取控制台内容
*
*/
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("请输入" + tip + ":");
System.out.println(help.toString());
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotEmpty(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
public static void main(String[] args) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("jobob");
gc.setOpen(false);
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/ant?useUnicode=true&useSSL=false&characterEncoding=utf8");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("密码");
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName(scanner("模块名"));
pc.setParent("com.baomidou.ant");
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
// 如果模板引擎是 freemarker
String templatePath = "/templates/mapper.xml.ftl";
// 如果模板引擎是 velocity
// String templatePath = "/templates/mapper.xml.vm";
// 自定义输出配置
List focList = new ArrayList<>();
// 自定义配置会被优先输出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输出文件名
return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
// 配置自定义输出模板
// templateConfig.setEntity();
// templateConfig.setService();
// templateConfig.setController();
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setSuperEntityClass("com.baomidou.ant.common.BaseEntity");
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true);
strategy.setSuperControllerClass("com.baomidou.ant.common.BaseController");
strategy.setInclude(scanner("表名"));
strategy.setSuperEntityColumns("id");
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(pc.getModuleName() + "_");
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}
更多详细配置,请参考代码生成器配置一文。
MP 3.0.3
之后移除了自动模板引擎依赖,需要手动添加对应引擎的依赖坐标如下:
org.apache.velocity
velocity-engine-core
最新版本
org.freemarker
freemarker
最新版本
// 切换为 freemarker 模板引擎
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
请继承类 com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine
说明:
- 通用 CRUD 封装BaseMapper接口,为
Mybatis-Plus
启动时自动解析实体表关系映射转换为Mybatis
内部对象注入容器- 泛型
T
为任意实体对象- 参数
Serializable
为任意类型主键Mybatis-Plus
不推荐使用复合主键约定每一张表都有自己的唯一id
主键- 对象
Wrapper
为 条件构造器
insert
/**
*
* 插入一条记录
*
*
* @param entity 实体对象
* @return 插入成功记录数
*/
int insert(T entity);
deleteById
/**
*
* 根据 ID 删除
*
*
* @param id 主键ID
* @return 删除成功记录数
*/
int deleteById(Serializable id);
deleteByMap
/**
*
* 根据 columnMap 条件,删除记录
*
*
* @param columnMap 表字段 map 对象
* @return 删除成功记录数
*/
int deleteByMap(@Param(Constants.COLUMN_MAP) Map columnMap);
delete
/**
*
* 根据 entity 条件,删除记录
*
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
* @return 删除成功记录数
*/
int delete(@Param(Constants.WRAPPER) Wrapper queryWrapper);
deleteBatchIds
/**
*
* 删除(根据ID 批量删除)
*
*
* @param idList 主键ID列表(不能为 null 以及 empty)
* @return 删除成功记录数
*/
int deleteBatchIds(@Param(Constants.COLLECTION) Collection extends Serializable> idList);
updateById
/**
*
* 根据 ID 修改
*
*
* @param entity 实体对象
* @return 修改成功记录数
*/
int updateById(@Param(Constants.ENTITY) T entity);
update
/**
*
* 根据 whereEntity 条件,更新记录
*
*
* @param entity 实体对象 (set 条件值,不能为 null)
* @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
* @return 修改成功记录数
*/
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper updateWrapper);
selectById
/**
*
* 根据 ID 查询
*
*
* @param id 主键ID
* @return 实体
*/
T selectById(Serializable id);
selectBatchIds
/**
*
* 查询(根据ID 批量查询)
*
*
* @param idList 主键ID列表(不能为 null 以及 empty)
* @return 实体集合
*/
List selectBatchIds(@Param(Constants.COLLECTION) Collection extends Serializable> idList);
selectByMap
/**
*
* 查询(根据 columnMap 条件)
*
*
* @param columnMap 表字段 map 对象
* @return 实体集合
*/
List selectByMap(@Param(Constants.COLUMN_MAP) Map columnMap);
selectOne
/**
*
* 根据 entity 条件,查询一条记录
*
*
* @param queryWrapper 实体对象
* @return 实体
*/
T selectOne(@Param(Constants.WRAPPER) Wrapper queryWrapper);
selectCount
/**
*
* 根据 Wrapper 条件,查询总记录数
*
*
* @param queryWrapper 实体对象
* @return 满足条件记录数
*/
Integer selectCount(@Param(Constants.WRAPPER) Wrapper queryWrapper);
selectList
/**
*
* 根据 entity 条件,查询全部记录
*
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
* @return 实体集合
*/
List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper);
selectMaps
/**
*
* 根据 Wrapper 条件,查询全部记录
*
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
* @return 字段映射对象 Map 集合
*/
List
selectObjs
/**
*
* 根据 Wrapper 条件,查询全部记录
* 注意: 只返回第一个字段的值
*
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
* @return 字段映射对象集合
*/
List
selectPage
/**
*
* 根据 entity 条件,查询全部记录(并翻页)
*
*
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
* @param queryWrapper 实体对象封装操作类(可以为 null)
* @return 实体分页对象
*/
IPage selectPage(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper);
selectMapsPage
/**
*
* 根据 Wrapper 条件,查询全部记录(并翻页)
*
*
* @param page 分页查询条件
* @param queryWrapper 实体对象封装操作类
* @return 字段映射对象 Map 分页对象
*/
IPage
说明:
- 通用 Service CRUD 封装IService接口,进一步封装 CRUD 采用
get 查询单行
remove 删除
list 查询集合
page 分页
前缀命名方式区分Mapper
层避免混淆,- 泛型
T
为任意实体对象- 建议如果存在自定义通用 Service 方法的可能,请创建自己的
IBaseService
继承Mybatis-Plus
提供的基类- 对象
Wrapper
为 条件构造器
save
/**
*
* 插入一条记录(选择字段,策略插入)
*
*
* @param entity 实体对象
*/
boolean save(T entity);
saveBatch
/**
*
* 插入一条记录(选择字段,策略插入)
*
*
* @param entity 实体对象
*/
boolean save(T entity);
saveOrUpdateBatch
/**
*
* 批量修改插入
*
*
* @param entityList 实体对象集合
*/
boolean saveOrUpdateBatch(Collection entityList);
saveOrUpdateBatch
/**
*
* 批量修改插入
*
*
* @param entityList 实体对象集合
* @param batchSize 每次的数量
*/
boolean saveOrUpdateBatch(Collection entityList, int batchSize);
removeById
/**
*
* 根据 ID 删除
*
*
* @param id 主键ID
*/
boolean removeById(Serializable id);
removeByMap
/**
*
* 根据 columnMap 条件,删除记录
*
*
* @param columnMap 表字段 map 对象
*/
boolean removeByMap(Map columnMap);
remove
/**
*
* 根据 entity 条件,删除记录
*
*
* @param queryWrapper 实体包装类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
boolean remove(Wrapper queryWrapper);
removeByIds
/**
*
* 删除(根据ID 批量删除)
*
*
* @param idList 主键ID列表
*/
boolean removeByIds(Collection extends Serializable> idList);
updateById
/**
*
* 根据 ID 选择修改
*
*
* @param entity 实体对象
*/
boolean updateById(T entity);
update
/**
*
* 根据 whereEntity 条件,更新记录
*
*
* @param entity 实体对象
* @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
*/
boolean update(T entity, Wrapper updateWrapper);
/**
*
* 根据ID 批量更新
*
*
* @param entityList 实体对象集合
* @param batchSize 更新批次数量
*/
boolean updateBatchById(Collection entityList, int batchSize);
saveOrUpdate
/**
*
* TableId 注解存在更新记录,否插入一条记录
*
*
* @param entity 实体对象
*/
boolean saveOrUpdate(T entity);
getById
/**
*
* 根据 ID 查询
*
*
* @param id 主键ID
*/
T getById(Serializable id);
listByIds
/**
*
* 查询(根据ID 批量查询)
*
*
* @param idList 主键ID列表
*/
Collection listByIds(Collection extends Serializable> idList);
listByMap
/**
*
* 查询(根据 columnMap 条件)
*
*
* @param columnMap 表字段 map 对象
*/
Collection listByMap(Map columnMap);
getOne
/**
*
* 根据 Wrapper,查询一条记录
*
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
* @param throwEx 有多个 result 是否抛出异常
*/
T getOne(Wrapper queryWrapper, boolean throwEx);
getMap
/**
*
* 根据 Wrapper,查询一条记录
*
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
Map getMap(Wrapper queryWrapper);
getObj
/**
*
* 根据 Wrapper,查询一条记录
*
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
Object getObj(Wrapper queryWrapper);
count
/**
*
* 根据 Wrapper 条件,查询总记录数
*
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
int count(Wrapper queryWrapper);
list
/**
*
* 查询列表
*
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
List list(Wrapper queryWrapper);
page
/**
*
* 翻页查询
*
*
* @param page 翻页对象
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
IPage page(IPage page, Wrapper queryWrapper);
listMaps
/**
*
* 查询列表
*
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
List
listObjs
/**
*
* 根据 Wrapper 条件,查询全部记录
*
*
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
List
pageMaps
/**
*
* 翻页查询
*
*
* @param page 翻页对象
* @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
*/
IPage
说明:
- 以下出现的第一个入参
boolean condition
表示该条件是否加入最后生成的sql中- 以下代码块内的多个方法均为从上往下补全个别
boolean
类型的入参,默认为true
- 以下出现的泛型
This
均为具体使用的Wrapper
的实例- 以下方法在入参中出现的
R
为泛型,在普通wrapper中是String
,在LambdaWrapper中是函数(例:Entity::getId
,Entity
为实体类,getId
为字段id
的getMethod)- 以下方法入参中的
R column
均表示数据库字段,当R
为String
时则为数据库字段名(字段名是数据库关键字的自己用转义符包裹!)!而不是实体类数据字段名!!!- 以下举例均为使用普通wrapper,入参为
Map
和List
的均以json
形式表现!- 使用中如果入参的
Map
或者List
为空,则不会加入最后生成的sql中!!!- 有任何疑问就点开源码看,看不懂函数的点击我学习新知识
说明:
QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类
用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件
注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为
allEq
allEq(Map params)
allEq(Map params, boolean null2IsNull)
allEq(boolean condition, Map params, boolean null2IsNull)
个别参数说明:
params
:key
为数据库字段名,value
为字段值null2IsNull
: 为true
则在map
的value
为null
时调用 isNull 方法,为false
时则忽略value
为null
的
allEq({id:1,name:"老王",age:null})
--->id = 1 and name = '老王' and age is null
allEq({id:1,name:"老王",age:null}, false)
--->id = 1 and name = '老王'
allEq(BiPredicate filter, Map params)
allEq(BiPredicate filter, Map params, boolean null2IsNull)
allEq(boolean condition, BiPredicate filter, Map params, boolean null2IsNull)
个别参数说明:
filter
: 过滤函数,是否允许字段传入比对条件中params
与null2IsNull
: 同上
allEq((k,v) -> k.indexOf("a") > 0, {id:1,name:"老王",age:null})
--->name = '老王' and age is null
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("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)
notBetween("age", 18, 30)
--->age not between 18 and 30
like
like(R column, Object val)
like(boolean condition, R column, Object val)
like("name", "王")
--->name like '%王%'
notLike
notLike(R column, Object val)
notLike(boolean condition, R column, Object val)
notLike("name", "王")
--->name not like '%王%'
likeLeft
likeLeft(R column, Object val)
likeLeft(boolean condition, R column, Object val)
likeLeft("name", "王")
--->name like '%王'
likeRight
likeRight(R column, Object val)
likeRight(boolean condition, R column, Object val)
likeRight("name", "王")
--->name like '王%'
isNull
isNull(R column)
isNull(boolean condition, R column)
isNull("name")
--->name is null
isNotNull
isNotNull(R column)
isNotNull(boolean condition, R column)
isNotNull("name")
--->name is not null
in
in(R column, Collection> value)
in(boolean condition, R column, Collection> value)
in("age",{1,2,3})
--->age in (1,2,3)
in(R column, Object... values)
in(boolean condition, R column, Object... values)
in("age", 1, 2, 3)
--->age in (1,2,3)
notIn
notIn(R column, Collection> value)
notIn(boolean condition, R column, Collection> value)
notIn("age",{1,2,3})
--->age not in (1,2,3)
notIn(R column, Object... values)
notIn(boolean condition, R column, Object... values)
notIn("age", 1, 2, 3)
--->age not in (1,2,3)
inSql
inSql(R column, String inValue)
inSql(boolean condition, R column, String inValue)
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)
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")
--->age not in (select id from table where id < 3)
groupBy(R... columns)
groupBy(boolean condition, R... columns)
groupBy("id", "name")
--->group by id,name
orderByAsc
orderByAsc(R... columns)
orderByAsc(boolean condition, R... columns)
orderByAsc("id", "name")
--->order by id ASC,name ASC
orderByDesc
orderByDesc(R... columns)
orderByDesc(boolean condition, R... columns)
orderByDesc("id", "name")
--->order by id DESC,name DESC
orderBy
orderBy(boolean condition, boolean isAsc, R... columns)
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("sum(age) > 10")
--->having sum(age) > 10
having("sum(age) > {0}", 11)
--->having sum(age) > 11
or
or()
or(boolean condition)
注意事项:
主动调用
or
表示紧接着下一个方法不是用and
连接!(不调用or
则默认为使用and
连接)
eq("id",1).or().eq("name","老王")
--->id = 1 or name = '老王'
or(Function func)
or(boolean condition, Function func)
or(i -> i.eq("name", "李白").ne("status", "活着"))
--->or (name = '李白' and status <> '活着')
and
and(Function func)
and(boolean condition, Function func)
and(i -> i.eq("name", "李白").ne("status", "活着"))
--->and (name = '李白' and status <> '活着')
apply
apply(String sqlHaving, Object... params)
apply(boolean condition, String sqlHaving, Object... params)
注意事项:
该方法可用于数据库函数 动态入参的
params
对应前面sqlHaving
内部的{index}
部分.这样是不会有sql注入风险的,反之会有!
apply("id = 1")
--->having sum(age) > 10
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(String lastSql)
last(boolean condition, String lastSql)
注意事项:
只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用
last("limit 1")
exists
exists(String existsSql)
exists(boolean condition, String existsSql)
exists("select id from table where age = 1")
--->exists (select id from table where age = 1)
notExists
notExists(String existsSql)
notExists(boolean condition, String existsSql)
notExists("select id from table where age = 1")
--->not exists (select id from table where age = 1)
nested
nested(Function func)
nested(boolean condition, Function func)
nested(i -> i.eq("name", "李白").ne("status", "活着"))
--->(name = '李白' and status <> '活着')
说明:
继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件
及 LambdaQueryWrapper, 可以通过 new QueryWrapper().lambda() 方法获取
select
select(String... sqlSelect)
select(Predicate predicate)
select(Class entityClass, Predicate predicate)
说明:
以上方分法为两类.
第二类方法为:过滤查询字段(主键除外),入参不包含 class 的调用前需要wrapper
内的entity
属性有值! 这两类方法重复调用以最后一次为准
select("id", "name", "age")
select(i -> i.getProperty().startsWith("test"))
excludeColumns @Deprecated
WARNING
已从3.0.5
版本上移除此方法!
说明:
继承自
AbstractWrapper
,自身的内部属性entity
也用于生成 where 条件
及LambdaUpdateWrapper
, 可以通过new UpdateWrapper().lambda()
方法获取!
set
set(String column, Object val)
set(boolean condition, String column, Object val)
set("name", "老李头")
set("name", "")
--->数据库字段值变为空字符串set("name", null)
--->数据库字段值变为null
setSql
setSql(String sql)
set("name = '老李头')
lambda
LambdaWrapper
QueryWrapper
中是获取LambdaQueryWrapper
UpdateWrapper
中是获取LambdaUpdateWrapper
需求来源:
在使用了
mybatis-plus
之后, 自定义SQL的同时也想使用Wrapper
的便利应该怎么办? 在mybatis-plus
版本3.0.7
得到了完美解决 版本需要大于或等于3.0.7
, 以下两种方案取其一即可
Service.java
mysqlMapper.getAll(Wrappers.lambdaQuery().eq(MysqlData::getGroup, 1));
方案一 注解方式 Mapper.java
@Select("select * from mysql_data ${ew.customSqlSegment}")
List getAll(@Param(Constants.WRAPPER) Wrapper wrapper);
方案二 XML形式 Mapper.xml
示例工程:
? mybatis-plus-sample-pagination
//Spring boot方式
@EnableTransactionManagement
@Configuration
@MapperScan("com.baomidou.cloud.service.*.mapper*")
public class MybatisPlusConfig {
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
public interface UserMapper{//可以继承或者不继承BaseMapper
/**
*
* 查询 : 根据state状态查询用户列表,分页显示
* 注意!!: 如果入参是有多个,需要加注解指定参数名才能在xml中取值
*
*
* @param page 分页对象,xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位(你可以继承Page实现自己的分页对象)
* @param state 状态
* @return 分页对象
*/
IPage selectPageVo(Page page, @Param("state") Integer state);
}
public IPage selectUserPage(Page page, Integer state) {
// 不进行 count sql 优化,解决 MP 无法自动优化 SQL 问题,这时候你需要自己查询 count 部分
// page.setOptimizeCountSql(false);
// 当 total 为非 0 时(默认为 0),分页插件不会进行 count 查询
// 要点!! 分页返回的对象与传入的对象是同一个
return userMapper.selectPageVo(page, state));
}
实体主键支持Sequence
GlobalConfiguration gc = new GlobalConfiguration();
gc.setKeyGenerator(new OracleKeyGenerator());
@Bean
public OracleKeyGenerator oracleKeyGenerator(){
return new OracleKeyGenerator();
}
@TableName("TEST_SEQUSER")
@KeySequence("SEQ_TEST")//类注解
public class TestSequser{
@TableId(value = "ID", type = IdType.INPUT)
private Long id;
}
@KeySequence("SEQ_TEST")
public abstract class Parent{
}
public class Child extends Parent{
}
以上步骤就可以使用Sequence当主键了。
Spring MVC:xml配置,请参考【安装集成】
也就是说,表的主键是varchar2, 但是需要从sequence中取值
@KeySequence(value = "SEQ_ORACLE_STRING_KEY", clazz = String.class)
public class YourEntity{
@TableId(value = "ID_STR", type = IdType.INPUT)
private String idStr;
...
}
@Bean
public GlobalConfiguration globalConfiguration() {
GlobalConfiguration conf = new GlobalConfiguration();
conf.setKeyGenerator(new OracleKeyGenerator());
return conf;
}
关于MybatisPlus插件,详细见下一篇。
https://blog.csdn.net/xiaozhegaa/article/details/85042299