Mybatis Plus的简单学习与使用

Mybatis Plus

create by xuyihui

学习网址:https://baomidou.com/guide/annotation.html#tablename

1.特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑

  • 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

2.执行流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UproRKZy-1615354567382)(C:\Users\xyh\Desktop\资源\images\MP执行流程.jpg)]

3.实际使用

  • 创建数据库
--  用户表
create table user
(
    id     character not null primary key,
    name   varchar(11),
    remark varchar(200)
) engine = Innodb
  charset = utf8;

--  部门表
create table dept
(
    id     character not null primary key,
    name   varchar(11),
    remark varchar(200)
) engine = Innodb
  charset = utf8;
--  用户部门联系表
create table user_dept
(
    s_id varchar(100),
    d_id varchar(100),
    constraint user_dept_pk primary key (s_id,d_id) ,
    constraint student_dept_student_id_fk
        foreign key (s_id) references user (id) on delete cascade
) engine = Innodb
  charset = utf8;
  • springboot的pom依赖
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.16</version>
        </dependency>
        <!--MP插件-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.2.0</version>
        </dependency>
        <!--Mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>
        <!-- 连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.1</version>
        </dependency>
        <!--JUNIT-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
    </dependencies>
  • 配置文件
#datasource  MySQL8使用
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver

#打印sql语句
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  • User实体类
@Data
public class User {
    @TableId(type = IdType.UUID)
    private String id;

    private String name;

    private String remark;

}
  • Dept实体类
@Data
public class Dept {
    @TableId(type = IdType.UUID)
    private String id;

    private String name;

    private String remark;

}
  • UserDept实体类
@Data
public class UserDept {
    private String sId;
    private String dId;
}
  • 对应的mapper文件
public interface DeptMapper extends BaseMapper<Dept> {}

public interface UserDeptMapper extends BaseMapper<UserDept> {}

public interface UserMapper extends BaseMapper<User> {}
  • 测试文件
@SpringBootTest
@RunWith(SpringRunner.class)
class DemoApplicationTests {

    @Autowired(required = false)
    private UserMapper userMapper;

@Test
    public void testUserInsert() {
        System.out.println(("----- insert method test ------"));
        User user = new User();
        user.setName("Kitty");
        user.setRemark("嘿嘿");
        userMapper.insert(user);
    }
}

结果:

==>  Preparing: INSERT INTO user ( id, name, remark ) VALUES ( ?, ?, ? ) 
==> Parameters: 67766f508d3f5247878a4b2885a3e2a8(String), Kitty(String), 嘿嘿(String)
<==    Updates: 1

可以看出成功了。

4.CRUD 基本操作

  1. insert
 @Test
    public void testUserInsert() {
        System.out.println(("----- insert method test ------"));
        User user = new User();
        user.setName("Nancy%");
        user.setRemark("哈哈哈哈");
        int insertFlag = userMapper.insert(user);
        log.info("插入影响行数,{} | Kitty的ID: {}", insertFlag, user.getId());
    }

结果

插入影响行数,1 | Kitty的ID: 267049e5935679b7f9a73640da535cd0

可以看到我们不仅插入了数据,而且还获取到了插入数据的IDMP 默认的 ID生成策略IdType type() default IdType.NONE; ,我们使用的是@TableId(type = IdType.UUID) 这个注解。下面分析IdType里面的几种情况:

public enum IdType {
    //主键自增
    AUTO(0),
    //未设置主键类型
    NONE(1),
    //用户输入 ID
    INPUT(2),
    //全局唯一ID(idworker)
    ID_WORKER(3),
    //全剧唯一ID(UUID)
    UUID(4),
    //字符串全局唯一ID(id_worker_str)
    ID_WORKER_STR(5);

    private final int key;

    private IdType(int key) {
        this.key = key;
    }

    public int getKey() {
        return this.key;
    }
}
  • 再看一个**@TableField** 的使用,它主要作用在其他非主键类型的属性上,里面包含的注解
