目录

一、MyBatis-Plus概述

1、简介

2、特性

3、框架结构​

4、快速指南

二、MybBatis-Plus的增删改查

1、项目搭建

(1)创建表及数据导入

(2)、导入相应的依赖

(3)连接数据库

(4)编写实体类 User.java

(5)编写Mapper类 UserMapper.java

(6)测试一下

2、CRUD

(1)insert

(2)selectById

(3)selectByMap

(4)selectBatchlds

(5)updateById

(6)deleteById

(7)deleteByMap

(8)deleteBatchIds

三、MyBatis-Plus注解

1、@TableId

2、@TableName

3、@TableFieId

FieldStrategy

FieldFill

4、@Version(乐观锁)

5、@EnumValue

6、@TableLogic

7、@KeySequence

8、OrderBy

四、 MyBatis-Plus条件构造器

1、构造器简介

五、MyBatis-Plus代码生成器

1、代码生成器简介

2、 添加依赖

3、添加配置

4、代码生成器编写

5、代码生成器方法

(1)save

(2)saveOrUpdate

(3)remove

(4)update

(6)list

(7)page

(8)count

(9)chain

六、MyBatis-Plus插件

1、@Version(乐观锁)

乐观锁实现方式:

2、分页插件

3、性能分析插件

七、MyBatis-Plus的扩展功能

1、逻辑删除

2、通用枚举

使用注解方式

使用实现接口模式

3、字段类型处理器

4、自动填充功能(fill):

5、Sql注入器

6、自定义ID生成器

7、Sequence主键


一、MyBatis-Plus概述

1、简介

mybatis-plus(简称MP)是一个MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

我们的愿景是成为 MyBatis 最好的搭档,就像魂斗罗中的1P、2P,基友搭配,效率翻倍。

2、特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

3、框架结构

4、快速指南

我们将通过一个简单的 Demo 来阐述 MyBatis-Plus 的强大功能,在此之前,我们假设您已经:

  • 拥有 Java 开发环境以及相应 IDE
  • 熟悉 Spring Boot
  • 熟悉 Maven

全新的 MyBatis-Plus3.0 版本基于 JDK8,提供了 lambda 形式的调用,所以必须是JDK 8+,这里用spring boot集成mybatis-plus

  • maven

    <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.0</version>
    </dependency>

注意:引入MyBatis-Plus之后不要再次引用MyBatis和MyBatis-Spring,以避免因版本差异导致的问题

二、MybBatis-Plus的增删改查

1、项目搭建

(1)创建表及数据导入

--创建表
DROP TABLE IF EXISTS user;CREATE TABLE user
(id BIGINT(20) NOT NULL COMMENT '主键ID',name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',age INT(11) NULL DEFAULT NULL COMMENT '年龄',email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',PRIMARY KEY (id)
);--导入相应数据
DELETE FROM user;INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

(2)、导入相应的依赖

    <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency>
<!--mybatis-plus 是自己开发的,非官方的!--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.0</version></dependency>
<!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.10</version><scope>provided</scope></dependency>

(3)连接数据库

spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver# 如果是mysql 8需要增加时区的配置:com.mysql.cj.jdbc.Driver#配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdouImpl

(4)编写实体类 User.java

@Data
public class User {private Long id;private String name;private Integer age;private String email;
}

(5)编写Mapper类 UserMapper.java

//在对应的Mapper上继承基本的类baseMapper
public interface UserMapper extends BaseMapper<User> {}

在Spring Boot启动类中添加@MapperScan注解,扫描Mapper文件夹:

@SpringBootApplication
@MapperScan("com.jacko.mapper")//扫描mapper文件夹
public class Application {public static void main(String[] args) {SpringApplication.run(QuickStartApplication.class, args);}}

(6)测试一下

@SpringBootTest
public class MPApplicationTests {@Autowiredprivate UserMapper userMapper;@Testpublic void testSelect() {//参数是一个Wrapper,条件结构器,这里先不用 填null//查询所有的用户 List<User> userList = userMapper.selectList(null);userList .forEach(System.out::println);}}

UserMapper 中的 selectList() 方法的参数为 MP 内置的条件封装器 Wrapper,所以不填写就是无任何条件

2、CRUD

(1)insert

需求描述:插入一个用户,姓名为“zhangsan”、年龄为18岁、邮箱为"zhangsan@qq.com"

@Test
void testInsert() {int result = userMapper.insert(new User(null,"zhangsan",18,"zhangsan@qq.com"));System.out.println("result:" + result);
}

(2)selectById

需求描述:查询id为1的用户信息

@Test
void testSelectById() {Useruser= userMapper.selectById(1);System.out.println(user);
}

(3)selectByMap

需求描述:年龄在18岁的用户信息

@Test
void testSelectByMap() {Map<String, Object> map = new HashMap<>();map.put("age",18);List<User> users= userMapper.selectByMap(map);users.forEach(System.out::println);
}

(4)selectBatchlds

需求描述:查询id分别为1、2、3的用户信息

@Test
void testSelectBatchIds() {List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));users.forEach(System.out::println);
}

