一、MyBatis-Plus 简介
MyBatis-Plus 官网 MyBatis-Plus 🚀 为简化开发而生
MyBatis-Plus 是一个功能强大、易于使用的持久层框架,MyBatis-Plus 并不是来替代 MyBatis 的,而是在 MyBatis 的基础上只做出加强,不会对原有的工程产生影响,只需简单配置,即可快速进行单表 CRUD 操作,从而节省大量时间;
二、MyBatis-Plus 快速入手
前置工作:准备一个数据库,并创建出对应表的实体类
drop database if exists student;
create database if not exists student charset = utf8;
use student;
create table grade (id int primary key auto_increment, name varchar(16) not null, chinese int, math int, english int);
insert into grade values (null, 'zhangsan', 80, 90, 75), (null, 'lisi', 69, 75, 50), (null, 'Rci', 90, 98, 95);
@Data
public class Grade {
private int id;
private String name;
private int chinese;
private int math;
private int english;
}
1. 在 pom.xml 中引入 MyBatis-plus 的依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
2. 在 application.yml 文件中进项数据库配置
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/student?characterEncoding=utf8&useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
3. 在 mapper 层中定义接口,继承 BaseMapper 接口
@Mapper
public interface GradeMapper extends BaseMapper<Grade> {
}
4. 测试 CRUD
@SpringBootTest
class GradeMapperTest {
@Autowired
public GradeMapper mapper;
@Test
public void selectById(){
Grade grade = mapper.selectById(1);
System.out.println(grade);
}
@Test
public void insertGrade(){
Grade grade = new Grade();
grade.setName("hhh");
grade.setChinese(97);
grade.setMath(80);
grade.setEnglish(90);
mapper.insert(grade);
}
@Test
public void updateChinese(){
Grade grade = new Grade();
grade.setId(1);
grade.setChinese(100);
mapper.updateById(grade);
}
@Test
public void deleteById(){
mapper.deleteById(4);
}
}
可以看出上述方法全部执行成功;
三、MyBatis-Plus 的常用注解
MyBatis-Plus 如何实现上述操作呢?
上述 GradeMapper 接口在继承 BaseMapper 接口时,传入了一个实体类 Grade,MyBatis-Plus 通过扫描该实体类,基于反射机制获取实体类的信息并作为数据库表信息来进行操作;
上述代码能执行成功的因素之一是,我们约定了数据库表中的字段和 Java 实体类中的属性一一对应(驼峰转换等);
但如果没有遵循此约定,就需要通过注解自己配置;
@TableName:指定表名
@TableName("student")
public class Test {
}
上述 Test 类就对应 student 表;
@TableId:指定表中的主键字段
@TableId(value= "id")
private int studentId;
value 属性用于指定数据库表中主键字段的名称,设置之后 studentId 就与数据库中的主键 id 字段对应;
type 属性指定了主键的生成策略;
AUTO:自增 Id,与 auto_increment 效果一样;
ASSIGN_ID:分布式全局唯一 ID,基于 Twitter 的 Snowflake 算法实现;
ASSIGN_UUID:全局唯一 ID,使用 UUID 生成策略;
NONE:未设置主键类型,不做处理;
INPUT:由程序员通过 set 方法自行输入;
@TableField:指定表中的普通字段
当数据库中的字段名与 Java 实体类的属性名不一致或不符合驼峰转下划线时(还有一种特殊情况 boolean 类型的 is 开头的属性),如果想让其对应上,就需要使用该注解;
@TableField("name")
private String studentName;
这样就指定 Java 类中的 studentName 与 数据库中的 name 字段对应;
四、MyBatis-Plus 的常用配置项
其他配置项在官网中可以查阅到:使用配置 | MyBatis-Plus
五、条件构造器
MyBatis-Plus 的条件构造器是一种简化 SQL 条件查询的工具,它提供了一种流式编程方式,使得构建动态 SQL 查询变得更加简洁和直观;主要有 Wrapper 接口 及其子类实现:
1. QueryWrapper
用于构建查询条件,常用方法:
- eq:等于
- ne:不等于
- gt: 大于
- ge:大于等于
- lt:小于
- le:小于等于
- like:模糊匹配
- orderByAsc / orderByDesc:排序 ......等等方法;
使用示例:查询姓名包含 i 并且英语成绩大于 60 的学生成绩信息;
手写的 SQL:
select * from grade where id like '%i%' and english > 60;
使用条件构造器编写的代码:
@Autowired
public GradeMapper mapper;
@Test
public void testQueryWrapper(){
QueryWrapper<Grade> wrapper = new QueryWrapper<>();
wrapper.like("name", "i").gt("english", 60);
List<Grade> grades = mapper.selectList(wrapper);
System.out.println(grades);
}
执行结果
2. UpdateWrapper
用于构建更新条件,常用方法有:
- set:设置更新字段
- setSql:设置 SQL 片段,可在更新语句中插入任意的 SQL 表达式
- eq:等于(用于条件)
使用示例:将 id 为 2 的学生的语文成绩 + 10 分;
手写 SQL:
update grade set chinese = chinese + 10 where id = 2;
使用条件构造器编写的代码:
@Autowired
public GradeMapper mapper;
@Test
public void testUpdateWrapper(){
UpdateWrapper<Grade> wrapper = new UpdateWrapper<>();
wrapper.setSql("chinese = chinese + 10").eq("id", 2);
mapper.update(null, wrapper);
}
执行结果:
3. LambdaQueryWrapper
类似于 QueryWrapper 但使用 lambda 表达式,类型安全,常用方法与 QueryWrapper 类似
使用示例:查询语文和数学成绩都大于 90 分的学生成绩信息;
@Test
public void testLambdaQueryWrapper(){
LambdaQueryWrapper<Grade> wrapper = new LambdaQueryWrapper<>();
wrapper.gt(Grade::getChinese, 90)
.lt(Grade::getMath, 90);
List<Grade> grades = mapper.selectList(wrapper);
System.out.println(grades);
}
4. LambdaUpdateWrapper
类似于 UpdateWrapper 但使用 lambda 表达式,类型安全,常用方法与 UpdateWrapper 类似
使用示例结合 UpdateWrapper 和 LambdaQueryWrapper;
六、自定义 SQL
使用示例:将 id 为 2,3 的学生的数学成绩更新为 99;
@Autowired
public GradeMapper mapper;
@Test
public void testSQL(){
List<Integer> ids = List.of(2, 3);
int score = 99;
QueryWrapper<Grade> wrapper = new QueryWrapper<>();
wrapper.in("id", ids);
mapper.updateMathById(wrapper, score);
}
GradeWrapper 类的实现(可以使用注解方式,也可以使用 xml 文件的方式)
@Mapper
public interface GradeMapper extends BaseMapper<Grade> {
@Update("update grade set math = #{score} ${ew.customSqlSegment}")
void updateMathById(@Param(Constants.WRAPPER) QueryWrapper<Grade> wrapper, @Param("score") int score);
}
测试结果: