MyBataisPlus
Mybatis-Plus(简称MP)是一个基于Mybatis框架的增强工具,它在Mybatis的基础上只做增强而不做改变,旨在简化开发、提高效率。Mybatis-Plus提供了一系列的功能和特性,使得开发人员能够更加高效地使用Mybatis进行数据库操作。
使用方式
1.引入依赖
<!– mybatis-plus 的起步依赖 –>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.7</version>
</dependency>
在引导类上加入注解,配置要自动扫描的Mapper
mapper类继承BaseMapper<>就可以使用了
配置文件
mybatis-plus:
type-aliases-package: com.itheima.pojo # 配置MyBatis的别名包
mapper-locations: classpath:mapper/**/*Mapper.xml # 配置MyBatis的mapper文件位置
configuration:
map-underscore-to-camel-case: true # 开启驼峰命名
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 配置MyBatis的日志输出
global-config:
db-config:
id-type: auto # 全局id类型为自增长
update-strategy: not_null # 更新策略:只更新非空字段
各层所要加的东西
Service
extends IService<数据库表对应的实体类名字>
ServiceImpl
extends ServiceImpl<EmpMapper, Emp> implements EmpService
Mapper
extends BaseMapper<数据库表对应的实体类名字>
常见注解
@TableName
- 描述:表名注解,标识实体类对应的表
- 使用位置:实体类
- 示例:
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(“tb_user”)
public class User {
private Long id;
private String name;
private Boolean isMarried;
private Integer order;
private String address;
}
@TableId
- 描述:主键注解,标识实体类中的主键字段
- 使用位置:实体类的主键字段
- 示例
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(“tb_user”)
public class User {
@TableId(value = “id”, type = IdType.AUTO)
private Long id;
private String name;
private Boolean isMarried;
private Integer order;
private String address;
}
- 注解支持两个属性:
属性 | 类型 | 必须指定 | 默认值 | 描述 |
value | String | 否 | “” | 字段描述 |
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) |
这里比较常见的有三种:
- AUTO:利用数据库的id自增长
- INPUT:手动生成id
- ASSIGN_ID:雪花算法生成Long类型的全局唯一id,这是默认的ID策略
@TableField
- 普通字段注解
- 示例
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(“tb_user”)
public class User {
@TableId(value = “id”, type = IdType.AUTO)
private Long id;
@TableField(“username”)
private String name;
@TableField(“is_married”)
private Boolean isMarried;
@TableField(“`order`”)
private Integer order;
@TableField(exist = false)
private String address;
}
一般情况下我们并不需要给字段添加@TableField注解,一些特殊情况除外:
- 成员变量名与数据库字段名不一致
- 成员变量是以isXXX命名,按照JavaBean的规范,MybatisPlus识别字段时会把is去除,这就导致与数据库不符。
- 成员变量名与数据库一致,但是与数据库的关键字冲突。使用@TableField注解给字段名添加转义字符:“
- 成员变量不是数据库中的字段,则需要使用exist表明为false
核心功能
MyBatais主要有三个核心功能:条件构造器、自定义SQL、Service接口
条件构造器
除了新增以外,查询、修改、删除的SQL语句都需要指定where条件。因此BaseMapper中提供的相关方法除了以id作为where条件以外,还支持更加复杂的where条件。
参数中的Wrapper就是条件构造的抽象类,其下有很多默认实现,继承关系如图:
Wrapper的子类AbstractWrapper提供了where中包含的所有条件构造方法:
而QueryWrapper在AbstractWrapper的基础上拓展了一个select方法,允许指定查询字段:
而UpdateWrapper在AbstractWrapper的基础上拓展了一个set方法,允许指定SQL中的SET部分:
接下来,我们就来看看如何利用Wrapper实现复杂查询。
QueryWrapper
无论是修改、删除、查询,都可以使用QueryWrapper来构建查询条件。接下来看一些例子: 查询:查询姓名中包含“李”且薪资大于等于5000的员工的 id, name, phone, salary字段。代码如下:
首先让EmpMapper继承自BaseMapper:
@Mapper
public interface EmpMapper extends BaseMapper<Emp> {
}
为了方便测试,咱们使用单元测试学习QueryWrapper的使用:
package com.itheima;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.mapper.EmpMapper;
import com.itheima.pojo.Emp;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class TestQueryWrapper {
@Autowired
private EmpMapper empMapper;
@Test
public void testQueryWrapper() {
// 查询姓名中包含“李”且薪资大于等于5000的员工的 id, name, phone, salary字段
QueryWrapper<Emp> queryWrapper = new QueryWrapper<>();
queryWrapper.like(“name”, “李”)
.ge(“salary”, 5000)
.select(“id”, “name”, “phone”, “salary”);
List<Emp> emps = empMapper.selectList(queryWrapper);
emps.forEach(System.out::println);
}
}
更新:更新名为”李忠”的员工的薪水为18000,代码如下:
@Test
public void testUpdateByQueryWrapper() {
// 更新名为”李忠”的员工的薪水为18000
Emp emp = new Emp();
emp.setSalary(18000);
QueryWrapper<Emp> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(“name”, “李忠”);
empMapper.update(emp, queryWrapper);
}
UpdateWrapper
更新:更新id为5, 6, 7的员工的薪水,加2000,代码如下:
update emp set salary = salary + 2000 where id in (5, 6, 7);
@Test
public void testUpdateWrapper() {
// 更新id为5, 6, 7的员工的薪水,加2000
UpdateWrapper<Emp> updateWrapper = new UpdateWrapper<>();
updateWrapper.in(“id”, 5, 6, 7)
.setSql(“salary = salary + 2000”);
empMapper.update(updateWrapper);
}
LambdaQueryWrapper
无论是QueryWrapper还是UpdateWrapper在构造条件的时候都需要写死字段名称,这在编程规范中显然是不推荐的。 那怎么样才能不写字段名,又能知道字段名呢?
其中一种办法是基于变量的gettter方法结合反射技术来实现,因此我们只要将条件对应的字段的getter方法传递给MybatisPlus,它就能计算出对应的变量名了。而传递方法可以使用JDK8中的方法引用和Lambda表达式。 因此MybatisPlus又提供了一套基于Lambda的Wrapper,包含两个:
- LambdaQueryWrapper
- LambdaUpdateWrapper
分别对应QueryWrapper和UpdateWrapper
其使用方式如下:
@Test
public void testLambdaUpdateWrapper() {
// 更新id为5, 6, 7的员工的薪水,加2000
LambdaUpdateWrapper<Emp> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.in(Emp::getId, 5, 6, 7)
.setSql(“salary = salary + 2000”);
empMapper.update(updateWrapper);
}
自定义SQL
在开发时需要遵守开发规范,不能将SQL写在Service中可以将条件放入service中然后在Mapper中用条件进行拼接
List<Long> ids = List.of(5L, 6L, 7L);
int amount = 2000;
//构建修改条件
LambdaQueryWrapper<Emp> wrapper=new LambdaQueryWrapper<Emp>().in(Emp::getId,ids);
//自定义SQL方法调用
this.empMapper.updateBalanceByIds(wrapper,amount);
void updateBalanceByIds(@Param(“ew”) LambdaQueryWrapper<Emp> wrapper,@Param(“amount”) int amount);
<update id=”updateBalanceByIds”>
update emp set salary =salary -#{amount} ${ew.customSqlSegment}
</update>
Service接口
MybatisPlus不仅提供了BaseMapper,还提供了通用的Service接口及默认实现,封装了一些常用的service模板方法。 通用接口为IService,默认实现为ServiceImpl,其中封装的方法可以分为以下几类:
- save:新增
- remove:删除
- update:更新
- get:查询单个结果
- list:查询集合结果
- count:计数
- page:分页查询
基本的增删改查
我们先来看下基本的CRUD接口,新增
- save是新增单个元素
- saveBatch是批量新增
- saveOrUpdate是根据id判断,如果数据存在就更新,不存在则新增
- saveOrUpdateBatch是批量的新增或修改
删除:
- removeById:根据id删除
- removeByIds:根据id批量删除
- removeByMap:根据Map中的键值对为条件删除
- remove(Wrapper<T>):根据Wrapper条件删除
- ~~removeBatchByIds~~:暂不支持
修改:
- updateById:根据id修改
- update(Wrapper<T>):根据UpdateWrapper修改,Wrapper中包含set和where部分
- update(T,Wrapper<T>):按照T内的数据修改与Wrapper匹配到的数据
- updateBatchById:根据id批量修改
Get:
- getById:根据id查询1条数据
- getOne(Wrapper<T>):根据Wrapper查询1条数据
- getBaseMapper:获取Service内的BaseMapper实现,某些时候需要直接调用Mapper内的自定义SQL时可以用这个方法获取到Mapper
List:
- listByIds:根据id批量查询
- list(Wrapper<T>):根据Wrapper条件查询多条数据
- list():查询所有
Count:
- count():统计所有数量
- count(Wrapper<T>):统计符合Wrapper条件的数据数量
Comments NOTHING