MyBatisPlus
概述
MyBatisPlus官网:https://baomidou.com/
入门案例
建表、加数据
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)
);
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');
IDEA新建工程
SpringBoot选用2.2.1.RELEASE版本
POM依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--lombok用来简化实体类-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
配置文件(关键)
配置文件内容
mysql5
#mysql数据库连接
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus
spring.datasource.username=root
spring.datasource.password=123456
mysql8以上(spring boot 2.1)注意:driver和url的变化
2.1以上版本默认是用MySQL8的驱动
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
主要的区别就是新版本MySQL8在路径中多了个CJ、URL后面加入了时区
注意:
1、这里的 url 使用了 ?serverTimezone=GMT%2B8 后缀,因为Spring Boot 2.1 集成了 8.0版本的jdbc驱动,这个版本的 jdbc 驱动需要添加这个后缀,否则运行测试用例报告如下错误:
java.sql.SQLException: The server time zone value is unrecognized or represents more
2、这里的 driver-class-name 使用了 com.mysql.cj.jdbc.Driver ,在 jdbc 8 中 建议使用这个驱动,之前的 com.mysql.jdbc.Driver 已经被废弃,否则运行测试用例的时候会有 WARN 信息
导入其他类
导入实体类,Mapper等等内容
记得加入@Mapper,MP配置类加入@Configuration注解
测试一下
遍历表内容
SQL输出日志
在XML中加入日志配置,在控制台会输出
# MP 日志输出
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
主键策略
如果用自增,那么数据库中对应字段也要开启自增
(1)ID_WORKER
MyBatis-Plus默认的主键策略是:ID_WORKER 全局唯一ID
(2)自增策略
- 要想主键自增需要配置如下主键策略
- 需要在创建数据表的时候设置主键自增(自增出来的ID一定比之前的ID要大,但是这种大体现在具体的数值上,方便后续排序。也就是后面自增出来的一定比前面自增的ID要大)
- 实体字段中配置 @TableId(type = IdType.AUTO)
@TableId(type = IdType.AUTO)
private Long id;
其它主键策略:分析 IdType 源码可知,是一个枚举类
public enum IdType {
/**
* 数据库ID自增
*/
AUTO(0),
/**
* 该类型为未设置主键类型
*/
NONE(1),
/**
* 用户输入ID
* 该类型可以通过自己注册自动填充插件进行填充
*/
INPUT(2),
/**
* 全局唯一ID
*/
ASSIGN_ID(3),
/**
* 全局唯一ID (UUID)
*/
ASSIGN_UUID(4),
/** @deprecated */
@Deprecated
ID_WORKER(3),
/** @deprecated */
@Deprecated
ID_WORKER_STR(3),
/** @deprecated */
@Deprecated
UUID(4);
private final int key;
private IdType(int key) {
this.key = key;
}
public int getKey() {
return this.key;
}
}
修改和分页
修改操作
分页查询
创建配置类
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
测试selectPage分页
IPage是page对象的接口,接收分页查询结果也是完全可以的
测试:最终通过page对象获取相关数据
删除
根据ID精确删
@Test
public void testDeleteById(){
int result = userMapper.deleteById(目标ID);
System.out.println(result);
}
批量删
@Test
public void testDeleteBatchIds() {
//int result = userMapper.deleteBatchIds(ID集合,集合就可以自动遍历,Collection接口下的);
int result = userMapper.deleteBatchIds(Arrays.asList(8, 9, 10));
System.out.println(result);
}
逻辑删除
物理删除:真删,这行数据直接干掉,彻底无了
逻辑删除:假删,字段加入标志,比如1是代表形式上没删除,0是形式上已经删除。在查询的时候0就跳过查不出来,假装自己被删了。
具体步骤
(1)数据库中添加 deleted字段
建议设置一下默认值
ALTER TABLE `user` ADD COLUMN `deleted` boolean
(2)实体类添加deleted字段
在逻辑删除字段上加入 @TableLogic 注解
@TableLogic
private Integer deleted;
(3)application.properties 加入配置
此为默认值,如果你的默认值和mp默认的一样,该配置可无
mybatis-plus.global-config.db-config.logic-delete-value=1 #默认被删除了就是1
mybatis-plus.global-config.db-config.logic-not-delete-value=0 #默认没删除了就是0
(4)测试逻辑删除
- 测试后发现,数据并没有被删除,deleted字段的值由0变成了1
- 测试后分析打印的sql语句,是一条update
- 注意:被删除数据的deleted 字段的值必须是 0(也就是没被删除,这时才能被删),才能被选取出来执行逻辑删除的操作
条件构造器
MP提供的条件构造器,输入一些条件就可以快速进行单表的增删改查操作
注意,是单表。多表是无法操作的,只能写SQL语句
类图
Wrapper : 条件构造抽象类,最顶端父类
AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
QueryWrapper : Entity 对象封装操作类,不是用lambda语法
UpdateWrapper : Update 条件封装,用于Entity对象更新操作
AbstractLambdaWrapper : Lambda 语法使用 Wrapper统一处理解析 lambda 获取 column。
LambdaQueryWrapper :看名称也能明白就是用于Lambda语法使用的查询Wrapper
LambdaUpdateWrapper : Lambda 更新封装Wrapper
注意:以下条件构造器的方法入参中的 column
均表示数据库字段
QueryWrapper使用
ge、gt、le、lt
ge:大于
gt:大于等于
le:小于
lt:小于等于
@Test
public void testSelect() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.ge("参数表字段名称", 参数值);//其余同理
queryWrapper.ge("age", 28);//age字段大于28的
queryWrapper.gt("age", 28);//age字段大于等于28的
queryWrapper.le("age", 28);//age字段小于28的
queryWrapper.lt("age", 28);//age字段小于等于28的
List<User> users = userMapper.selectList(queryWrapper);
System.out.println(users);
}
eq、ne
eq:等于
ne:不等于
注意:seletOne返回的是一条实体记录,当出现多条时会报错
@Test
public void testSelectOne() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "Tom");//name字段等于Tom的
queryWrapper.eq("name", "Tom");//name字段不等于Tom的
User user = userMapper.selectOne(queryWrapper);
System.out.println(user);
}
SELECT id,name,age,email,create_time,update_time,deleted,version FROM user WHERE deleted=0 AND name = ?
like、likeLeft、likeRight
like:模糊匹配
likeLeft:左侧模糊匹配
likeRight:右侧模糊匹配
selectMaps返回Map集合列表
@Test
public void testSelectMaps() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name", "e");//只要是在name字段包含e的,就算匹配到位相当于(%e%)
queryWrapper.likeLeft("email", "t");//只要是在email字段包以t结尾的,就算匹配到位相当于(t%)
queryWrapper.likeRight("email", "t");//只要是在email字段包以t开头的,就算匹配到位相当于(%t)
List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);//返回值是Map列表
maps.forEach(System.out::println);
}
SELECT id,name,age,email,create_time,update_time,deleted,version
FROM user WHERE deleted=0 AND name LIKE ? AND email LIKE ?
orderByDesc、orderByAsc
orderByDesc:降序
orderByAsc:升序
@Test
public void testSelectListOrderBy() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("id");//按字段降序
queryWrapper.orderByAsc("id");//按字段升序
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
SELECT id,name,age,email,create_time,update_time,deleted,version
FROM user WHERE deleted=0 ORDER BY id DESC
LambdaQueryWrapper 使用
与QueryWrapper相比,LambdaQueryWrapper支持Lambda表达式
里面内置的方法和QueryWrapper 内的方法保持一致
@Test
public void testLambdaQuery() {
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getAge,30);//对象::get属性 是Java8的写法
queryWrapper.like(User::getName,"张");
List<User> list = userMapper.selectList(queryWrapper);
System.out.println(list);
}
SELECT id,name,age,email,create_time,update_time,deleted,version
FROM user WHERE deleted=0 AND age = ? AND name LIKE ?
MyBatisPlus封装Service层
创建service
public interface UserService extends IService<User> {
}
创建service实现类
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
底层封装了注入Mapper过程
方法调用测试
@SpringBootTest
class TestApplicationTests {
//注入service
@Autowired
private UserService userService;
//查询表所有数据
@Test
public void findAll() {
List<User> userList = userService.list();
for (User user:userList) {
System.out.println(user);
}
}
}