String value() default "";

    boolean exist() default true;

    String condition() default "";

    String update() default "";

    FieldStrategy insertStrategy() default FieldStrategy.DEFAULT;

    FieldStrategy updateStrategy() default FieldStrategy.DEFAULT;

    FieldStrategy whereStrategy() default FieldStrategy.DEFAULT;

    FieldFill fill() default FieldFill.DEFAULT;

    boolean select() default true;

    boolean keepGlobalFormat() default false;

    JdbcType jdbcType() default JdbcType.UNDEFINED;

    Class<? extends TypeHandler> typeHandler() default UnknownTypeHandler.class;

    String numericScale() default "";
  • value 解决字段名不一致问题和驼峰命名 实体类remark ,但是表中用的describe 就可以使用@TableField(value="describe") 转换。
  • exist 用于在数据表中不存在的字段,我们可以使用 @TableField(exist = false) 来进行标记
  • condition 当我们讲一个对象传入的是一个条件结构器Wrapper 的时候,我们在属性上面加上 @TableField(condition = SqlCondition.LIKE) 这个配置时,就可以按照这个形式进行SQL查询select 表 where name LIKE CONCAT('%',值,'%')SqlCondition 里面的常量有一下五种:
public static final String EQUAL = "%s=#{%s}";
public static final String NOT_EQUAL = "%s&lt;&gt;#{%s}";
public static final String LIKE = "%s LIKE CONCAT('%%',#{%s},'%%')";
public static final String LIKE_LEFT = "%s LIKE CONCAT('%%',#{%s})";
public static final String LIKE_RIGHT = "%s LIKE CONCAT(#{%s},'%%')";

具体案例如下:

//  不加此注解的情况:
//    @TableField(condition = SqlCondition.LIKE)
    private String name;

 @Test
    public void testSelect() {
        System.out.println(("----- selectAll method test ------"));
        //参数是一个Wrapper,条件结构器,这里先不用 填null
        //查询所有的用户
        User user = new User();
        user.setName("a");
        QueryWrapper<User> queryWrapper = new QueryWrapper<User>(user);
        List<User> userList = userMapper.selectList(queryWrapper);
        userList.forEach(System.out::println);
    }

//  得出的结果是:
//  Preparing: SELECT id,name,remark FROM user WHERE name=? 
//  ==> Parameters: a(String)
//  <==      Total: 0

//  加此注解的情况:
//  放开后的结果为:
//  Parameters: a(String)
//  <==    Columns: id, name, remark
//  <==        Row: 767eec62651a1a62e422b70962d08350, Nancy%, 哈哈哈哈
//  <==      Total: 1
  • update

用在预处理 set 字段自定义注入,比如我配置了 @TableField(update = "%s+1"),其中 %s 会填充字段,输出 SQL 为:update 表名 set 字段 = 字段+1 where 条件

  • select

用于是否查询时约束,如果我们有个字段 remarktext 类型的,查询的时候不想查询该字段,那么就可以使用 @TableField(select = false) 来约束查询的时候不查询该字段

  1. update

MybatisPlus 的更新操作存在两种:

int updateById(Param("et") T entity);

int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);
  • 根据ID更新
 @Test
    public void testUserUpdateById() {
        User user = new User();
        user.setId("767eec62651a1a62e422b70962d08350");
        user.setName("Alice");
        userMapper.updateById(user);
    }

//  显示结果为:User(id=767eec62651a1a62e422b70962d08350, name=Alice, remark=哈哈哈哈)
  • 根据条件更新
@Test
    public void testUserUpdateByWrapper() {
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id","767eec62651a1a62e422b70962d08350").set("name","Helen");
        userMapper.update(null,updateWrapper);
    }
    
//  显示结果为:User(id=767eec62651a1a62e422b70962d08350, name=Helen, remark=哈哈哈哈)
  • 将更新条件放入User对象
@Test
    public void testUserUpdateByWrapper1() {
        User user = new User();
        user.setRemark("管理人员");
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id","767eec62651a1a62e422b70962d08350");
        userMapper.update(user,updateWrapper);
    }
    
