Mybatis-Plus基础入门
简介
MyBatis-Plus (简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
特性介绍
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作
基本使用
常用注解
@TableName(“表名”) 表名注解
@TableId(“主键字段名”) 主键注解
@TableField(“字段注解”) 字段注解(非主键)
@Version 乐观锁注解
@EnumValue 通枚举类注解(注解在枚举字段上)
@TableLogic 表字段逻辑处理注解(逻辑删除)
查询(Retrieve)
条件构造器
allEq:全部eq(或个别isNull]
allEq(Map<R, V> params)
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
eq:等于 =
eq(R column, Object val)
eq(boolean condition, R column, Object val)
ne:不等于 <>
ne(R column, Object val)
ne(boolean condition, R column, Object val)
gt:大于 >
gt(R column, Object val)
gt(boolean condition, R column, Object val)
ge: 大于等于 >=
ge(R column, Object val)
ge(boolean condition, R column, Object val)
lt: 小于 <
lt(R column, Object val)
lt(boolean condition, R column, Object val)
le:小于等于 <=
le(R column, Object val)
le(boolean condition, R column, Object val)
between:BETWEEN 值1 AND 值2
between(R column, Object val1, Object val2)
between(boolean condition, R column, Object val1, Object val2)
notBetween:NOT BETWEEN 值1 AND 值2
notBetween(R column, Object val1, Object val2)
notBetween(boolean condition, R column, Object val1, Object val2)
like:LIKE ‘%值%’
like(R column, Object val)
like(boolean condition, R column, Object val)
notLike:NOT LIKE ‘%值%’
notLike(R column, Object val)
notLike(boolean condition, R column, Object val)
isNull:字段为空
isNull(R column)
isNull(boolean condition, R column)
isNotNull:字段非空
isNotNull(R column)
isNotNull(boolean condition, R column)
lambda 条件构造器
获取 LambdaWrapper
在QueryWrapper
中是获取LambdaQueryWrapper
在UpdateWrapper
中是获取LambdaUpdateWrapper
LambdaQueryWrapper<T> lambda = new QueryWrapper<User>().lambda();
LambdaQueryWrapper<T> lambdaQueryWrapper = new LambdaQueryWrapper<T>();
LambdaQueryWrapper<T> lambdaQuery = Wrapper.<T>lambdaQuery();
自定义SQL
使用Wrapper自定义SQL,在MP3.0.7版本后实现了可自定义SQL
方案一:注解方式Mapper.java
@Select("select * from mysql_data ${ew.customSqlSegment}")
List<MysqlData> getAll(@Param(Constants.WRAPPER) Wrapper wrapper);
方案二:XML形式Mapper.xml
<select id="getAll" resultType="MysqlData">
SELECT * FROM mysql_data ${ew.customSqlSegment}
</select>
分页查询
<!-- spring xml 方式 -->
<property name="plugins">
<array>
<bean class="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor">
<property name="sqlParser" ref="自定义解析类、可以没有"/>
<property name="dialectClazz" value="自定义方言类、可以没有"/>
<!-- COUNT SQL 解析.可以没有 -->
<property name="countSqlParser" ref="countSqlParser"/>
</bean>
</array>
</property>
<bean id="countSqlParser" class="com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize">
<!-- 设置为 true 可以优化部分 left join 的sql -->
<property name="optimizeJoin" value="true"/>
</bean>
//Spring boot方式
@EnableTransactionManagement
@Configuration
@MapperScan("com.baomidou.cloud.service.*.mapper*")
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
// 开启 count 的 join 优化,只针对部分 left join
paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
return paginationInterceptor;
}
}
XML自定义分页查询
//UserMapper.java 方式查询
public interface UserMapper {//可以继承或者不继承BaseMapper
/**
* <p>
* 查询 : 根据state状态查询用户列表,分页显示
* </p>
*
* @param page 分页对象,xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位(你可以继承Page实现自己的分页对象)
* @param state 状态
* @return 分页对象
*/
IPage<User> selectPageVo(Page<?> page, Integer state);
}
<-- Usermapper.xml 等同于编写一个普通list查询,MP自动替你分页 -->
<select id="selectPageVo" resultType="com.baomidou.cloud.entity.UserVo">
SELECT id,name FROM user WHERE state=#{state}
</select>
//UserServiceImpl.java 调用分页方法
public IPage<User> selectUserPage(Page<User> page, Integer state) {
// 不进行 count sql 优化,解决 MP 无法自动优化 SQL 问题,这时候你需要自己查询 count 部分
// page.setOptimizeCountSql(false);
// 当 total 为小于 0 或者设置 setSearchCount(false) 分页插件不会进行 count 查询
// 要点!! 分页返回的对象与传入的对象是同一个
return userMapper.selectPageVo(page, state);
}
更新(Update)& 删除(Delete)
//更新
@Test
public void updateById(){
User user = new User();
user.setId(1l);
user.setAge(26);
user.setEmail("lxm@gky.com");
int rows = userMapper.updateById(user);
}
@Test
public void updateByWrapper(){
UpdateWrapper<User> updateWrapper = new UpdateWrapper<User>();
updateWrapper.eq("name","李").eq("age",28);
User user = new User();
user.setEmail("li@gky.com");
user.setAge(29);
userMapper.update(user,updateWrapper);
}
//更新少量字段时
@Test
public void updateByWrapper(){
UpdateWrapper<User> updateWrapper = new UpdateWrapper<User>();
updateWrapper.eq("name","李").eq("age",28).set("age",30);
userMapper.update(user,updateWrapper);
}
@Test
public void updateByWrapperLambda(){
LambdaUpdateWrapper<User> lambdaUpdate = Wrappers.<User>lambdaUpdate();
lambdaUpdate.eq(User::getName,"李").eq(User::getAge,29).set(User::Age,30);
}
//删除
@Test
public void deleteByMap(){
Map<String,Object> columnMap = new HashMap<>();
columnMap.put("name","李");
columnMap.put("age",32);
}
//批量删除
@Test
public void deleteBatchids(){
UserMapper userMapper = new UserMapper();
userMapper.deleteBatchids(Arrays.asList(1l,2l,3l));
}
@Test
public void deleteByWrapper(){
LambdaQuertyWrapper<User> lambdaQuery = Wrapper.<User>lLambdaQuery();
lambdaQuery.eq(User::getAge,27).or().gt(User::getAGe,40);
userMapper.delete(lambdaQuery);
}