(5)updateById

需求描述:将id为1的用户姓名改为“jacko”

@Test
void testUpdateById() {// 先查询User user = UserMapper.selectById(1);user .setLastName("jacko");// 再修改int result = UserMapper.updateById(user);System.out.println(result);
}

(6)deleteById

需求描述:删除id为1的用户信息

@Test
void testDeleteById() {int result = userMapper.deleteById(1);System.out.println(result);
}

(7)deleteByMap

需求描述:删除年龄为18岁且姓名为jacko的用户信息

@Test
void testDeleteByMap() {Map<String, Object> map = new HashMap<>();map.put("name", "jakoc");map.put("age", 18);int result = userMapper.deleteByMap(map);System.out.println(result);
}

(8)deleteBatchIds

需求描述:删除id分别为4、5、6的员工的信息

@Test
void testDeleteBatchIds() {int result = userMapper.deleteBatchIds(Arrays.asList(4, 5));System.out.println(result);
}

三、MyBatis-Plus注解

1、@TableId

主键注解
序号 属性 类型 默认值 描述
01 value String "" 主键字段名
02 type Enum IdType.NONE 主键类型
IdType
描述
AUTO 数据库ID自增
NONE 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
INPUT insert前自行set主键值
ASSIGN_ID 分配ID(主键类型为Number(Long和Integer)或String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法)
ASSIGN_UUID 分配UUID,主键类型为String(since 3.3.0),使用接口IdentifierGenerator的方法nextUUID(默认default方法)
ID_WORKER 分布式全局唯一ID 长整型类型(please use ASSIGN_ID)
UUID 32位UUID字符串(please use ASSIGN_UUID)
ID_WORKER_STR 分布式全局唯一ID 字符串类型(please use ASSIGN_ID)

2、@TableName

表名注解
序号 属性 类型 默认值 描述
01 value String "" 表名
02 schema String "" schema
03 keepGlobalPrefix boolean false 是否保持使用全局的 tablePrefix 的值(如果设置了全局 tablePrefix 且自行设置了 value 的值)
04 resultMap String "" xml中resultMap的id
05 autoResultMap boolean false 是否自动构建resultMap并使用(如果设置resultMap则不会进行resultMap的自动构建并注入)
06 excludeProperty String[] {} 需要排除的属性名(@since 3.3.1)

3、@TableFieId

字段注解(非主键)
序号 属性 类型 默认值 描述
01 value String "" 数据库的字段名
02 el String "" 映射为原生#{...}逻辑,相当于写在xml里的#{...}部分
03 exist boolean true 是否为数据库表的字段
04 condition String "" 字段 where 实体查询比较条件,有值设置则按设置的值为准,没有则为默认全局的 %s=#{%s},
05 update String "" 字段 update set 部分注入, 例如:update="%s+1":表示更新时会set version=version+1(该属性优先级高于 el 属性)
06 insertStrategy Enum DEFAULT 举例:NOT_NULL: insert into table_a(<if test="columnProperty != null">column</if>) values (<if test="columnProperty != null">#{columnProperty}</if>)
07 updateStrategy Enum DEFAULT 举例:IGNORED: update table_a set column=#{columnProperty}
08 whereStrategy Enum DEFAULT 举例:NOT_EMPTY: where <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if>
09 fill Enum FieldFill.DEFAULT 字段自动填充策略
10 select boolean true 是否进行 select 查询
11 keepGlobalFormat boolean false 是否保持使用全局的 format 进行处理
12 jdbcType JdbcType JdbcType.UNDEFINED JDBC类型 (该默认值不代表会按照该值生效)
13 typeHandler Class<? extends TypeHandler> UnknownTypeHandler.class 类型处理器 (该默认值不代表会按照该值生效)
14 numericScale String "" 指定小数点后保留的位数

FieldStrategy

序号 描述
01 IGNORED 忽略判断
02 NOT_NULL 非NULL判断
03 NOT_EMPTY 非空判断(只对字符串类型字段,其他类型字段依然为非NULL判断)
04 DEFAULT 追随全局配置

FieldFill

具体使用MyBatis-Puls的扩展功能

序号 描述
01 DEFAULT 默认不处理
02 INSERT 插入时填充字段
03 UPDATE 更新时填充字段
04 INSERT_UPDATE 插入和更新时填充字段

4、@Version(乐观锁)

描述:乐观锁注解、标记 @Verison 在字段上,具体使用MyBatis-Puls的扩展功能

5、@EnumValue

描述:通枚举类注解(注解在枚举字段上),具体使用MyBatis-Puls的扩展功能

6、@TableLogic

描述:表字段逻辑处理注解(逻辑删除),具体使用MyBatis-Puls的扩展功能

序号 属性 类型 默认值 描述
01 value String "" 逻辑未删除值
02 delval String "" 逻辑删除值

7、@KeySequence

  • 描述:序列主键策略 oracle,具体使用MyBatis-Puls的扩展功能
  • 属性:value、resultMap
    序号 属性 类型 默认值 描述
    01 value String "" 序列名
    02 clazz Class Long.class id的类型, 可以指定String.class,这样返回的Sequence值是字符串"1

8、OrderBy

  • 描述:内置 SQL 默认指定排序,优先级低于 wrapper 条件查询
序号 属性 类型 默认值 描述
01 isDesc boolean 是否倒序查询
02 sort short Short.MAX_VALUE 数字越小越靠前

四、 MyBatis-Plus条件构造器

1、构造器简介

MyBatis-Plus 通过 EntityWrapper(简称 EW,MP 封装的一个查询条件构造器)或者 Condition(与 EW 类似) 来让用户自由的构建查询条件,简单便捷,没有额外的负担, 能够有效提高开发效率,它主要用于处理 sql 拼接,排序,实体参数查询等。

注意:使用的是数据库字段,不是 Java 属性!

@Test
void testSelectList1() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.allEq({name:"老王",age:24})   //name = '老王' and age= 24,.eq("age",24)                  //等于,age=24.ne("age",24)                  //不等于,age<>24.gt("age",24);                 //大于,age>24.ge("age",24);                 //大于等于,age>=24.lt("age",24);                 //小于,age<24.le("age",24);                 //小于等于,age<=24的.between("age", 18, 30)        //age between 18 and 30.notBetween("age", 18, 30)     //age not between 18 and 30.Like("name", "王")            //模糊查询,name like '%王%.notLike("name", "王")         //模糊查询,name not like '%王%.likeLeft("name", "王")        //模糊查询,name like '%王'.likeRight("name", "王")       //模糊查询,name like '王%'.isNull("name")                //name is null.isNotNull("name")             //name is not null.in("age",{1,2,3})             //age in (1,2,3).notIn("age", 1, 2, 3)         //age not in (1,2,3).inSql("id", "select id from table where id < 3")//id in (select id from table where id < 3).notInSql("id", "select id from table where id < 3")//id not in (select id from table where id < 3).groupBy("id", "name")        //分组,group by id,name.orderByAsc("id", "name")     //排序,order by id ASC,name ASC.orderByDesc("id", "name")    //排序,order by id DESC,name DESC.having("sum(age) > 10")      //having sum(age) > 10.or(i -> i.eq("name", "jacko").ne("status", "活着"))//or (name = '李白' and status <> '活着').and(i -> i.eq("name", "jacko").ne("status", "活着"))//and (name = '李白' and status <> '活着').select("id", "name", "age").set("name", "老李头")List<User> users= userMapper.selectList(queryWrapper);users.forEach(System.out::println);
}

五、MyBatis-Plus代码生成器

1、代码生成器简介

AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

2、 添加依赖

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.0</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.4.0</version></dependency><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.2</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version><scope>provided</scope></dependency>
</dependencies>
<build><!-- 插件管理 --><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-resources-plugin</artifactId><version>2.5</version></plugin></plugins><!-- 资源管理 --><resources><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include><include>**/*.conf</include></includes><filtering>false</filtering></resource><resource><directory>src/main/resources</directory><includes><include>**/*.properties</include><include>**/*.xml</include><include>**/*.conf</include></includes><filtering>false</filtering></resource></resources>
</build>

3、添加配置

spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver# 如果是mysql 8需要增加时区的配置:com.mysql.cj.jdbc.Driver#配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdouImpl#mybatis-plus
mybatis-plus.mapper-locations=classpath*:**/mapper/xml/*.xml

4、代码生成器编写

public class CodeGenerator {public static String scanner(String tip) {Scanner scanner = new Scanner(System.in);StringBuilder help = new StringBuilder();help.append("请输入" + tip + ":");System.out.println(help.toString());if (scanner.hasNext()) {String ipt = scanner.next();if (StringUtils.isNotBlank(ipt)) {return ipt;}}throw new MybatisPlusException("请输入正确的" + tip + "!");}public static void main(String[] args) {// 代码生成器AutoGenerator mpg = new AutoGenerator();// 全局配置GlobalConfig gc = new GlobalConfig();String projectPath = System.getProperty("user.dir");gc.setOutputDir(projectPath + "/src/main/java");//设置代码生成路径gc.setFileOverride(true);//是否覆盖以前文件gc.setOpen(false);//是否打开生成目录gc.setAuthor("jacko");//设置项目作者名称gc.setIdType(IdType.AUTO);//设置主键策略gc.setBaseResultMap(true);//生成基本ResultMapgc.setBaseColumnList(true);//生成基本ColumnListgc.setServiceName("%sService");//去掉服务默认前缀mpg.setGlobalConfig(gc);// 数据源配置DataSourceConfig dsc = new DataSourceConfig();dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf8");dsc.setDriverName("com.mysql.jdbc.Driver");dsc.setUsername("root");dsc.setPassword("123456");mpg.setDataSource(dsc);// 包配置PackageConfig pc = new PackageConfig();pc.setParent("com.jacko");pc.setMapper("mapper");pc.setXml("mapper.xml");pc.setEntity("entity");pc.setService("service");pc.setServiceImpl("service.impl");pc.setController("controller");mpg.setPackageInfo(pc);// 策略配置StrategyConfig sc = new StrategyConfig();sc.setNaming(NamingStrategy.underline_to_camel);sc.setColumnNaming(NamingStrategy.underline_to_camel);sc.setEntityLombokModel(true);//自动配置lomboksc.setRestControllerStyle(true);sc.setControllerMappingHyphenStyle(true);sc.setTablePrefix("tbl_");sc.setInclude(scanner("表名,多个英文逗号分割").split(","));//设置要映射的表名mpg.setStrategy(sc);// 生成代码mpg.execute();}}

5、代码生成器方法

通用 Service CRUD 封装 IService 接口,进一步封装 CRUD 采用 get 查询单行 remove 删除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆,泛型 T 为任意实体对象,建议如果存在自定义通用 Service 方法的可能,请创建自己的 IBaseService 继承 Mybatis-Plus 提供的基类,对象 Wrapper 为 条件构造器。

(1)save

// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量)
boolean saveBatch(Collection<T> entityList, int batchSize);

参考说明:

类型 参数名 描述
T entity 实体对象
Collection<T> entityList 实体对象集合
int batchSize 插入批次数量

(2)saveOrUpdate

// TableId 注解存在更新记录,否插入一条记录
boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);

参考说明:

类型 参数名 描述
T entity 实体对象
Wrapper<T> updateWrapper 实体对象封装操作类 UpdateWrapper
Collection<T> entityList 实体对象集合
int batchSize 插入批次数量

(3)remove

// 根据 entity 条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
// 根据 columnMap 条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);

参考说明:

类型 参数名 描述
Wrapper<T> queryWrapper 实体包装类 QueryWrapper
Serializable id 主键ID
Map<String, Object> columnMap 表字段 map 对象
Collection<? extends Serializable> idList 主键ID列表

(4)update

// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
boolean update(Wrapper<T> updateWrapper);
// 根据 whereEntity 条件,更新记录
boolean update(T entity, Wrapper<T> updateWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);

参考说明:

类型 参数名 描述
Wrapper<T> updateWrapper 实体对象封装操作类 UpdateWrapper
T entity 实体对象
Collection<T> entityList 实体对象集合
int batchSize 更新批次数量

(5)get

// 根据 ID 查询
T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);

参考说明:

(6)list

// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询(根据 columnMap 条件)
Collection<T> listByMap(Map<String, Object> columnMap);
// 查询所有列表
List<Map<String, Object>> listMaps();
// 查询列表
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 查询全部记录
List<Object> listObjs();
// 查询全部记录
<V> List<V> listObjs(Function<? super Object, V> mapper);
// 根据 Wrapper 条件,查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);

参考说明:

类型 参数名 描述
Wrapper<T> queryWrapper 实体对象封装操作类 QueryWrapper
Collection<? extends Serializable> idList 主键ID列表
Map<?String, Object> columnMap 表字段 map 对象
Function<? super Object, V> mapper 转换函数

(7)page

// 无条件分页查询
IPage<T> page(IPage<T> page);
// 条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 无条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);

参数说明:

类型 参数名 描述
IPage<T> page 翻页对象
Wrapper<T> queryWrapper 实体对象封装操作类 QueryWrapper

(8)count

// 查询总记录数
int count();
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);

参数说明:

类型 参数名 描述
Wrapper<T> queryWrapper 实体对象封装操作类 QueryWrapper

(9)chain

query

// 链式查询 普通
QueryChainWrapper<T> query();
// 链式查询 lambda 式。注意:不支持 Kotlin
LambdaQueryChainWrapper<T> lambdaQuery(); // 示例:
query().eq("column", value).one();
lambdaQuery().eq(Entity::getId, value).list();

update

// 链式更改 普通
UpdateChainWrapper<T> update();
// 链式更改 lambda 式。注意:不支持 Kotlin
LambdaUpdateChainWrapper<T> lambdaUpdate();// 示例:
update().eq("column", value).remove();
lambdaUpdate().eq(Entity::getId, value).update(entity);

六、MyBatis-Plus插件

创建包:com.jacko.config

新建类:com.jacko.config.MybatisPlusConfig

1、@Version(乐观锁)

  • 乐观锁:顾名思义十分乐观,它总是被认为不会出现问题,无论干什么都不去上锁!如果出现了问题,再次更新测试
  • 悲观锁:顾名思义十分悲观,它总是出现问题,无论干什么都会上锁!再去操作!

乐观锁实现方式:

  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时,set version=newVersion where version =oldVersion
  • 如果version不对,就更新失败

(1)表中添加乐观锁字段version 默认值为1

(2)同步实体类

@Version
private Integer version;

(3)注册组件

@EnableTransactionManagement
@Configuration//配置类
public class MyBatisPlusConfig{//注册乐观锁插件@Beanpublic OptimisticLockerInterceptor optimisticLockerInterceptor() {return new OptimisticLockerInterceptor();}
}

注意:

  • 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
  • 整数类型下 newVersion = oldVersion + 1
  • 仅支持 updateById(id) 与 update(entity, wrapper) 方法
  • 在 update(entity, wrapper) 方法下, wrapper 不能复用!!!

测试一下:

@Test
public void testOptimisticLocker(){//假设线程1User user = userMapper.selectById(1L);user.setName("zhangsan111");user.setEmail("123456789@qq.com");//假设线程2,执行插队操作User user2 = userMapper.selectById(1L);user2.setName("zhangsan222");user2.setEmail("123456789@qq.com");userMapper.updateById(user2);//如果没有乐观锁就会覆盖插队线程2的值userMapper.updateById(user2);}

2、分页插件

添加插件:

@EnableTransactionManagement
@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 添加分页插件interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}}

属性设置:

属性名 类型 默认值 描述
overflow boolean false 溢出总页数后是否进行处理(默认不处理,参见 插件#continuePage 方法)
maxLimit Long 单页分页条数限制(默认无限制,参见 插件#handlerLimit 方法)
dbType DbType 数据库类型(根据类型获取应使用的分页方言,参见 插件#findIDialect 方法)
dialect IDialect 方言实现类(参见 插件#findIDialect 方法)

测试一下:

@Test
void testPagination() {Page<Employee> page = new Page<>(1,5);Page<User> usersPage = userMapper.selectPage(page, null);usersPage.getRecords().forEach(System.out::println);System.out.println("当前页:" + usersPage.getCurrent());System.out.println("总页数:" + usersPage.getPages());System.out.println("记录数:" + usersPage.getTotal());System.out.println("是否有上一页:" + usersPage.hasPrevious());System.out.println("是否有下一页:" + usersPage.hasNext());
}

3、性能分析插件

作用:性能分析拦截器,用于输出每条SQL语句及执行时间,MP也提供性能分析插件,如果超过这和时间就会停止运行

添加插件:

@EnableTransactionManagement
@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {...}/*** SQL执行效率插件*/@Bean@Profile({"dev","test"})// 设置 dev test 环境开启public PerformanceInterceptor performanceInterceptor() {PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();performanceInterceptor.setMaxTime(100);// ms 设置sql执行的最大时间,如果超过就停止performanceInterceptor.setFormat(true);return new PerformanceInterceptor();}
}
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver# 如果是mysql 8需要增加时区的配置:com.mysql.cj.jdbc.Driver#配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdouImpl#mybatis-plus
mybatis-plus.mapper-locations=classpath*:**/mapper/xml/*.xmlspring.profiles.active=dev

测试一下:

@Test
void testPagination() {Page<Employee> page = new Page<>(1,5);Page<User> usersPage = userMapper.selectPage(page, null);usersPage.getRecords().forEach(System.out::println);System.out.println("当前页:" + usersPage.getCurrent());System.out.println("总页数:" + usersPage.getPages());System.out.println("记录数:" + usersPage.getTotal());System.out.println("是否有上一页:" + usersPage.hasPrevious());System.out.println("是否有下一页:" + usersPage.hasNext());
}

七、MyBatis-Plus的扩展功能

1、逻辑删除

  • 物理删除:从数据库中直接移除
  • 逻辑删除:在数据库中没有被移除,而是通过一个变量来让他失效!delete=0 => delete=1

管理员可以查看被删除的记录!防止数据的丢失,类似于回收站!

(1)在数据表中添加deleted字段

(2)实体类中添加deleted属性

//逻辑删除字段
private Integer deleted;

(3)配置一下

# 配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-field=deleted # 全局逻辑删除的实体字段名
mybatis-plus.global-config.db-config.logic-delete-value=1 # 逻辑已删除值(默认为 1)
mybatis-plus.global-config.db-config.logic-not-delete-value=0 # 逻辑未删除值(默认为 0)

(4)测试一下

@Test
void testPagination() {userMapper.deleteById(2);
}

2、通用枚举

通用枚举解决了繁琐的配置,让 mybatis 优雅的使用枚举属性!实现自定义枚举有两种方式,一种是使用注解而另一种是使用实现接口IEnum的方式

使用注解方式

(1)添加配置

mybatis-plus.type-enums-package=com.jacko.myenum
mybatis-plus.configuration.default-enum-type-handler=org.apache.ibatis.type.EnumOrdinalTypeHandler

(2)创建枚举类com.jacko.myenum.GradeEnum

public enum GradeEnum {PRIMARY(1, "小学"),SECONDORY(2, "中学"),HIGH(3, "高中");private int code;@EnumValue//描述作为枚举值保存到数据库private String desc;GradeEnum(int code, String desc) {this.code = code;this.desc = desc;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}
}

(3)修改实体类com.jacko.entity.Student

/*** 学生年级*/
private GradeEnum grade;