//  查询结果为: User(id=767eec62651a1a62e422b70962d08350, name=Helen, remark=管理人员)
  1. delete

MybatisPlus 中删除的方式相对于更新多,总共有四种:

int deleteById(Serializable id);

int deleteByMap(@Param("cm") Map<String, Object> columnMap);

int delete(@Param("ew") Wrapper<T> wrapper);

int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);
  • deleteById
@Test
    public void testUserDeleteById() {
        System.out.println(("----- delete method test ------"));
        userMapper.deleteById("767eec62651a1a62e422b70962d08350");
    }

//  sql语句: DELETE FROM user WHERE id=? 
  • deleteByMap
@Test
    public void testUserDeleteByMap() {
        HashMap<String, Object> columnMap = new HashMap<>();
        columnMap.put("name","Kitty");
        userMapper.deleteByMap(columnMap);
    }

//  sql语句:  DELETE FROM user WHERE name = ? 
  • deleteByWrapper
@Test
public void deleteByWrapper () {
    UpdateWrapper<User> wrapper = new UpdateWrapper<>();
    wrapper.eq("remark","嘿嘿");
    userMapper.delete(wrapper);
}
//  SQL语句:DELETE FROM user WHERE (remark = ?) 

根据 Wrapper 删除还有另外一种方式,直接将实体类放入 Wrapper 中包装:

@Test
    public void deleteByWrapper2 () {
        User user = new User();
        user.setRemark("嘿嘿");
        UpdateWrapper<User> wrapper = new UpdateWrapper<>(user);
        userMapper.delete(wrapper);
    }
//SQL语句:  DELETE FROM user WHERE remark=? 
  • deleteBatchIds
@Test
    public void deleteBatchIds() {
        List<String> idList = new ArrayList<>();
        idList.add("315c8465b19edef74d330bc9007462e9");
        idList.add("e829558de87cf9573d043b971a00d68e");
        userMapper.deleteBatchIds(idList);
    }
/** SQL语句:
DELETE FROM user WHERE id IN ( ? , ? ) 
==> Parameters: 315c8465b19edef74d330bc9007462e9(String), e829558de87cf9573d043b971a00d68e(String)
<==    Updates: 2
**/
  1. select

查询操作在我们开发中是最经常用到的,也是重中之重。MybatisPlus 中支持查询的方法也比较多,如下:

T selectById(Serializable id);

List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);

List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);

T selectOne(@Param("ew") Wrapper<T> queryWrapper);

Integer selectCount(@Param("ew") Wrapper<T> queryWrapper);

List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);

List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);

List<Object> selectObjs(@aram("ew") Wrapper<T> queryWrapper);

IPage<T> selectPage(IPage<T> page, @Param("ew") Wrapper<T> queryWrapper);

IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param("ew") Wrapper<T> queryWrappe
  • selectList
@Test
    public void testSelectList() {
        List<User> userList = userMapper.selectList(null);
        userList.forEach(System.out::println);
    }

/**
结果为:
User(id=71de68cd14b1e09bf0983d16343a9273, name=Helen, remark=eeee)
User(id=f5e6ff394703a960d9169936d027d808, name=Kitty, remark=hhhh)
*/
  • selectBatchIds
@Test
    public void testSelectBatchIds() {
        List<String> idList = new ArrayList<>();
        idList.add("71de68cd14b1e09bf0983d16343a9273");
        idList.add("f5e6ff394703a960d9169936d027d808");
        List<User> userList = userMapper.selectBatchIds(idList);
        userList.forEach(System.out::println);
    }

/**
结果为:
User(id=71de68cd14b1e09bf0983d16343a9273, name=Helen, remark=eeee)
User(id=f5e6ff394703a960d9169936d027d808, name=Kitty, remark=hhhh)
*/
  • selectByMap
@Test
    public void testSelectByMap() {
        Map<String,Object> columnMap = new HashMap<>();
        columnMap.put("name","Helen");
        List<User> userList = userMapper.selectByMap(columnMap);
        userList.forEach(System.out::println);
    }

