# MyBatis-Plus

# 配置:
# pom.xml
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
2
3
4
5
# application.yaml
#配置端口
server:
port: 8888
spring:
#配置数据源
datasource:
#配置数据源类型
type: com.zaxxer.hikari.HikariDataSource
#配置连接数据库的信息
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/xxx?characterEncoding=utf-8&useSSL=false
username: root
password:
#MyBatis-Plus相关配置
mybatis-plus:
configuration:
#配置日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 启动类加@MapperScan("xxx")
@SpringBootApplication
@MapperScan("指定Mapper接口所在的包")
public class MybatisPlusDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusDemoApplication.class, args);
}
}
2
3
4
5
6
7
# 开干:
# 编写实体类
# 编写service接口
public interface UserService extends IService<User> {
}
2
3
# 编写service实现类
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{
}
2
3
4
# 编写Mapper接口
public interface UserMapper extends BaseMapper<User> {
}
2
3
# 常用注解:
# @TableName
默认操作的表名和实体类型的类名一致
不一致时在实体类上加@TableName("表名")
使用MyBatis-Plus提供的全局配置,为实体类所对应的表名设置默认的前缀,那么就不需要在每个实体类上通过@TableName标识实体类对应的表
mybatis-plus: global-config: db-config: # 设置实体类所对应的表的统一前缀 table-prefix: t_1
2
3
4
5
# @TableId
默认实体类和表中表示主键是id
不是id时(如uid),在实体类中uid属性上通过
@TableId将其标识为主键value属性:
- 指定表中的主键字段,
@TableId("uid")或@TableId(value="uid") - 使用场景:若实体类中主键对应的属性为id,而表中表示主键的字段为uid,此时若只在属性id上添加注解@TableId,则抛出异常Unknown column 'id' in 'field list'
- 指定表中的主键字段,
type属性:
用来定义主键策略:默认雪花算法
值 描述 IdType.ASSIGN_ID(默认) 基于雪花算法的策略生成数据id,与数据库id是否设置自增无关 IdType.AUTO 使用数据库的自增策略,注意,该类型请确保数据库设置了id自增, 配置全局主键策略:
mybatis-plus: global-config: db-config: #配置mp的主键策略为自增 id-type: auto1
2
3
4
5
# @TbaleField
MyBatis-Plus在执行SQL语句时,要保证实体类中的属性名和表中的字段名一致
不一致时:
驼峰:MyBatis-Plus会自动将下划线命名风格转化为驼峰命名风格
非驼峰(如实体类属性
name,表中字段username):在实体类属性上使用@TableField("username")设置属性所对应的字段名public class User { @TableId("uid") private Long id; @TableField("username") private String name; private Integer age; private String email; }1
2
3
4
5
6
7
8
# @TableLogic
逻辑删除:假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录
实现:
在数据库中创建逻辑删除状态列(is_deleted),设置默认值为0
实体类中添加逻辑删除属性
@TableLogic private int isDeleted;1
2
# 条件构造器:

Wrapper: 条件构造抽象类,最顶端父类AbstractWrapper: 用于查询条件封装,生成 sql 的 where 条件QueryWrapper: 查询条件封装UpdateWrapper: Update 条件封装AbstractLambdaWrapper: 使用Lambda 语法LambdaQueryWrapper:用于Lambda语法使用的查询WrapperLambdaUpdateWrapper: Lambda 更新封装Wrapper
# QueryWrapper
组装查询条件
**执行SQL:**SELECT uid AS id,username AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (username LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)
public void test01(){ //查询用户名包含a,年龄在20到30之间,邮箱信息不为null的用户信息 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.like("username","a").between("age",20,30).isNotNull("email"); List<User> users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); }1
2
3
4
5
6
7组装排序条件
**执行SQL:**SELECT uid AS id,username AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 ORDER BY age DESC,id ASC
public void test02(){ //查询用户信息,按照年龄的降序排序,若年龄相同,则按照id升序排序 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.orderByDesc("age").orderByAsc("id"); List<User> users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); }1
2
3
4
5
6
7组装删除条件
**执行SQL:**UPDATE t_user SET is_deleted=1 WHERE is_deleted=0 AND (email IS NULL)
public void test03(){ //删除邮箱地址为null的用户信息 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.isNull("email"); int result = userMapper.delete(queryWrapper); System.out.println(result > 0 ? "删除成功!" : "删除失败!"); System.out.println("受影响的行数为:" + result); }1
2
3
4
5
6
7
8条件的优先级
**执行SQL:**UPDATE t_user SET user_name=?, email=? WHERE is_deleted=0 AND (age > ? AND user_name LIKE ? OR email IS NULL)
public void test04(){ //将(年龄大于20并且用户名中包含有a)或邮箱为null的用户信息修改 UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(); updateWrapper.gt("age",20).like("username","a").or().isNull("email"); User user = new User(); user.setName("Oz"); user.setEmail("test@oz6.com"); int result = userMapper.update(user, updateWrapper); System.out.println(result > 0 ? "修改成功!" : "修改失败!"); System.out.println("受影响的行数为:" + result); }1
2
3
4
5
6
7
8
9
10
11
12补充:
原符号 < <= > >= <> 对应函数 lt() le() gt() ge() ne() less than greater than not equal1
2
3**执行SQL:**UPDATE t_user SET username=?, email=? WHERE is_deleted=0 AND (username LIKE ? AND (age > ? OR email IS NULL))
public void test05(){ //将用户名中包含有a并且(年龄大于20或邮箱为null)的用户信息修改 UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(); updateWrapper.like("username","a").and(i->i.gt("age",20).or().isNull("email")); User user = new User(); user.setName("Vz7797"); user.setEmail("test@ss8o.com"); int result = userMapper.update(user, updateWrapper); System.out.println(result > 0 ? "修改成功!" : "修改失败!"); System.out.println("受影响的行数为:" + result); }1
2
3
4
5
6
7
8
9
10
11
12组装select子句
**执行SQL:**SELECT username,age,email FROM t_user WHERE is_deleted=0
public void test06(){ //查询用户的用户名、年龄、邮箱信息 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.select("username","age","email"); List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper); maps.forEach(System.out::println); }1
2
3
4
5
6
7实现子查询
**执行SQL:**SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (uid IN (select uid from t_user where uid <= 100))
public void test07(){ //查询id小于等于100的用户信息 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.inSql("uid", "select uid from t_user where uid <= 100"); List<User> list = userMapper.selectList(queryWrapper); list.forEach(System.out::println); }1
2
3
4
5
6
7
# UpdateWrapper
UpdateWrapper不仅拥有QueryWrapper的组装条件功能,还提供了set方法进行修改对应条件的数据库信息
public void test08(){
//将用户名中包含有a并且(年龄大于20或邮箱为null)的用户信息修改
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.like("username","a").and( i -> i.gt("age",20).or().isNull("email")).set("email","svip@qq.com");
//int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);
int result = userMapper.update(null, updateWrapper);
System.out.println(result > 0 ? "修改成功!" : "修改失败!");
System.out.println("受影响的行数为:" + result);
}
2
3
4
5
6
7
8
9
# condition
在真正开发的过程中,组装条件是常见的功能,而这些条件数据来源于用户输入,是可选的,因此我们在组装这些条件时,必须先判断用户是否选择了这些条件,若选择则需要组装该条件,若没有选择则一定不能组装,以免影响SQL执行的结果
思路
**执行SQL:**SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (user_name LIKE ? AND age <= ?)
public void test10(){ String username = "a"; Integer ageBegin = null; Integer ageEnd = 30; QueryWrapper<User> queryWrapper = new QueryWrapper<>(); //Children like(boolean condition, R column, Object val); queryWrapper.like(StringUtils.isNotBlank(username), "user_name", username) .ge(ageBegin != null, "age", ageBegin) .le(ageEnd != null, "age", ageEnd); List<User> list = userMapper.selectList(queryWrapper); list.forEach(System.out::println); }1
2
3
4
5
6
7
8
9
10
11
12
# LambdaQueryWrapper
功能等同于QueryWrapper,提供了Lambda表达式的语法可以避免填错列名。
public void test11(){
String username = "a";
Integer ageBegin = null;
Integer ageEnd = 30;
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(StringUtils.isNotBlank(username), User::getName, username)
.ge(ageBegin != null, User::getAge, ageBegin)
.le(ageEnd != null, User::getAge, ageEnd);
List<User> list = userMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}
2
3
4
5
6
7
8
9
10
11
# LambdaUpdateWrapper
功能等同于UpdateWrapper,提供了Lambda表达式的语法可以避免填错列名。
public void test12(){
//将用户名中包含有a并且(年龄大于20或邮箱为null)的用户信息修改
LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.like(User::getName, "a")
.and(i -> i.gt(User::getAge, 20).or().isNull(User::getEmail));
updateWrapper.set(User::getName, "小黑").set(User::getEmail,"abc@atguigu.com");
int result = userMapper.update(null, updateWrapper);
System.out.println("result:"+result);
}
2
3
4
5
6
7
8
9
# 常用插件:
# 分页插件
# 添加配置类MyBatisPlusConfig
@Configuration
@MapperScan("com.atguigu.mybatisplus.mapper")
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
2
3
4
5
6
7
8
9
10
11
# 一般分页
@Test
public void testPage(){
//new Page()中的两个参数分别是当前页码,每页显示数量
Page<User> page = userMapper.selectPage(new Page<>(1, 2), null);
List<User> users = page.getRecords();
users.forEach(System.out::println);
}
2
3
4
5
6
7
# 自定义分页
返回值为Page类型,参数传入一个Page对象,其他就是正常的编写sql
1.在UserMapper接口中定义一个方法
Page<User> selectPageVo(@Param("page") Page<User> page,@Param("age") Integer age);
2.在UserMapper.xml中编写SQL实现该方法
<select id="selectPageVo" resultType="User">
select id,username as name,age,email from t_user where age > #{age}
</select>
2
3
3.测试
@Test
public void testPageVo(){
Page<User> page = userMapper.selectPageVo(new Page<User>(1,2), 20);
List<User> users = page.getRecords();
users.forEach(System.out::println);
}
2
3
4
5
6
# 分页常用数据
- pageNum:当前页的页码
- pageSize:每页显示的条数
- size:当前页显示的真实条数
- total:总记录数
- pages:总页数
- prePage:上一页的页码
- nextPage:下一页的页码
- isFirstPage/isLastPage:是否为第一页/最后一页
- hasPreviousPage/hasNextPage:是否存在上一页/下一页
- navigatePages:导航分页的页码数
- navigatepageNums:导航分页的页码,[1,2,3,4,5]
# MyBatisX插件
# 安装MyBatisX插件
打开IDEA,File-> Setteings->Plugins->MyBatisX,搜索栏搜索MyBatisX然后安装

# 步骤:
新建一个Spring Boot项目引入依赖(创建工程时记得勾选lombok及mysql驱动)
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.1</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>3.5.0</version> </dependency>1
2
3
4
5
6
7
8
9
10
11配置数据源信息
spring: datasource: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false username: root password:1
2
3
4
5
6
7在IDEA中与数据库建立链接

填写数据库信息并保存

找到我们需要生成的表点击右键

填写完信息以后下一步

继续填写信息

大功告成

# 快速生成CRUD
MyBaitsX可以根据我们在Mapper接口中输入的方法名快速帮我们生成对应的sql语句(Alt+Enter)