(4)测试一下

@Test
void testGradeEnum() {Student student = new Student();student.setName("王五");student.setGrade(GradeEnum.HIGH);int result = studentMapper.insert(student);System.out.println(result);
}

使用实现接口模式

(1)添加配置

mybatis-plus.type-enums-package=com.jacko.myenum
mybatis-plus.configuration.default-enum-type-handler=org.apache.ibatis.type.EnumOrdinalTypeHandler

(2)创建枚举类com.jacko.myenum.AgeEnum

public enum AgeEnum implements IEnum<Integer> {ONE(1, "一岁"),TWO(2, "二岁"),THREE(3, "三岁");private int value;private String desc;AgeEnum(int value, String desc) {this.value = value;this.desc = desc;}@Overridepublic Integer getValue() {//数值作为枚举值保存到数据库return this.value;}
}

(3)修改实体类com.jacko.entity.Student

/*** 学生年龄*/
private AgeEnum age;

(4)测试一下

@Test
void testAgeEnum() {Student student = new Student();student.setName("李四");student.setAge(AgeEnum.THREE);int result = studentMapper.insert(student);System.out.println(result);
}

3、字段类型处理器

字段类型处理器,用于 JavaType 与 JdbcType 之间的转换,用于 PreparedStatement 设置参数值和从 ResultSet 或 CallableStatement 中取出一个值,本文讲解 mybaits-plus 内置常用类型处理器如何通过TableField注解快速注入到 mybatis 容器中。

@Data
@Accessors(chain = true)
@TableName(autoResultMap = true)
public class User {private Long id;.../*** 注意!! 必须开启映射注解** @TableName(autoResultMap = true)** 以下两种类型处理器,二选一,也可以同时存在** 注意!! 选择对应的 JSON 处理器也必须存在对应 JSON 解析依赖包*/@TableField(typeHandler = JacksonTypeHandler.class)// @TableField(typeHandler = FastjsonTypeHandler.class)private OtherInfo otherInfo;}

4、自动填充功能(fill):

创建时间、修改时间!这些个操作一遍都是自动化完成,我们不希望手动更新!

阿里巴巴开发手册:所有的数据库表几乎所有的表都要配置上!而且需要自动化

方式一:数据库级别

在表中新增字段create_time、update_time(默认CURRENT_TIMESIAMP)

方式二:代码级别

①实体类上的属性增加注解@TableField


//创建时间
@TableField(fill = FieldFill.INSERT)
private Date createTime;//更新时间
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;

②编写处理器处理这个注解

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {//插入时候的填充策略@Override@Componcent  //一定不要忘记吧处理器加到IOC容器中public void insertFill(MetaObject metaObject) {log.info("start insert fill ....");  //日志//设置字段的值(String fieldName字段名,Object fieldVal要传递的值,MetaObject metaObject)this.setFieldVaLByName("createTime",new Date(),metaObject);this.setFieldVaLByName("updateTime",new Date(),metaObject);//this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)// this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug请升级到之后的版本如`3.3.1.8-SNAPSHOT`)/* 上面选其一使用,下面的已过时(注意 strictInsertFill 有多个方法,详细查看源码) *///this.setFieldValByName("operator", "Jerry", metaObject);//this.setInsertFieldValByName("operator", "Jerry", metaObject);}//更新时间的填充策略@Overridepublic void updateFill(MetaObject metaObject) {log.info("start update fill ....");this.setFieldVaLByName("updateTime",new Date(),metaObject);//this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)// this.fillStrategy(metaObject, "updateTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug请升级到之后的版本如`3.3.1.8-SNAPSHOT`)/* 上面选其一使用,下面的已过时(注意 strictUpdateFill 有多个方法,详细查看源码) *///this.setFieldValByName("operator", "Tom", metaObject);//this.setUpdateFieldValByName("operator", "Tom", metaObject);}
}

5、Sql注入器

根据 MybatisPlus 的 AutoSqlInjector 可以自定义各种你想要的 SQL 注入到全局中,相当于自定义 MybatisPlus 自动注入的方法。之前需要在 xml 中进行配置的 SQL 语句,现在通过扩展 AutoSqlInjector 在加载 mybatis 环境时就注入

(1)在mapper接口上添加@Repository注解

@Repository
public interface UserMapper extends BaseMapper<User> {public void deleteAll();}

注意:我们不需要编写xml映射,因为我们会采用sql注入的形式,在 MybatisPlus 启动的时候就注入。

(2)创建对象 com.jacko.injector.MyMappedStatement、MySqlInjector

public class MyMappedStatement extends AbstractMethod {@Overridepublic MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {// 接口中的方法名String method = "deleteAll";// 该方法执行语句String sql = "delete from " + tableInfo.getTableName();// 创建SqlSourceSqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);// 构造一个删除的MappedStatement并返回return this.addDeleteMappedStatement(mapperClass, method, sqlSource);}
}
public class MySqlInjector extends DefaultSqlInjector {@Overridepublic List<AbstractMethod> getMethodList(Class<?> mapperClass) {List<AbstractMethod> methodList = super.getMethodList(mapperClass);methodList.add(new MyMappedStatement());return methodList;}
}

(3)在MybatisPlusConfig添加自定义sql注入对象

@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {...}@Beanpublic MySqlInjector mySqlInjector() {return new MySqlInjector();}}

6、自定义ID生成器

Tip:自3.3.0开始,默认使用雪花算法+UUID(不含中划线)

重写方法

方法 主键生成策略 主键类型 说明
nextId ASSIGN_ID,ID_WORKER,ID_WORKER_STR Long,Integer,String 支持自动转换为String类型,但数值类型不支持自动转换,需精准匹配,例如返回Long,实体主键就不支持定义为Integer
nextUUID ASSIGN_UUID,UUID String 默认不含中划线的UUID生成

(1)创建类:com.jacko.incrementer.CustomIdGenerator

public class CustomIdGenerator implements IdentifierGenerator {private final AtomicLong al = new AtomicLong(1);@Overridepublic Long nextId(Object entity) {//可以将当前传入的class全类名来作为bizKey或者提取参数来生成bizKey进行分布式Id调用生成String bizKey = entity.getClass().getName();MetaObject metaObject = SystemMetaObject.forObject(entity);String name = (String) metaObject.getValue("pname");final long id = al.getAndAdd(1);System.out.println("为" + name + "生成主键值->:" + id);return id;}
}

(2)注册类:MybatisPlusConfig

@Bean
public IdentifierGenerator customIdGenerator(){return new CustomIdGenerator();
}

(3)修改主键策略

/*** 商品主键*/
@TableId(value = "pid", type = IdType.ASSIGN_ID)
private Long id;

(4)测试一下

@Autowired
private ProductMapper productMapper;@Test
void testCustomIdGenerator() {Product product = new Product();product.setPname("手机");int result = productMapper.insert(product);System.out.println(result);
}

7、Sequence主键

Tip主键生成策略必须使用INPUT

支持父类定义@KeySequence子类继承使用

支持主键类型指定(3.3.0开始自动识别主键类型)

内置支持:

  • DB2KeyGenerator
  • H2KeyGenerator
  • KingbaseKeyGenerator
  • OracleKeyGenerator
  • PostgreKeyGenerator

如果内置支持不满足你的需求,可实现IKeyGenerator接口来进行扩展.

在实际开发中,我们经常会使用到MySQL和Oracle数据库,但是这两种数据库对于主键有不同的策略,如下:

  • MySQL:支持主键自增,type = IdType.Auto
  • Oracle:支持序列自增,type = IdType.INPUT

实现:

(1)在实体类对象上添加注解@KeySequence(value=”序列名”, clazz=主键属性类型.class)

(2)在实体类对象的主键字段上添加注解@TableId(value = “主键名称”, type = IdType.INPUT)

@KeySequence(value = "SEQ_ORACLE_INTEGER_KEY", clazz = Integer.class)
public class YourEntity {@TableId(value = "ID", type = IdType.INPUT)private Integer id;}

(3)在全局配置中注册com.baomidou.mybatisplus.incrementer.OracleKeyGenerator

@Bean
public IKeyGenerator keyGenerator() {return new oracleKeyGenerator();
}

学习MyBatis-Plus相关推荐

  1. 跟小博老师一起学习MyBatis ——MyBatis搭建运行环境

    数据库 上回小傅老师与大伙聊了MyBatis是一款非常优秀的操作数据库的框架产品,所以大家先要安装好数据库,以便MyBatis能操作它.小傅老师用的是MYSQL数据库产品,当然你也可以使用MSSQL. ...

  2. 小白大学生学习MyBatis(二)

    小白大学生学习MyBatis(二) 1 . 接(一)解释测试代码 主要类的介绍 https://blog.csdn.net/hjs_75187712/article/details/118344894 ...

  3. 学习Mybatis第三天

    学习Mybatis第三天 1. 日志 1.1 日志工厂 如果一个数据库操作出现了异常,我们需要排错,日志就是最好的助手了! 曾今:sout,debug 现在:日志工厂 SLF4J LOG4J [掌握] ...

  4. 快速学习MyBatis|实战项目详解

    作者主页:橙子! 主页 系列专栏:JavaWeb基础教程系列 精彩回顾:HTTP协议详解 文章目的:快速学习MyBatis及实战项目详解 文章目录 1.什么是MyBatis? 2. JDBC存在的缺点 ...

  5. MyBatis构架设计学习------MyBatis的整体架构

    一.基础框架图 二.各模块的基本作用 --------------------基础支持层-------------------- 1.反射模块 MyBatis的反射模块中专门对原生的java反射进行了 ...

  6. 学习Mybatis与mysql数据库的示例笔记

    目录结构: pom.xml文件 1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xml ...

  7. 深入学习Mybatis框架(二)- 进阶

    1.动态SQL 1.1 什么是动态SQL? 动态SQL就是通过传入的参数不一样,可以组成不同结构的SQL语句. 这种可以根据参数的条件而改变SQL结构的SQL语句,我们称为动态SQL语句.使用动态SQ ...

  8. [转载] 快速学习-Mybatis框架概述

    参考链接: Java在竞争性编程中的快速I/O 第1章 框架概述 1.1 什么是框架 1.1.1 什么是框架 框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互 ...

  9. mybatis mysql schema_学习Mybatis与mysql数据库的示例笔记

    目录结构: pom.xml文件 1 <?xml version="1.0" encoding="UTF-8"?> 2 3 xmlns:xsi=&qu ...

  10. 黑马程序员视频教程学习mybatis框架常用注释SQL语句学习笔记?

    mybatis学习笔记 常用注释增删改查SQL语句 常用注释拓展SQL语句 解决实体类属性和数据库表中的属性名称不相同的问题: mybatis注解之一对一查询: mybatis注解之一对多查询: my ...

最新文章

  1. ​Highmaps网页图表教程之绘图区显示标签显示数据标签定位
  2. 45号:公钥,私钥和数字签名
  3. 转载CopyOnWriteArrayList
  4. heartbeat+drbd+mysql:实现最廉价的高可用组合
  5. 6.Vue Class 与 Style 绑定
  6. gradle 配置java 项目maven 依赖
  7. python怎么用split字符串全部分开_请教一下python怎么用split对一句话拆分两次?...
  8. Matlab命令汇总
  9. 《一张图看懂华为云BigData Pro鲲鹏大数据解决方案》
  10. 一个软件系统哪些可独立实现
  11. Cocoa中Core Data的简单介绍
  12. php是什么电器元件,第三代计算机采用的主要电子元器件是什么
  13. 双向DC/DC变换器设计-硬件主拓扑
  14. FusionStorage原理及组件
  15. 苹果严打iMessage垃圾短信
  16. C语言-OFDM过采样获得中频IF信号
  17. 没人谈论的 3 种从 ChatGPT 赚钱的方法,我测试过的建立被动收入流的行之有效的方法
  18. ElasticSearch底层Lucene的执行流程与细节
  19. Hexo博客框架的搭建与使用
  20. 帝国CMS7.5微信扫码登录插件 帝国cms插件分享

热门文章

  1. 生物信息学入门之基本概念之蛋白质同源检测和折叠识别
  2. echart添加文本_ECharts自定义富文本
  3. Chromium浏览器修改网页显示字体
  4. 2019计算机世界语言排名,2019程序语言排行_2019 年 8 月编程语言排行榜
  5. 三星6818LED驱动的编写
  6. unit04-JavaScript
  7. 读书会招募 | 一起来读《蛤蟆先生去看心理医生》吧
  8. 华为 OSPF特殊区域
  9. 「硬见小百科」几种镜像恒流源电路分析
  10. 小米平板2 android6,小米平板2终于来了MIUI7/Win10双系统