Ruoyi-vue-plus-5.x第二篇MyBatis-Plus数据持久层技术:2.1 MyBatis-Plus核心功能
👋 大家好,我是 阿问学长
!专注于分享优质开源项目
解析、毕业设计项目指导
支持、幼小初高
的教辅资料
推荐等,欢迎关注交流!🚀
MyBatis-Plus核心功能
前言
MyBatis-Plus(简称MP)是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。RuoYi-Vue-Plus框架深度集成了MyBatis-Plus,充分利用其强大的功能特性来构建高效的数据访问层。本文将详细介绍MyBatis-Plus的核心功能及其在RuoYi-Vue-Plus中的应用。
MyBatis-Plus简介
核心特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响
- 损耗小:启动即会自动注入基本CRUD,性能基本无损耗,直接面向对象操作
- 强大的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等多种数据库
BaseMapper通用CRUD操作
实体类定义
在RuoYi-Vue-Plus中,实体类通常继承BaseEntity并使用MyBatis-Plus注解:
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("sys_user")
public class SysUser extends BaseEntity {/*** 用户ID*/@TableId(value = "user_id", type = IdType.AUTO)private Long userId;/*** 用户账号*/@TableField("user_name")private String userName;/*** 用户昵称*/@TableField("nick_name")private String nickName;/*** 用户邮箱*/@TableField("email")private String email;/*** 手机号码*/@TableField("phonenumber")private String phonenumber;/*** 用户性别*/@TableField("sex")private String sex;/*** 用户头像*/@TableField("avatar")private String avatar;/*** 密码*/@TableField("password")private String password;/*** 帐号状态(0正常 1停用)*/@TableField("status")private String status;/*** 删除标志(0代表存在 2代表删除)*/@TableLogic@TableField("del_flag")private String delFlag;/*** 最后登录IP*/@TableField("login_ip")private String loginIp;/*** 最后登录时间*/@TableField("login_date")private Date loginDate;/*** 部门ID*/@TableField("dept_id")private Long deptId;/*** 部门对象*/@TableField(exist = false)private SysDept dept;/*** 角色对象*/@TableField(exist = false)private List<SysRole> roles;/*** 角色组*/@TableField(exist = false)private Long[] roleIds;/*** 岗位组*/@TableField(exist = false)private Long[] postIds;/*** 角色ID*/@TableField(exist = false)private Long roleId;
}
Mapper接口定义
/*** 用户表 数据层*/
@Mapper
public interface SysUserMapper extends BaseMapper<SysUser> {/*** 根据条件分页查询用户列表*/@DataPermission({@DataColumn(key = "deptName", value = "d.dept_id"),@DataColumn(key = "userName", value = "u.user_id")})Page<SysUserVo> selectPageUserList(@Param("page") Page<SysUser> page, @Param("queryWrapper") Wrapper<SysUser> queryWrapper);/*** 根据条件查询用户列表*/@DataPermission({@DataColumn(key = "deptName", value = "d.dept_id"),@DataColumn(key = "userName", value = "u.user_id")})List<SysUserVo> selectUserList(@Param("queryWrapper") Wrapper<SysUser> queryWrapper);/*** 根据用户ID查询用户*/SysUserVo selectUserById(Long userId);/*** 根据用户名查询用户*/SysUser selectUserByUserName(String userName);/*** 根据手机号查询用户*/SysUser selectUserByPhonenumber(String phonenumber);/*** 根据邮箱查询用户*/SysUser selectUserByEmail(String email);/*** 通过用户ID删除用户*/int deleteUserById(Long userId);/*** 批量删除用户信息*/int deleteUserByIds(Long[] userIds);/*** 修改用户信息*/int updateUser(SysUser user);/*** 新增用户信息*/int insertUser(SysUser user);/*** 校验用户名称是否唯一*/SysUser checkUserNameUnique(String userName);/*** 校验手机号码是否唯一*/SysUser checkPhoneUnique(String phonenumber);/*** 校验email是否唯一*/SysUser checkEmailUnique(String email);
}
BaseMapper基础CRUD操作
MyBatis-Plus的BaseMapper提供了丰富的CRUD方法:
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {@Autowiredprivate SysUserMapper userMapper;/*** 插入操作示例*/public boolean insertUser(SysUser user) {// 方式1:使用BaseMapper的insert方法int result = userMapper.insert(user);// 方式2:使用Service层的save方法// boolean result = this.save(user);return result > 0;}/*** 删除操作示例*/public boolean deleteUser(Long userId) {// 方式1:根据ID删除int result = userMapper.deleteById(userId);// 方式2:根据条件删除// LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();// wrapper.eq(SysUser::getUserId, userId);// int result = userMapper.delete(wrapper);// 方式3:使用Service层的removeById方法// boolean result = this.removeById(userId);return result > 0;}/*** 批量删除操作示例*/public boolean deleteUsers(List<Long> userIds) {// 方式1:使用BaseMapper的deleteBatchIds方法int result = userMapper.deleteBatchIds(userIds);// 方式2:使用Service层的removeByIds方法// boolean result = this.removeByIds(userIds);return result > 0;}/*** 更新操作示例*/public boolean updateUser(SysUser user) {// 方式1:根据ID更新(null字段不更新)int result = userMapper.updateById(user);// 方式2:根据条件更新// LambdaUpdateWrapper<SysUser> wrapper = new LambdaUpdateWrapper<>();// wrapper.eq(SysUser::getUserId, user.getUserId());// wrapper.set(SysUser::getStatus, user.getStatus());// int result = userMapper.update(null, wrapper);// 方式3:使用Service层的updateById方法// boolean result = this.updateById(user);return result > 0;}/*** 查询操作示例*/public SysUser selectUserById(Long userId) {// 方式1:根据ID查询return userMapper.selectById(userId);// 方式2:使用Service层的getById方法// return this.getById(userId);}/*** 条件查询示例*/public List<SysUser> selectUserList(SysUser user) {// 使用QueryWrapper进行条件查询LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();// 用户名模糊查询wrapper.like(StringUtils.isNotBlank(user.getUserName()), SysUser::getUserName, user.getUserName());// 状态精确查询wrapper.eq(StringUtils.isNotBlank(user.getStatus()), SysUser::getStatus, user.getStatus());// 部门ID查询wrapper.eq(ObjectUtil.isNotNull(user.getDeptId()), SysUser::getDeptId, user.getDeptId());// 创建时间范围查询wrapper.between(ObjectUtil.isNotNull(user.getParams().get("beginTime")) && ObjectUtil.isNotNull(user.getParams().get("endTime")),SysUser::getCreateTime, user.getParams().get("beginTime"), user.getParams().get("endTime"));// 排序wrapper.orderByDesc(SysUser::getCreateTime);return userMapper.selectList(wrapper);}/*** 分页查询示例*/public Page<SysUser> selectUserPage(Page<SysUser> page, SysUser user) {LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();// 构建查询条件wrapper.like(StringUtils.isNotBlank(user.getUserName()), SysUser::getUserName, user.getUserName());wrapper.eq(StringUtils.isNotBlank(user.getStatus()), SysUser::getStatus, user.getStatus());// 执行分页查询return userMapper.selectPage(page, wrapper);}/*** 统计查询示例*/public Long countUsers(SysUser user) {LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();// 构建查询条件wrapper.eq(StringUtils.isNotBlank(user.getStatus()), SysUser::getStatus, user.getStatus());wrapper.eq(ObjectUtil.isNotNull(user.getDeptId()), SysUser::getDeptId, user.getDeptId());return userMapper.selectCount(wrapper);}/*** 存在性检查示例*/public boolean existsUser(String userName) {LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();wrapper.eq(SysUser::getUserName, userName);// 方式1:使用count > 0判断return userMapper.selectCount(wrapper) > 0;// 方式2:使用exists方法(需要自定义)// return userMapper.exists(wrapper);}
}
IService服务层封装
Service接口定义
/*** 用户 业务层*/
public interface ISysUserService extends IService<SysUser> {/*** 根据条件分页查询用户列表*/TableDataInfo<SysUserVo> selectPageUserList(SysUserBo user, PageQuery pageQuery);/*** 根据条件查询用户列表*/List<SysUserVo> selectUserList(SysUserBo user);/*** 根据用户ID查询用户信息*/SysUserVo selectUserById(Long userId);/*** 根据用户名查询用户*/SysUser selectUserByUserName(String userName);/*** 校验用户名称是否唯一*/boolean checkUserNameUnique(SysUserBo user);/*** 校验手机号码是否唯一*/boolean checkPhoneUnique(SysUserBo user);/*** 校验email是否唯一*/boolean checkEmailUnique(SysUserBo user);/*** 校验用户是否允许操作*/void checkUserAllowed(Long userId);/*** 校验用户是否有数据权限*/void checkUserDataScope(Long userId);/*** 新增用户信息*/Boolean insertUser(SysUserBo user);/*** 注册用户信息*/Boolean registerUser(SysUserBo user, String tenantId);/*** 修改用户信息*/Boolean updateUser(SysUserBo user);/*** 用户授权角色*/void insertUserAuth(Long userId, Long[] roleIds);/*** 修改用户状态*/Boolean updateUserStatus(Long userId, String status);/*** 修改用户基本信息*/Boolean updateUserProfile(SysUserBo user);/*** 修改用户头像*/Boolean updateUserAvatar(Long userId, Long ossId);/*** 重置用户密码*/Boolean resetUserPwd(Long userId, String password);/*** 通过用户ID删除用户*/Boolean deleteUserById(Long userId);/*** 批量删除用户信息*/Boolean deleteUserByIds(Long[] userIds);
}
Service实现类
@RequiredArgsConstructor
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {private final SysUserMapper baseMapper;private final SysRoleMapper roleMapper;private final SysPostMapper postMapper;private final SysUserRoleMapper userRoleMapper;private final SysUserPostMapper userPostMapper;/*** 分页查询用户列表*/@Overridepublic TableDataInfo<SysUserVo> selectPageUserList(SysUserBo user, PageQuery pageQuery) {LambdaQueryWrapper<SysUser> lqw = buildQueryWrapper(user);Page<SysUserVo> result = baseMapper.selectPageUserList(pageQuery.build(), lqw);return TableDataInfo.build(result);}/*** 查询用户列表*/@Overridepublic List<SysUserVo> selectUserList(SysUserBo user) {LambdaQueryWrapper<SysUser> lqw = buildQueryWrapper(user);return baseMapper.selectUserList(lqw);}/*** 构建查询条件*/private LambdaQueryWrapper<SysUser> buildQueryWrapper(SysUserBo user) {Map<String, Object> params = user.getParams();LambdaQueryWrapper<SysUser> lqw = Wrappers.lambdaQuery();lqw.like(StringUtils.isNotBlank(user.getUserName()), SysUser::getUserName, user.getUserName());lqw.eq(StringUtils.isNotBlank(user.getStatus()), SysUser::getStatus, user.getStatus());lqw.like(StringUtils.isNotBlank(user.getPhonenumber()), SysUser::getPhonenumber, user.getPhonenumber());lqw.between(params.get("beginTime") != null && params.get("endTime") != null,SysUser::getCreateTime, params.get("beginTime"), params.get("endTime"));lqw.eq(ObjectUtil.isNotNull(user.getDeptId()), SysUser::getDeptId, user.getDeptId());lqw.orderByAsc(SysUser::getUserId);return lqw;}/*** 新增用户信息*/@Override@Transactional(rollbackFor = Exception.class)public Boolean insertUser(SysUserBo user) {SysUser sysUser = BeanUtil.toBean(user, SysUser.class);// 新增用户信息int rows = baseMapper.insert(sysUser);user.setUserId(sysUser.getUserId());// 新增用户岗位关联insertUserPost(user);// 新增用户与角色管理insertUserRole(user);return rows > 0;}/*** 修改用户信息*/@Override@Transactional(rollbackFor = Exception.class)public Boolean updateUser(SysUserBo user) {Long userId = user.getUserId();// 删除用户与角色关联userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));// 新增用户与角色管理insertUserRole(user);// 删除用户与岗位关联userPostMapper.delete(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getUserId, userId));// 新增用户与岗位管理insertUserPost(user);SysUser sysUser = BeanUtil.toBean(user, SysUser.class);return baseMapper.updateById(sysUser) > 0;}/*** 新增用户角色信息*/private void insertUserRole(SysUserBo user) {this.insertUserRole(user.getUserId(), user.getRoleIds());}/*** 新增用户角色信息*/private void insertUserRole(Long userId, Long[] roleIds) {if (ArrayUtil.isNotEmpty(roleIds)) {// 新增用户与角色管理List<SysUserRole> list = StreamUtils.toList(List.of(roleIds), roleId -> {SysUserRole ur = new SysUserRole();ur.setUserId(userId);ur.setRoleId(roleId);return ur;});userRoleMapper.insertBatch(list);}}/*** 新增用户岗位信息*/private void insertUserPost(SysUserBo user) {Long[] posts = user.getPostIds();if (ArrayUtil.isNotEmpty(posts)) {// 新增用户与岗位管理List<SysUserPost> list = StreamUtils.toList(List.of(posts), postId -> {SysUserPost up = new SysUserPost();up.setUserId(user.getUserId());up.setPostId(postId);return up;});userPostMapper.insertBatch(list);}}/*** 批量删除用户信息*/@Override@Transactional(rollbackFor = Exception.class)public Boolean deleteUserByIds(Long[] userIds) {for (Long userId : userIds) {checkUserAllowed(userId);checkUserDataScope(userId);}List<Long> ids = List.of(userIds);// 删除用户与角色关联userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getUserId, ids));// 删除用户与岗位表userPostMapper.delete(new LambdaQueryWrapper<SysUserPost>().in(SysUserPost::getUserId, ids));return baseMapper.deleteBatchIds(ids) > 0;}
}
条件构造器QueryWrapper使用
基础条件构造
@Service
public class UserQueryService {@Autowiredprivate SysUserMapper userMapper;/*** 基础条件查询*/public List<SysUser> basicQuery() {QueryWrapper<SysUser> wrapper = new QueryWrapper<>();// 等于wrapper.eq("status", "0");// 不等于wrapper.ne("del_flag", "2");// 大于wrapper.gt("user_id", 1);// 大于等于wrapper.ge("create_time", "2023-01-01");// 小于wrapper.lt("user_id", 1000);// 小于等于wrapper.le("create_time", "2023-12-31");// 模糊查询wrapper.like("user_name", "admin");// 左模糊查询wrapper.likeLeft("user_name", "admin");// 右模糊查询wrapper.likeRight("user_name", "admin");// 不包含wrapper.notLike("user_name", "test");// 包含wrapper.in("user_id", Arrays.asList(1, 2, 3));// 不包含wrapper.notIn("user_id", Arrays.asList(4, 5, 6));// 为空wrapper.isNull("email");// 不为空wrapper.isNotNull("phonenumber");// 分组wrapper.groupBy("dept_id");// 排序wrapper.orderByAsc("user_id");wrapper.orderByDesc("create_time");return userMapper.selectList(wrapper);}/*** 复杂条件查询*/public List<SysUser> complexQuery(String userName, String status, Long deptId, Date beginTime, Date endTime) {QueryWrapper<SysUser> wrapper = new QueryWrapper<>();// 动态条件wrapper.like(StringUtils.isNotBlank(userName), "user_name", userName);wrapper.eq(StringUtils.isNotBlank(status), "status", status);wrapper.eq(ObjectUtil.isNotNull(deptId), "dept_id", deptId);wrapper.between(ObjectUtil.isNotNull(beginTime) && ObjectUtil.isNotNull(endTime), "create_time", beginTime, endTime);// 嵌套条件 (status = '0' OR status = '1') AND dept_id = 1wrapper.and(w -> w.eq("status", "0").or().eq("status", "1"));wrapper.eq("dept_id", 1);// 子查询wrapper.inSql("dept_id", "select dept_id from sys_dept where status = '0'");return userMapper.selectList(wrapper);}/*** 自定义SQL查询*/public List<SysUser> customSqlQuery() {QueryWrapper<SysUser> wrapper = new QueryWrapper<>();// 自定义SQL片段wrapper.apply("date_format(create_time,'%Y-%m-%d') = '2023-01-01'");// 带参数的自定义SQLwrapper.apply("date_format(create_time,'%Y-%m-%d') = {0}", "2023-01-01");return userMapper.selectList(wrapper);}
}
LambdaQueryWrapper类型安全查询
Lambda表达式查询
@Service
public class UserLambdaQueryService {@Autowiredprivate SysUserMapper userMapper;/*** Lambda基础查询*/public List<SysUser> lambdaBasicQuery() {LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();// 类型安全的字段引用wrapper.eq(SysUser::getStatus, "0");wrapper.ne(SysUser::getDelFlag, "2");wrapper.like(SysUser::getUserName, "admin");wrapper.isNotNull(SysUser::getEmail);wrapper.orderByDesc(SysUser::getCreateTime);return userMapper.selectList(wrapper);}/*** Lambda动态查询*/public List<SysUser> lambdaDynamicQuery(SysUserBo user) {LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();// 动态条件构建wrapper.like(StringUtils.isNotBlank(user.getUserName()), SysUser::getUserName, user.getUserName());wrapper.like(StringUtils.isNotBlank(user.getNickName()), SysUser::getNickName, user.getNickName());wrapper.eq(StringUtils.isNotBlank(user.getStatus()), SysUser::getStatus, user.getStatus());wrapper.eq(StringUtils.isNotBlank(user.getPhonenumber()), SysUser::getPhonenumber, user.getPhonenumber());wrapper.eq(ObjectUtil.isNotNull(user.getDeptId()), SysUser::getDeptId, user.getDeptId());// 时间范围查询Map<String, Object> params = user.getParams();wrapper.between(params.get("beginTime") != null && params.get("endTime") != null,SysUser::getCreateTime, params.get("beginTime"), params.get("endTime"));// 排序wrapper.orderByAsc(SysUser::getUserId);return userMapper.selectList(wrapper);}/*** Lambda复杂查询*/public List<SysUser> lambdaComplexQuery() {LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();// 嵌套条件wrapper.and(w -> w.eq(SysUser::getStatus, "0").or().eq(SysUser::getStatus, "1"));// 函数查询wrapper.apply("date_format(create_time,'%Y-%m-%d') = {0}", "2023-01-01");// 子查询wrapper.inSql(SysUser::getDeptId, "select dept_id from sys_dept where status = '0'");// 存在子查询wrapper.exists("select 1 from sys_user_role ur where ur.user_id = sys_user.user_id");return userMapper.selectList(wrapper);}/*** Lambda更新操作*/public boolean lambdaUpdate(Long userId, String status) {LambdaUpdateWrapper<SysUser> wrapper = new LambdaUpdateWrapper<>();// 设置更新字段wrapper.set(SysUser::getStatus, status);wrapper.set(SysUser::getUpdateTime, new Date());// 更新条件wrapper.eq(SysUser::getUserId, userId);return userMapper.update(null, wrapper) > 0;}/*** Lambda删除操作*/public boolean lambdaDelete(String status) {LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();wrapper.eq(SysUser::getStatus, status);return userMapper.delete(wrapper) > 0;}
}
链式调用优化
@Service
public class UserChainQueryService {@Autowiredprivate SysUserMapper userMapper;/*** 链式查询*/public List<SysUser> chainQuery(SysUserBo user) {return new LambdaQueryChainWrapper<>(userMapper).like(StringUtils.isNotBlank(user.getUserName()), SysUser::getUserName, user.getUserName()).eq(StringUtils.isNotBlank(user.getStatus()), SysUser::getStatus, user.getStatus()).eq(ObjectUtil.isNotNull(user.getDeptId()), SysUser::getDeptId, user.getDeptId()).orderByDesc(SysUser::getCreateTime).list();}/*** 链式更新*/public boolean chainUpdate(Long userId, String status) {return new LambdaUpdateChainWrapper<>(userMapper).set(SysUser::getStatus, status).set(SysUser::getUpdateTime, new Date()).eq(SysUser::getUserId, userId).update();}/*** 链式删除*/public boolean chainDelete(String status) {return new LambdaQueryChainWrapper<>(userMapper).eq(SysUser::getStatus, status).remove();}
}
总结
本文详细介绍了MyBatis-Plus的核心功能,包括:
- BaseMapper通用CRUD:提供了丰富的基础数据操作方法
- IService服务层封装:更高层次的业务操作接口
- QueryWrapper条件构造器:灵活的查询条件构建
- LambdaQueryWrapper:类型安全的Lambda表达式查询
- 链式调用:更简洁的代码编写方式
MyBatis-Plus的这些核心功能大大简化了数据访问层的开发工作,提高了开发效率和代码质量。在下一篇文章中,我们将深入探讨MyBatis-Plus的分页与性能优化。
参考资料
- MyBatis-Plus官方文档
- MyBatis-Plus核心功能
- RuoYi-Vue-Plus数据访问层源码