背景
MyBatis作为Java世界中最受欢迎的持久层框架之一,经常在各种项目上被使用,以映射的方式实现了数据库CRUD等功能。然而,随着技术的发展和项目的复杂性增加,开发者对数据库操作提出了更高的要求。在此背景下,MyBatis Plus应运而生,它不仅继承了MyBatis的优点,还通过内置CRUD操作、分页插件、性能分析插件等功能,进一步简化了数据库操作,提高了开发效率。
MyBatis Plus的出现,为Java开发者提供了一种更加便捷、高效的数据库操作方式。它不仅简化了数据库操作的复杂性,还通过一系列的功能扩展,帮助开发者更加快速地完成开发任务。在本文中,我们将详细介绍MyBatis Plus的使用方式。
MyBatisPlus的官方文档:https://baomidou.com/
使用方式
环境
- Java
- Spring
- Mysql
- JPA
- Gradle
引入依赖
implementation 'com.baomidou:mybatis-plus-boot-starter:3.5.5'
单表查询
准备数据
- 首先定义一下数据结构的Java数据类
@NoArgsConstructor
@AllArgsConstructor
@Data
@TableName(value = "user")
public class UserEntity {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
@EnumValue
private Gender gender;
private Integer classNo;
}
注释
都是MybatisPlus定义的,分别表示表明、表主键、表中的枚举字段。@TableName
和
@TableId
和
@EnumValue
- 根据Java类创建表结构
create table user
(
id bigint auto_increment,
name varchar(20) not null,
gender varchar(20) not null,
class_no int not null,
constraint user_pk
primary key (id)
);
- 插入假数据
insert into user(name, gender, class_no)
VALUES ('Tom', 'MALE', 1),
('Alice', 'FEMALE', 1),
('MARTIN', 'MALE', 2),
('PENNY', 'FEMALE', 2);
- 定义MyBatisPlus的Mapper
@Component
public interface UserMapper extends BaseMapper<UserEntity> {
}
BaseMapper是MybatisPlus提供的,只需要继承这个类,UserEntity就具有了CRUD的能力。在无需使用MyBatis的xml配置的情况下,可以直接使用BaseMapper提供的方法对user单表做一些简单操作。
- 注入分页配置(如果需要分页功能)
@Configuration
@MapperScan("com.example.mybatis.mapper")
public class PageConfig {
@Bean
public PaginationInnerInterceptor paginationInnerInterceptor() {
return new PaginationInnerInterceptor();
}
}
实现单表查询
查询全量数据
@Test
void should_get_all_user() {
List<UserEntity> users = userMapper.selectList(null);
users.forEach(user -> {
System.out.printf("姓名%s的同学是%d班的学生%n/n", user.getName(), user.getClassNo());
});
}
输出结果:
根据条件进行数据查询
@Test
void should_get_all_user_by_class_no() {
QueryWrapper<UserEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("class_no", 1);
List<UserEntity> users = userMapper.selectList(queryWrapper);
users.forEach(user -> {
System.out.printf("1班的同学有:%s\n", user.getName());
});
}
输出结果:
分页查询
@Test
void should_get_all_user_pageable() {
Page<UserEntity> page = new Page<>(1, 2);
Page<UserEntity> userPageable = userMapper.selectPage(page, null);
System.out.printf("总共%d页数据,下述是第%d页的数据:\n", userPageable.getPages(), userPageable.getCurrent());
userPageable.getRecords().forEach(user -> {
System.out.printf("姓名%s的同学是%d班的学生%n", user.getName(), user.getClassNo());
});
}
输出结果:
多表联查
准备数据
- 首先定义一下数据结构的Java数据类
@NoArgsConstructor
@AllArgsConstructor
@Data
@TableName(value = "user")
public class UserEntity {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
@EnumValue
private Gender gender;
private Integer classNo;
}
@NoArgsConstructor
@AllArgsConstructor
@Data
@TableName(value = "score")
public class ScoreEntity {
@TableId(type = IdType.AUTO)
private Long id;
@TableField(value = "user_id")
private Long userId;
@EnumValue
private CourseType type;
@OrderBy(sort = Short.MIN_VALUE)
private Integer score;
private LocalDateTime createdTime;
}
注释``@OrderBy是MybatisPlus定义的,表示根据该字段进行排序。
- 根据Java类创建表结构
create table user
(
id bigint auto_increment,
name varchar(20) not null,
gender varchar(20) not null,
class_no int not null,
constraint user_pk
primary key (id)
);
create table score
(
id bigint auto_increment,
user_id bigint not null,
type varchar(20) not null,
score int not null,
created_time datetime default now() not null,
constraint score_pk
primary key (id)
);
- 插入假数据
insert into user(name, gender, class_no)
VALUES ('Tom', 'MALE', 1),
('Alice', 'FEMALE', 1),
('MARTIN', 'MALE', 2),
('PENNY', 'FEMALE', 2);
insert into score(user_id, type, score, created_time)
VALUES (1, 'MATH', 85, now()),
(1, 'ENGLISH', 80, now()),
(1, 'SCIENCE', 90, now()),
(2, 'MATH', 80, now()),
(2, 'ENGLISH', 93, now()),
(2, 'SCIENCE', 85, now()),
(3, 'MATH', 80, now()),
(3, 'ENGLISH', 90, now()),
(3, 'SCIENCE', 90, now()),
(4, 'MATH', 99, now()),
(4, 'ENGLISH', 85, now()),
(4, 'SCIENCE', 85, now());
- 定义MyBatisPlus的Mapper
@Component
public interface UserMapper extends BaseMapper<UserEntity> {
}
@Component
public interface ScoreMapper extends BaseMapper<ScoreEntity> {
}
- 定义多表联查后的结果的数据结构
@NoArgsConstructor
@AllArgsConstructor
@Data
public class UserScoreDto {
private Long id;
private String name;
private Gender gender;
private Integer classNo;
private List<ScoreEntity> scores;
}
实现多表联查
获取全量数据
@Component
public interface ScoreMapper extends BaseMapper<ScoreEntity> {
@Select("select * from score where user_id = #{userId}")
List<ScoreEntity> selectByUserId(@Param("userId") Long userId);
}
@Component
public interface UserMapper extends BaseMapper<UserEntity> {
@Select("SELECT * from user")
@Results({
@Result(id = true, column = "id", property = "id"),
@Result(column = "name", property = "name"),
@Result(column = "classNo", property = "classNo"),
@Result(property = "scores", column = "id",
javaType = List.class,
many = @Many(select = "com.example.mybatis.mapper.ScoreMapper.selectByUserId"))
})
List<UserScoreDto> selectUsersWithScores();
}
上述的程序分别定义了user和score的查询语句。
首先
定义的是根据user_id查询的方法,这个方法会在多表联查的时候被调用。ScoreMapper
接着
方法后的结果。UserMapper
就定义了获取所有user与score的方法。因为user和score是一对多的关系,所以
score
这个
@Result
是一个many的数据结构,结果就是使用
column = "id"
调用
selectByUserId
@Test
void should_get_all_user_with_scores() {
List<UserScoreEntity> users = userMapper.selectUsersWithScores();
users.forEach(user -> {
System.out.printf("%s是%d班的学生,总成绩是:%d\n", user.getName(), user.getClassNo(),
user.getScores().stream().map(ScoreEntity::getScore).reduce(Integer::sum).orElse(0));
});
}
输出结果:
优点
通过上述的实例,我们可以发现相较于原始的Mybatis,MybatisPlus主要有以下几个方面的优势:
首先,MybatisPlus提供了更为丰富的API,极大地简化了开发者的编码工作。无需再编写繁琐的Mapper接口和XML映射文件,MybatisPlus通过注解和Lambda表达式等特性,让开发者能够更加专注于业务逻辑的实现。
其次,MybatisPlus内置了许多实用的功能,如主键生成策略、乐观锁、分页插件等,这些功能在Mybatis中需要开发者自行实现或集成第三方插件。MybatisPlus的这些内置功能不仅提高了开发效率,同时也减少了出错的可能性。
此外,MybatisPlus还提供了更加智能的CRUD操作,使得数据库操作变得更加简洁和高效。通过简单的方法调用,就可以完成复杂的数据库操作,这对于追求高效开发的团队来说,无疑是一个巨大的优势。
留言