MyBatis-Plus学习总结

  • Post author:
  • Post category:其他




什么是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常用注解



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接口,我们可以通过官方文档查看


Mapper CRUD 接口



MyBatis-Plus Mapper提供的选装件

选装件,位于 com.baomidou.mybatisplus.extension.injector.methods 包下, 需要配合Sql 注入器使用,可以进行批量更新、插入和逻辑删除


mapper 层 选装件



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方法。


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 条件。


AbstractWrapper详细说明



QueryWrapper

继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件

及 LambdaQueryWrapper, 可以通过 new QueryWrapper().lambda() 方法获取


QueryWrapper详细说明



UpdateWrapper

继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件

及 LambdaUpdateWrapper, 可以通过 new UpdateWrapper().lambda() 方法获取!


UpdateWrapper详细说明



使用 Wrapper 自定义SQL

使用 Wrapper 自定义SQL,需要mybatis-plus版本 >= 3.0.7 param 参数名要么叫ew,要么加上注解@Param(Constants.WRAPPER) 使用${ew.customSqlSegment} 不支持 Wrapper 内的entity生成where语句


使用 Wrapper 自定义SQL



MyBatis-Plus物理分页插件


物理分页插件

使用过程中要注意,paginationInterceptor类本质就是Mybatis的拦截器,不配置会导致Mybatis的分页插件不能的正常使用。



MyBatis-Plus主键配置和自定义ID生成器

MyBatis-Plus可以配置实体类对应到数据库表的主键和对应的ID生成器


主键配置


自定义ID生成器



MyBatis-Plus配置实现逻辑删除


逻辑删除



MyBatis-Plus自动填充功能


自动填充功能

这个是MyBatis-Plus中相当好用的功能,当你的数据库表中有创建人、修改人、创建时间、修改时间等不依靠输入而填充的字段时,可以再自动填充方法中配置相关字段的填充。



执行 SQL 分析打印


SQL 分析打印

可以利用SQL 分析打印来对SQL语句的性能进行分析,但是要注意这个功能也会造成性能负担,所以最好只在测试环境中使用,不要在生产环境中使用。



插件主体


插件主体(必看!)(since 3.4.0)

个人开发常用插件为分页插件和乐观锁插件



分页插件PaginationInnerInterceptor


PaginationInnerInterceptor



乐观锁插件OptimisticLockerInnerInterceptor


OptimisticLockerInnerInterceptor

通过自动配置就可以实现乐观锁,不过利用乐观锁进行的更新方法还是需要自己写。



教程推荐


MyBatis-Plus入门


MyBatis-Plus进阶

这两个教程讲的比较详细,非常推荐。



版权声明:本文为qq_43475336原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。