/**
结果为:
User(id=71de68cd14b1e09bf0983d16343a9273, name=Helen, remark=eeee)
*/
  • selectOne
@Test
    public void testSelectOne() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name","l");
        User user = userMapper.selectOne(queryWrapper);
        System.out.println(user);
//        userList.forEach(System.out::println);
    }

/**
结果为:
User(id=71de68cd14b1e09bf0983d16343a9273, name=Helen, remark=eeee)
*/
  • selectCount
@Test
    public void testSelectCount() {
        Integer count = userMapper.selectCount(null);
        System.out.println("数据条数为:"+count);
//        userList.forEach(System.out::println);
    }

/**
结果为:
数据条数为:2
*/
  • selectById
 @Test
    public void testSelectById() {
        User user = userMapper.selectById("f5e6ff394703a960d9169936d027d808");
        System.out.println(user);
    }

/**
结果为:
User(id=f5e6ff394703a960d9169936d027d808, name=Kitty, remark=hhhh)
*/
  • selectMaps

如果我们没有新建实体类进行结果封装,我们还可以用 Map 来接收结果集:

@Test
public void selectMaps() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.like("name","l");
    List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
    maps.forEach(System.out::println);
}
/**
结果为:
{name=Helen, remark=eeee, id=71de68cd14b1e09bf0983d16343a9273}
{name=Kittyl, remark=hhhh, id=f5e6ff394703a960d9169936d027d808}
*/
  • selectObjs

也可以用 Object 对象来接收结果集:

@Test
    public void selectObjs() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name", "l");
        List<Object> objects = userMapper.selectObjs(queryWrapper);
    }
/**
结果为:
{name=Helen, remark=eeee, id=71de68cd14b1e09bf0983d16343a9273}
{name=Kittyl, remark=hhhh, id=f5e6ff394703a960d9169936d027d808}
*/
  • selectPage

分页的话需要配置分页插件如下:

package com.example.demo.config;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

//Spring boot方式
@EnableTransactionManagement(proxyTargetClass = true)
@Configuration
public class MybatisPlusConfig {

    /**
     * 分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

执行看结果:

 @Test
    public void selectPage() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name", "l");
        Page<User> page = new Page<>(1, 1);
        IPage<User> userIPage = userMapper.selectPage(page, queryWrapper);
        System.out.println("数据总数:" + userIPage.getTotal());
        System.out.println("总页数:" + userIPage.getPages());
        System.out.println("当前页:" + userIPage.getCurrent());
        System.out.println("页大小:" + userIPage.getSize());
        userIPage.getRecords().forEach(System.out::println);
    }

/**
结果:
JsqlParserCountOptimize sql=SELECT  id,name,remark  FROM user 
 
 WHERE (name LIKE ?)
==>  Preparing: SELECT COUNT(1) FROM user WHERE (name LIKE ?) 
==> Parameters: %l%(String)
<==    Columns: COUNT(1)
<==        Row: 2
==>  Preparing: SELECT id,name,remark FROM user WHERE (name LIKE ?) LIMIT ?,? 
==> Parameters: %l%(String), 0(Long), 1(Long)
<==    Columns: id, name, remark
<==        Row: 71de68cd14b1e09bf0983d16343a9273, Helen, eeee
<==      Total: 1

数据总数:2
总页数:2
当前页:1
页大小:1
User(id=71de68cd14b1e09bf0983d16343a9273, name=Helen, remark=eeee)
*/

5.条件构造器

CRUD 的基本操作中,我们想要通过条件查询都是通过 Wrapper 类进行封装的,上面只是简单的用到 eqlike 操作。事实上这个类十分强大,我们在下面会详细进行介绍。

  1. allEq

全部 eq 或个别 isNull

allEq(Map<R, V> params)
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
    
allEq(BiPredicate<R, V> filter, Map<R, V> params)
allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) 

参数说明:

param: key 为数据库字段名,value 为字段值

