MyBatis-Plus学习总结
-
什么是MyBatis-Plus?
-
MyBatis-Plus的优点有哪些?
-
快速开始(在SpringBoot中使用MP)
-
MyBatis-Plus常用注解
-
MyBatis-Plus查询方法范例
-
MyBatis-Plus Mapper提供的CRUD方法详解
-
MyBatis-Plus Mapper提供的选装件
-
MyBatis-Plus的AR模式
-
MyBatis-Plus 的Service CRUD 接口
-
MyBatis-Plus 的条件构造器
-
MyBatis-Plus物理分页插件
-
MyBatis-Plus主键配置和自定义ID生成器
-
MyBatis-Plus配置实现逻辑删除
-
MyBatis-Plus自动填充功能
-
执行 SQL 分析打印
-
插件主体
-
教程推荐
什么是MyBatis-Plus?
-
List item
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
MyBatis-Plus的优点有哪些?
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作
快速开始(在SpringBoot中使用MP)
1、新建SpringBoot项目,配置好数据库连接
2、引入Mybatis Plus依赖(注意不需要再引入Mybatis依赖了)
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
3、在数据库管理工具中创建数据库表
4、在项目中创建与数据库表对应的实体类
@Data
@TableName("user")
public class UserDO implements Serializable {
/**
* serialVersionUID
*/
private static final long serialVersionUID = 926397353672171598L;
/*** 用户主信息 ***/
/**
* 用户名
*/
private String username;
/**
* 用户密码
*/
private String password;
/**
* 邮箱
*/
private String email;
/**
* 年龄
*/
private Integer age;
/**
* 手机号
*/
private String phone;
/*** 系统主信息 ***/
/**
* 数据库主键
*/
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/**
* 数据的创建时间
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime created;
/**
* 数据修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime modified;
/**
* 创建者
*/
@TableField(fill = FieldFill.INSERT)
private String creator;
/**
* 最后修改者
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private String operator;
/**
* 逻辑删除字段:0:正常,1:逻辑删除
*/
@TableField(fill = FieldFill.INSERT)
private Integer status;
/**
* 版本号
*/
@Version
@TableField(fill = FieldFill.INSERT)
private Long version;
}
3、创建Mapper包
4、创建Mapper文件,并且继承BaseMapper
@Mapper
public interface UserInfoMapper extends BaseMapper<UserDO> {
// 这里可以自定义一些方法
}
5、在SpringBootApplication当中加上MapperSacn(“Mapper包路径”)
例如:
@SpringBootApplication
@MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")//这里是Mapper文件存放的包路径
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
6、直接在Service当中注入Mapper,然后直接调用BaseMapper提供的功能
@Autowired
private UserInfoMapper userInfoMapper;
BaseMapper中提供了大量默认实现的CRUD方法,可以直接使用,下面是Mybatis Plus中的BaseMapper的源码
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.Constants;
import org.apache.ibatis.annotations.Param;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
* Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
* <p>这个 Mapper 支持 id 泛型</p>
*
* @author hubin
* @since 2016-01-23
*/
public interface BaseMapper<T> extends Mapper<T> {
/**
* 插入一条记录
*
* @param entity 实体对象
*/
int insert(T entity);
/**
* 根据 ID 删除
*
* @param id 主键ID
*/
int deleteById(Serializable id);
/**
* 根据 columnMap 条件,删除记录
*
* @param columnMap 表字段 map 对象
*/
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
/**
* 根据 entity 条件,删除记录
*
* @param wrapper 实体对象封装操作类(可以为 null)
*/
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
/**
* 删除(根据ID 批量删除)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> 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 条件,查询一条记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询总记录数
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
Integer 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 条件,查询全部记录
* <p>注意: 只返回第一个字段的值</p>
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
<E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件
* @param queryWrapper 实体对象封装操作类
*/
<E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
}
接下来,可以使用被这个BaseMapper增强过后的自己所定义的Mapper。
MyBatis-Plus常用注解
这里可以参考官方文档和源码
MyBatis-Plus查询方法范例
以下是 MyBatis-Plus查询方法的各种范例,分别应对不同的需求使用不同的查询方法
@Test
public void contextLoads() {
}
@Autowired
private UserInfoMapper userInfoMapper;
/**
* 普通查询
*/
@Test
public void selectById() {
UserInfo userInfo = userInfoMapper.selectById(123);
System.out.println(userInfo);
}
/**
* 批量查询
*/
@Test
public void selectByIds() {
List<Long> ids = Arrays.asList(123L,124L,125L);
List<UserInfo> userInfo = userInfoMapper.selectBatchIds(ids);
System.out.println(userInfo);
}
/**
* 名字包含娟并且年龄小雨30
*/
@Test
public void selectByWrapper() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.like("username","娟").lt("age",30);
List<UserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* 名字包含娟并且年龄大雨等于20且小于等于40并且email不为空
*/
@Test
public void selectByWrapper2() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.like("username","娟").between("age",20,30).isNotNull("email");
List<UserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* 名字姓肖或者年量大雨等于20,按照年龄降序排列,年龄相同按照id生序排列
*/
@Test
public void selectByWrapper3() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.likeRight("username","肖")
.or().ge("age",20).orderByDesc("age").orderByAsc("id");
List<UserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* 创建日期为2019年10月2日并且直属上级名字为王姓
*/
@Test
public void selectByWrapper4() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.apply("date_format(create_time,'%Y-%m-%d')={0}","2019-10-07")
.inSql("parent_id","select id from user where username like '王%'");
List<UserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* 名字为王姓并且(年龄小于40或邮箱不为空)
*/
@Test
public void selectByWrapper5() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.likeRight("username","王")
.and(wq->wq.lt("age",40))
.or().isNotNull("email");
List<UserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* 名字为王姓并且(年龄小于40并且大与20或邮箱不为空)
*/
@Test
public void selectByWrapper6() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.likeRight("username","王")
.and(wq->wq.lt("age",40).gt("age",20))
.or().isNotNull("email");
List<UserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* (年龄小于40并且大与20或邮箱不为空)名字为王姓并且
*/
@Test
public void selectByWrapper7() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.nested(wq->wq.lt("age",40))
.or().isNotNull("email")
.likeRight("username","王");
List<UserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* 年龄23,30,40
*/
@Test
public void selectByWrapper8() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.in("age",Arrays.asList(20,30,40));
List<UserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* 只返回满足条件的其中一条语句即可
*/
@Test
public void selectByWrapper9() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.in("age",Arrays.asList(20,30,40)).last("limit 1");
List<UserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* 名字中包含雨并且年龄小于40(只取id,username)
*/
@Test
public void selectByWrapper10() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.select("id","username").like("username","雨").lt("age",40);
List<UserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* 名字中包含雨并且年龄小于40(不取create_time,parent_id两个字段,即不列出全部字段)
*/
@Test
public void selectByWrapper11() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.like("username","雨").lt("age",40)
.select(UserInfo.class,info->!info.getColumn().equals("create_time")&&
!info.getColumn().equals("parent_id"));
List<UserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* 姓名和邮箱不为空
*/
public void testCondition() {
String username = "王";
String email = "";
condition(username,email);
}
private void condition(String username,String email){
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.like(StringUtils.isNullOrEmpty(username),"name",username)
.like(StringUtils.isNullOrEmpty(email),"email",email);
List<UserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* 实体作为条件构造器方法的参数
*/
@Test
public void selectByWrapperEntity() {
UserInfo whereUser = new UserInfo();
whereUser.setUsername("xiaojuan");
whereUser.setAge(22);
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>(whereUser);
List<UserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* AllEq用法
*/
@Test
public void selectByWrapperAllEq() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
Map<String, Object> params = new HashMap<String, Object>();
params.put("nuserame","xiaojuan");
params.put("age",null);
queryWrapper.allEq(params);
List<UserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* AllEq用法(排除不是条件的字段)
*/
@Test
public void selectByWrapperAllEq2() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
Map<String, Object> params = new HashMap<String, Object>();
params.put("nuserame","xiaojuan");
params.put("age",null);
queryWrapper.allEq((k,v)->!k.equals("name"),params);
List<UserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* selectMaps
*/
@Test
public void selectByWrapperMaps() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.like("name","肖").lt("age",40);
List<Map<String,Object>> userInfoList = userInfoMapper.selectMaps(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* 按照直属上级分组,查询每组的平均年龄,最大年龄,最小年龄。并且只取年龄总和小于500的组
*/
@Test
public void selectByWrapperMaps2() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.select("avg(age) avg_age","min(min) min_age","max(age) max_age")
.groupBy("parent_id").having("sum(age)<{0}",500);
List<Map<String,Object>> userInfoList = userInfoMapper.selectMaps(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* selectObjs
*/
@Test
public void selectByWrapperObjs() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.select("id","name").like("name","肖").lt("age",40);
List<Object> userInfoList = userInfoMapper.selectObjs(queryWrapper);
userInfoList.forEach(System.out::println);
}
/**
* selectCount
*/
@Test
public void selectByWrapperCount() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.like("name","肖").lt("age",40);
Integer count = userInfoMapper.selectCount(queryWrapper);
System.out.println(count);
}
/**
* selectOne
*/
@Test
public void selectByWrapperSelectOne() {
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.like("name","肖").lt("age",40);
UserInfo user = userInfoMapper.selectOne(queryWrapper);
System.out.println(user);
}
/**
* 使用Lambda
*/
@Test
public void selectLambda() {
// LambdaQueryWrapper<UserInfo> lambda = new QueryWrapper<UserInfo>().lambda();
LambdaQueryWrapper<UserInfo> lambda = new LambdaQueryWrapper<UserInfo>();
lambda.like(UserInfo::getUsername,"娟").lt(UserInfo::getAge,40);
List<UserInfo> userInfoList = userInfoMapper.selectList(lambda);
userInfoList.forEach(System.out::println);
}
/**
* 使用Lambda,名字为王姓(年龄小于40或邮箱不为空)
*/
@Test
public void selectLambd2() {
LambdaQueryWrapper<UserInfo> lambda = new LambdaQueryWrapper<UserInfo>();
lambda.like(UserInfo::getUsername,"娟")
.and(lqw->lqw.lt(UserInfo::getAge,40).or().isNotNull(UserInfo::getEmail));
List<UserInfo> userInfoList = userInfoMapper.selectList(lambda);
userInfoList.forEach(System.out::println);
}
/**
* 使用Lambda链式
*/
@Test
public void selectLambd3() {
List<UserInfo> userInfoList = new LambdaQueryChainWrapper<UserInfo>(userInfoMapper)
.like(UserInfo::getUsername,"娟").ge(UserInfo::getAge,20).list();
userInfoList.forEach(System.out::println);
}
以上范例转载至
Mybatis Plus 查询方法记录
MyBatis-Plus Mapper提供的CRUD方法详解
Mybatis-Plus框架的BaseMapper给我们提供了常用的CRUD接口,我们可以通过官方文档查看
MyBatis-Plus Mapper提供的选装件
选装件,位于 com.baomidou.mybatisplus.extension.injector.methods 包下, 需要配合Sql 注入器使用,可以进行批量更新、插入和逻辑删除
MyBatis-Plus的AR模式
AR,又叫做ActiveRecord,AR模式是一种领域模型模式,特点是一个模型类对应关系型数据库中的 一个表,而模型类的一个实例对应表中的一行记录。
AR模式 一直广受动态语言( PHP 、 Ruby 等)的喜爱,而 Java 本身却不提供这种模式的实现,不过MyBatis-Plus在AR模式上做出了一定的实现。
MyBatis-Plus的AR模式使用
首先,自定义实体类,然后将该实体类继承MyBatis-Plus的Model
@Data
public class User extends Model<User> {
/*** 用户主信息 ***/
/**
* 用户名
*/
private String username;
/**
* 用户密码
*/
private String password;
/**
* 邮箱
*/
private String email;
/**
* 年龄
*/
private Integer age;
/**
* 手机号
*/
private String phone;
/*** 系统主信息 ***/
/**
* 数据库主键
*/
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/**
* 数据的创建时间
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime created;
/**
* 数据修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime modified;
/**
* 创建者
*/
@TableField(fill = FieldFill.INSERT)
private String creator;
/**
* 最后修改者
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private String operator;
/**
* 逻辑删除字段:0:正常,1:逻辑删除
*/
@TableField(fill = FieldFill.INSERT)
private Integer status;
/**
* 版本号
*/
@Version
@TableField(fill = FieldFill.INSERT)
private Long version;
}
接下来,创建Mapper
public interface UserMapper extends BaseMapper<UserDO> {}
虽然AR模式用不到该接口,但是一定要定义,否则使用AR时会报空指针异常。
接下来使用就好了
@Test
public void testArInsert(){
UserDO user = new UserDO();
user.setUsername("张文远");
user.setAge(22);
boolean result = user.insert();
System.out.println(result);
}
借助于Model提供的方法,可以直接执行增删改查等操作,例如上面的user.insert
我们可以通过Model的源码查看其提供的功能
/**
* ActiveRecord 模式 CRUD
* 必须存在对应的原始mapper并继承baseMapper并且可以使用的前提下
* 才能使用此 AR 模式 !!!
*/
public abstract class Model<T extends Model<?>> implements Serializable {
private static final long serialVersionUID = 1L;
private transient Log log = LogFactory.getLog(getClass());
/**
* 插入(字段选择插入)
*/
public boolean insert() {
SqlSession sqlSession = sqlSession();
try {
return SqlHelper.retBool(sqlSession.insert(sqlStatement(SqlMethod.INSERT_ONE), this));
} finally {
closeSqlSession(sqlSession);
}
}
/**
* 插入 OR 更新
*/
public boolean insertOrUpdate() {
return StringUtils.checkValNull(pkVal()) || Objects.isNull(selectById(pkVal())) ? insert() : updateById();
}
/**
* 根据 ID 删除
*
* @param id 主键ID
*/
public boolean deleteById(Serializable id) {
SqlSession sqlSession = sqlSession();
try {
return SqlHelper.retBool(sqlSession.delete(sqlStatement(SqlMethod.DELETE_BY_ID), id));
} finally {
closeSqlSession(sqlSession);
}
}
/**
* 根据主键删除
*/
public boolean deleteById() {
Assert.isFalse(StringUtils.checkValNull(pkVal()), "deleteById primaryKey is null.");
return deleteById(pkVal());
}
/**
* 删除记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
public boolean delete(Wrapper<T> queryWrapper) {
Map<String, Object> map = new HashMap<>(1);
map.put(Constants.WRAPPER, queryWrapper);
SqlSession sqlSession = sqlSession();
try {
return SqlHelper.retBool(sqlSession.delete(sqlStatement(SqlMethod.DELETE), map));
} finally {
closeSqlSession(sqlSession);
}
}
/**
* 更新(字段选择更新)
*/
public boolean updateById() {
Assert.isFalse(StringUtils.checkValNull(pkVal()), "updateById primaryKey is null.");
// updateById
Map<String, Object> map = new HashMap<>(1);
map.put(Constants.ENTITY, this);
SqlSession sqlSession = sqlSession();
try {
return SqlHelper.retBool(sqlSession.update(sqlStatement(SqlMethod.UPDATE_BY_ID), map));
} finally {
closeSqlSession(sqlSession);
}
}
/**
* 执行 SQL 更新
*
* @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
*/
public boolean update(Wrapper<T> updateWrapper) {
Map<String, Object> map = new HashMap<>(2);
map.put(Constants.ENTITY, this);
map.put(Constants.WRAPPER, updateWrapper);
// update
SqlSession sqlSession = sqlSession();
try {
return SqlHelper.retBool(sqlSession.update(sqlStatement(SqlMethod.UPDATE), map));
} finally {
closeSqlSession(sqlSession);
}
}
/**
* 查询所有
*/
public List<T> selectAll() {
SqlSession sqlSession = sqlSession();
try {
return sqlSession.selectList(sqlStatement(SqlMethod.SELECT_LIST));
} finally {
closeSqlSession(sqlSession);
}
}
/**
* 根据 ID 查询
*
* @param id 主键ID
*/
public T selectById(Serializable id) {
SqlSession sqlSession = sqlSession();
try {
return sqlSession.selectOne(sqlStatement(SqlMethod.SELECT_BY_ID), id);
} finally {
closeSqlSession(sqlSession);
}
}
/**
* 根据主键查询
*/
public T selectById() {
Assert.isFalse(StringUtils.checkValNull(pkVal()), "selectById primaryKey is null.");
return selectById(pkVal());
}
/**
* 查询总记录数
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
public List<T> selectList(Wrapper<T> queryWrapper) {
Map<String, Object> map = new HashMap<>(1);
map.put(Constants.WRAPPER, queryWrapper);
SqlSession sqlSession = sqlSession();
try {
return sqlSession.selectList(sqlStatement(SqlMethod.SELECT_LIST), map);
} finally {
closeSqlSession(sqlSession);
}
}
/**
* 查询一条记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
public T selectOne(Wrapper<T> queryWrapper) {
return SqlHelper.getObject(log, selectList(queryWrapper));
}
/**
* 翻页查询
*
* @param page 翻页查询条件
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
public <E extends IPage<T>> E selectPage(E page, Wrapper<T> queryWrapper) {
Map<String, Object> map = new HashMap<>(2);
map.put(Constants.WRAPPER, queryWrapper);
map.put("page", page);
SqlSession sqlSession = sqlSession();
try {
page.setRecords(sqlSession.selectList(sqlStatement(SqlMethod.SELECT_PAGE), map));
} finally {
closeSqlSession(sqlSession);
}
return page;
}
/**
* 查询总数
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
public Integer selectCount(Wrapper<T> queryWrapper) {
Map<String, Object> map = new HashMap<>(1);
map.put(Constants.WRAPPER, queryWrapper);
SqlSession sqlSession = sqlSession();
try {
return SqlHelper.retCount(sqlSession.<Integer>selectOne(sqlStatement(SqlMethod.SELECT_COUNT), map));
} finally {
closeSqlSession(sqlSession);
}
}
/**
* 执行 SQL
*/
public SqlRunner sql() {
return new SqlRunner(getClass());
}
/**
* 获取Session 默认自动提交
*/
protected SqlSession sqlSession() {
return SqlHelper.sqlSession(getClass());
}
/**
* 获取SqlStatement
*
* @param sqlMethod sqlMethod
*/
protected String sqlStatement(SqlMethod sqlMethod) {
return sqlStatement(sqlMethod.getMethod());
}
/**
* 获取SqlStatement
*
* @param sqlMethod sqlMethod
*/
protected String sqlStatement(String sqlMethod) {
return SqlHelper.table(getClass()).getSqlStatement(sqlMethod);
}
/**
* 主键值
*/
protected Serializable pkVal() {
return (Serializable) ReflectionKit.getMethodValue(this, TableInfoHelper.getTableInfo(getClass()).getKeyProperty());
}
/**
* 释放sqlSession
*
* @param sqlSession session
*/
protected void closeSqlSession(SqlSession sqlSession) {
SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(getClass()));
}
}
MyBatis-Plus 的Service CRUD 接口
MyBatis-Plus提供了BaseMapper,可以让我们自定义Mapper并继承,从而使用增强版本的Mapper。
既然Mapper大多都要在Service中使用,那么可不可以一步到位直接增强Service呢?
MyBatis-Plus为此提供了IService接口,继承该接口之后可以直接使用IService生成的CRUD方法。
MyBatis-Plus 的条件构造器
Mybatis-Plus提供了强大的条件构造器,提供了很多sql语法支持的方法,比如模糊查询,比较,区间,分组查询,排序,判断空,子查询等等,方便我们用面向对象的方式去实现sql语句。
我们主要使用的MyBatis-Plus 的条件构造器主要包括QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper)。
AbstractWrapper
AbstractWrapper是QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类,用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件。
QueryWrapper
继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件
及 LambdaQueryWrapper, 可以通过 new QueryWrapper().lambda() 方法获取
UpdateWrapper
继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件
及 LambdaUpdateWrapper, 可以通过 new UpdateWrapper().lambda() 方法获取!
使用 Wrapper 自定义SQL
使用 Wrapper 自定义SQL,需要mybatis-plus版本 >= 3.0.7 param 参数名要么叫ew,要么加上注解@Param(Constants.WRAPPER) 使用${ew.customSqlSegment} 不支持 Wrapper 内的entity生成where语句
MyBatis-Plus物理分页插件
使用过程中要注意,paginationInterceptor类本质就是Mybatis的拦截器,不配置会导致Mybatis的分页插件不能的正常使用。
MyBatis-Plus主键配置和自定义ID生成器
MyBatis-Plus可以配置实体类对应到数据库表的主键和对应的ID生成器
MyBatis-Plus配置实现逻辑删除
MyBatis-Plus自动填充功能
这个是MyBatis-Plus中相当好用的功能,当你的数据库表中有创建人、修改人、创建时间、修改时间等不依靠输入而填充的字段时,可以再自动填充方法中配置相关字段的填充。
执行 SQL 分析打印
可以利用SQL 分析打印来对SQL语句的性能进行分析,但是要注意这个功能也会造成性能负担,所以最好只在测试环境中使用,不要在生产环境中使用。
插件主体
个人开发常用插件为分页插件和乐观锁插件
分页插件PaginationInnerInterceptor
乐观锁插件OptimisticLockerInnerInterceptor
OptimisticLockerInnerInterceptor
通过自动配置就可以实现乐观锁,不过利用乐观锁进行的更新方法还是需要自己写。
教程推荐
这两个教程讲的比较详细,非常推荐。