nullsIsNull:为 true 则在 map 的 value 为 null 时调用 isNull 方法,为 false 时则忽略 value 为 null 时不调用 isNull 方法

condtion: 为true时拼接查询条件,为false时不拼接查询条件

filter: 过滤函数,判断是否允许字段传入比对条件中

使用示例:

  • allEq(Map<R, V> params)
@Test
public void testAllEq1() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    Map<String,Object> params = new HashMap<>();
    params.put("name","Helen");
        params.put("remark",null);
    queryWrapper.allEq(params); //会调用 isNull 方法
    userMapper.selectList(queryWrapper);
}
/** 
 结果:
{}
 SQL语句:
==>  Preparing: SELECT id,name,remark FROM user WHERE (name = ? AND remark IS NULL) 
==> Parameters: Helen(String)
<==      Total: 0
 */
  • allEq(Map<R, V> params, boolean null2IsNull)
@Test
    public void testAllEq2() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        Map<String,Object> params = new HashMap<>();
        params.put("name","Helen");
        params.put("remark",null);
        queryWrapper.allEq(params,false); //不会调用 isNull 方法
        userMapper.selectList(queryWrapper);
    }
/** 
SQL语句:
==>  Preparing: SELECT id,name,remark FROM user WHERE (name = ?) 
==> Parameters: Helen(String)
<==    Columns: id, name, remark
<==        Row: 71de68cd14b1e09bf0983d16343a9273, Helen, eeee
<==      Total: 1
*/
  • allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
@Test
    public void testAllEq3() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        Map<String,Object> params = new HashMap<>();
        params.put("name","Helen");
        params.put("remark",null);
        queryWrapper.allEq(false,params,false); ///不会带入查询条件
        userMapper.selectList(queryWrapper);
    }
/** 
结果:
==>  Preparing: SELECT id,name,remark FROM user 
==> Parameters: 
<==    Columns: id, name, remark
<==        Row: 71de68cd14b1e09bf0983d16343a9273, Helen, eeee
<==        Row: f5e6ff394703a960d9169936d027d808, Kittyl, hhhh
<==      Total: 2
*/
  • allEq(BiPredicate<R, V> filter, Map<R, V> params)
@Test
    public void testAllEq4() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        Map<String, Object> params = new HashMap<>();
        params.put("name", "Helen");
        params.put("remark", null);
        //只有 key 中含有 “m” 才会用作条件判断
        queryWrapper.allEq((k, v) -> (k.contains("m")), params);
        userMapper.selectList(queryWrapper);
    }
/** 
SQL语句:
==>  Preparing: SELECT id,name,remark FROM user WHERE (name = ? AND remark IS NULL) 
==> Parameters: Helen(String)
<==   
Total: 0
*/
  1. 比较操作
  • eq: 相当于 =
  • ne: 相当于 !=
  • gt: 相当于 >
  • ge: 相当于>=
  • lt: 相当于 <
  • le: 相当于<=
  • between: 相当于between ... and ...
  • notBetween: 相当于not between ... and ...
  • in: 相当于in(.., .., ..)
  • notIn: 相当于not in(.., .., ..)
  1. 模糊查询
  • like: like("name","H") --> name like "%H%"
  • notLike: notLike("name","H") --> name not like "%H%"
  • likeLeft: like("name","H") --> name like "%H"
  • likeRight: like("name","H") --> name like "H%"
  1. 排序
  • orderBy:
orderBy(boolean condition, boolean isAsc, R... columns)
orderBy(true, true, "id", "name") --> order by id ASC, name ASC
  • orderByAsc:
orderByAsc("id","name") --> order by id ASC, name ASC
  • orderByDesc:
orderByDesc("id","name) --> order by id Desc, name Desc
  1. 逻辑查询
  • or:

拼接:主动调用 or 表示紧接着下一个方法不是用 and 连接!(不调用 or 则默认为使用 and连接), eq("id",1).or().eq("name","老王")

嵌套:or(i -> i.eq("name", "李白").ne("status", "活着"))

  • and:

嵌套:and(i -> i.eq("name", "李白").ne("status", "活着"))

  1. select

在MP查询中,默认查询所有的字段,如果有需要也可以通过select方法进行指定字段,如select("id", "name")

6. 配置讲解

  1. 基本配置
  • configLocation

用于指明 **MyBatis ** 配置文件的位置,如果我们有 MyBatis 的配置文件,需将配置文件的路径配置到 configLocation

SpringBoot:

mybatis-plus.config-location = classpath:mybatis-config.xml

SpringMvc:

<bean id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean
  • mapperLocations

用于指明 Mapper 所对应的 XML 的文件位置,我们在 通用 CRUD 中用到的 Mapper 是直接继承 MP 提供的 BaseMapper ,我们也可以自定义方法,然后在 XML 文件中自定义 SQL,而这时我们需要告诉 Mapper 所对应 XML 文件的位置

SpringBoot:

mybatis-plus.mapper-locations = classpath*:mybatis/*.xml

SpringMVC:

<bean id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="mapperLocations" value="classpath*:mybatis/*.xml"/>
</bean>
  • typeAliasesPackage

用于 MyBatis 别名包扫描路径,通过该属性可以给包中的类注册别名,注册后在 Mapper对应的 XML 文件中可以直接使用类名,而不用使用全限定的类名

SpringBoot:

mybatis-plus.type-aliases-package = cbuc.life.bean

SpringMVC:

<bean id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="typeAliasesPackage"
value="com.baomidou.mybatisplus.samples.quickstart.entity"/>
</bean>
  1. 进阶配置
  • mapUnderScoreToCamelCase

是否开启自动驼峰命名规则映射,这个配置的默认值是 true,但是这个属性在 MyBatis 中的默认值是 false,所以在我们平时的开发中都会将这个配置开启。

#关闭自动驼峰映射,该参数不能和mybatis-plus.config-location同时存在
mybatis-plus.configuration.map-underscore-to-camel-case = false
  • cacheEnabled

全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存,默认为 true

mybatis-plus.configuration.cache-enabled = false
  1. DB 策略配置
  • idType

全局默认主键类型,设置后,即可省略实体对象中的@TableId(type = IdType.AUTO)配置。该配置的默认值为 ID_WORKER

SpringBoot:

mybatis-plus.global-config.db-config.id-type = auto

SpringMVC:

<bean id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
 <property name="dataSource" ref="dataSource"/>
    <property name="globalConfig">
        <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig">
            <property name="dbConfig">
                <bean         class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
                 <property name="idType" value="AUTO"/>
                </bean>
            </property>
        </bean>
    </property>
</bean>
  • tablePrefix

表名前缀,全局配置后可省略@TableName()配置。该配置的默认值为 null

SpringBoot:

mybatis-plus.global-config.db-config.table-prefix = yq_

SpringMVC:

<bean id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="globalConfig">
        <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig">
            <property name="dbConfig">
                <bean            class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
                 <property name="idType" value="AUTO"/>
                 <property name="tablePrefix" value="yq_"/>
                </bean>
            </property>
        </bean>
    </property>
</bean>

7. 其他扩展

  1. 自动填充

有时候我们在插入或更新数据的时候,希望有些字段可以自动填充。比如我们平时数据表里面会有个 插入时间 或者 更新时间 这种字段,我们会默认以当前时间填充,在 MP 中我们也可以进行配置。

首先我们需要借助 @TableField(fill = FieldFill.INSERT) 这个注解,在插入时进行填充。

@TableField(fill = FieldFill.INSERT)
private String remark;

其中自动填充的模式如下:

public enum FieldFill {
    /**
    * 默认不处理
    */
    DEFAULT,
    /**
    * 插入时填充字段
    */
    INSERT,
    /**
    * 更新时填充字段
    */
    UPDATE,
    /**
    * 插入和更新时填充字段
    */
    INSERT_UPDATE
}

然后我们再编写自定义的填充处理模式:

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        Object remark = getFieldValByName("remark", metaObject);
        if (null == remark) {
            setFieldValByName("remark", "好好学习", metaObject);
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {
  //自定义更新时填充
    }
}

测试:

 @Test
    public void testUserInsert() {
        System.out.println(("----- insert method test ------"));
        User user = new User();
        user.setName("Helen");
//        user.setRemark("eeee");
        int insertFlag = userMapper.insert(user);
        log.info("插入影响行数,{} | Kitty的ID: {}", insertFlag, user.getId());
    }

可以看到插入时,已经自动将我们填充的字段合并进去。

  1. 逻辑删除

在开发中,很多时候我们删除数据并不需要真正意义上的物理删除,而是使用逻辑删除,这样子查询的时候需要状态条件,确保被标记的数据不被查询到。MP 当然也支持这样的功能。

我们需要先为 student 表添加一个字段 status 来声明数据是否被删除,0 表示被删除,1表示未删除,然后也需要在实体类上增加这个属性:

@TableLogic
private Integer status;

application.yaml 中配置:

mybatis-plus:
  global-config:
    db-config:
      logic-delete-value: 0
      logic-not-delete-value: 1

测试:

@Test
public void testLogicDelete() {
    userMapper.deleteById(1);
}
/**
 SQL语句:
UPDATE student SET status=0
WHERE id=1 AND status=1;
**/

可以看出这段 SQL 并没有真正删除,而是进行了逻辑删除,只是更新了删除标识

  1. 通用枚举

如果有性别之类的字段,我们通常会用 01 来表示,但是查出来我们得进行值转换,这个时候我们就可以使用枚举来解决这个问题:

首先为 student 表添加一个 sex 字段来表示性别,0 表示女性,1 表示男性,然后定义一个枚举类:

public enum SexEnum implements IEnum<Integer> {
    MAN(1, "男"),
    WOMEN(0, "女");

    private int code;

    private String value;

    SexEnum(int code, String value) {
        this.code = code;
        this.value = value;
    }

    @Override
    public Integer getValue() {
        return this.code;
    }
    
    //注意要重写此方法,不然会将值转换成 ‘MAN’,而不是 ‘男’
    @Override
    public String toString() {
        return this.value;
    }
}

然后在实体类中添加对应属性:

private SexEnum sex;

application.yaml 中配置:

mybatis-plus:
  type-enums-package: cbuc.life.enums

测试:

 @Test
    public void testSelectOne() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name","Helen");
        User user = userMapper.selectOne(queryWrapper);
        System.out.println(user);
//        userList.forEach(System.out::println);
    }
/**
 输出结果:
User(id=1, deptId=1, name=小菜, remark=关注小菜不迷路!, status=1, sex=男)
 SQL语句:
 SELECT id,sex,name,dept_id,remark,status
 FROM student
 WHERE status=1 AND (name = '小菜');
**/

springbootyml配置:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: false
    cache-enabled: false
#  config-location: classpath:mybatis-config.xml
  mapper-locations: classpath*:mapper/*.xml
  type-aliases-package: com.example.demo.entity
  global-config:
    db-config:
      id-type: auto
#      table-prefix: t_

pe-enums-package: cbuc.life.enums


**测试:**

```java
 @Test
    public void testSelectOne() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name","Helen");
        User user = userMapper.selectOne(queryWrapper);
        System.out.println(user);
//        userList.forEach(System.out::println);
    }
/**
 输出结果:
User(id=1, deptId=1, name=小菜, remark=关注小菜不迷路!, status=1, sex=男)
 SQL语句:
 SELECT id,sex,name,dept_id,remark,status
 FROM student
 WHERE status=1 AND (name = '小菜');
**/

springbootyml配置:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: false
    cache-enabled: false
#  config-location: classpath:mybatis-config.xml
  mapper-locations: classpath*:mapper/*.xml
  type-aliases-package: com.example.demo.entity
  global-config:
    db-config:
      id-type: auto
#      table-prefix: t_

END

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值