springboot 整合mybatisplus

1.导入依赖

<!--mybatis-plus 是自己开发的,并非官方!-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

说明:我们使用mybatis-plus可以节省我们大量的代码,尽量不要同时带入mybatis跟mybatis-plus,可能会产生冲突

在这里插入图片描述

连接数据库! 这一步和mybatis相同

url字段中 设置时区:serverTime=GMT%2b8 (%2b 就是+的意思,这里是指加8个小时,以北京东八区为准)

# mysql 8 驱动不同,需要增加时区设置
spring.datasource.username=root
spring.datasource.password=83821979Zs
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2b8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

2.  pojo-dao(连接mybatis,配置mapper.xml文件)-service-controller
dao层

mapper接口

/**
* @DATE: 2021/3/3 0003 23:24
* @Author: 小爽帅到拖网速
*/

// 在对应的Mapper上面实现基本的接口BaseMapper
@Repository // 代码持久层
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 所有的CRUD操作都已经编写完成了
// 你不需要像以前那样配置一大堆文件了
}

3、配置日志

我们所有的Sql现在是不可见的,我们希望知道它是怎么执行的,所以我们必须要看日志!

# 配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

6.@TableId(type = IdType.AUTO)

其余的源码解释

public enum IdType {
AUTO(0), // 数据库id自增
NONE(1), // 未设置主键
INPUT(2), // 手动输入
ID_WORKER(3), // 默认的全局id
UUID(4), // 全局唯一id
ID_WORKER_STR(5); // ID_WORKER 字符串表示法
}

改为手动输入之后,就需要自己配置id

public class User {

// 对应数据库的主键(uuid、自增id、雪花算法、redis、zookeeper)
@TableId(type = IdType.INPUT) // 默认方案
private Long id;
private String name;
private Integer age;
private String email;
}

7.自动填充

实体类字段属性上需要增加注解

// 字段添加填充内容
@TableField(fill = FieldFill.INSERT)
private Date create_time;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date update_time;
1
2
3
4
5
编写处理器来处理这个注解即可!

由于这个处理器在Springboot下面, mybatis会自动处理我们写的所有的处理器

当我们执行插入操作的时候,自动帮我们通过反射去读取哪边有对应注解的字段,从而把处理器代码插入成功,会自动帮我把createTime,updateTime插入值

package com.shuang.handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.logging.Log;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
* @DATE: 2021/3/4 0004 21:43
* @Author: 小爽帅到拖网速
*/

@Slf4j
@Component // 一定不要忘记把处理器加到IOC容器中!
public class MyMetaObjectHandler implements MetaObjectHandler {

// 插入时的填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill.....");
// setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
// 更新时的填充策略
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}

8.乐观锁

测试Mybatis-Plus的乐观锁实现

1、给数据库中增加version字段

实体类加对应的字段

//乐观锁version注解
@Version
private Integer version;
1
2
3
3、注册组件

// 这个扫描本来是在我们MybatisPlusApplication 主启动类中,现在我们把它放在配置类中
// 扫描mapper文件夹
@MapperScan("com.shuang.mapper")
@EnableTransactionManagement // 自动开启事务管理
@Configuration // 配置类

public class MybatisPlusConfig {

// 注册乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
}
}

// 测试乐观锁成功
@Test
public void testVersionSuccess(){
// 1. 查询用户信息
User user = userMapper.selectById(1L);
// 2. 修改用户信息
user.setName("fan");
user.setAge(24);
// 3. 执行更新操作
userMapper.updateById(user);
}

// 测试乐观锁失败!多线程下
@Test
public void testVersionFall(){
// 线程1
User user1 = userMapper.selectById(1L);
user1.setName("fan111");
user1.setAge(14);

// 线程2
User user2 = userMapper.selectById(1L);
user2.setName("fan222");
user2.setAge(24);
userMapper.updateById(user2);

//自旋锁来多次尝试提交!
userMapper.updateById(user1); //如果没有乐观锁就会覆盖插队线程的值
}
}

9.分页查询
分页在网站使用的十分之多!

原始的limit 进行分页
pageHepler 第三方插件
Mybatis-Plus其实也内置了分页插件!
如何使用分页插件

1、拦截器组件即可

public class MybatisPlusConfig {
// 分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {

return new PaginationInterceptor();
}
}

2、直接使用Page对象即可!

// 测试分页查询
@Test
public void testPage(){
// 参数1 当前页 ;参数2 页面大小
Page<User> page = new Page<>(1,5);
userMapper.selectPage(page,null);

page.getRecords().forEach(System.out::println);
System.out.println("getCurrent()"+page.getCurrent());
System.out.println("page.getSize()"+page.getSize());
System.out.println("page.getTotal()"+page.getTotal());
}

 

 

 获取总条数!

10.逻辑删除
物理删除:从数据库中直接移除

逻辑删除:再数据库中没有被移除,而是通过一个变量来让它失效! deleted = 0 => deleted = 1

说明:

只对自动注入的sql起效:

插入: 不作限制
查找: 追加where条件过滤掉已删除数据,且使用 wrapper.entity 生成的where条件会忽略该字段
更新: 追加where条件防止更新到已删除数据,且使用 wrapper.entity 生成的where条件会忽略该字段
删除: 转变为 更新
例如:

删除: update user set deleted=1 where id = 1 and deleted=0
查找: select id,name,deleted from user where deleted=0
字段类型支持说明:

支持所有数据类型(推荐使用 Integer,Boolean,LocalDateTime)
如果数据库字段使用datetime,逻辑未删除值和已删除值支持配置为字符串null,另一个值支持配置为函数来获取值如now()
附录:

逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案,但实际就是删除。
如果你需要频繁查出来看就不应使用逻辑删除,而是以一个状态去表示。
管理员可以查看被删除的记录! 防止数据的丢失,类似于回收站!

测试一下:

在数据表中增加一个deleted字段

 

实体类中增加字段

// 逻辑删除注解
@TableLogic
private Integer deleted;
1
2
3
配置

public class MybatisPlusConfig {
// 逻辑删除组件
@Bean
public ISqlInjector iSqlInjector(){
return new LogicSqlInjector();
}
}

# 配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value= 1
mybatis-plus.global-config.db-config.logic-not-delete-value= 0
1
2
3
测试一下删除!

10条件构造器

十分重要:Wrapper

非空 大于
@Test
void contextLoads(){
// 查询 name 不为空的用户,并且邮箱不为空的用户,年龄大于等于20
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.isNotNull("name")
.isNotNull("email")
.ge("age",20);

查询一个名字
@Test
void getOneName(){
// 查询名字 小爽帅到拖网速
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name","小爽帅到拖网速"); // 查询一个数据
userMapper.selectOne(wrapper);
}

userMapper.selectList(wrapper).forEach(System.out::println);
}

使用between
@Test
void betweenTest(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.between("age",25 ,100);
Integer count = userMapper.selectCount(wrapper);// 查询结果数
System.out.println(count);
}

连接查询(内查询)
// 内查询
@Test
void innerJoinTest(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
// id 在子查询中查找出来的
wrapper.inSql("id","select id from user where id<3");
List<Object> users = userMapper.selectObjs(wrapper);
users.forEach(System.out::println);
}

升序排序

过id进行排序
@Test
void orderById(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
//
wrapper.orderByDesc("id");
List<Object> objects = userMapper.selectObjs(wrapper);
objects.forEach(System.out::println);
}


# mybatis-plus相关配置
mybatis-plus:
# xml扫描,多个目录用逗号或者分号分隔(告诉 Mapper 所对应的 XML 文件位置)
mapper-locations: classpath:**/*Mapper.xml
# 以下配置均有默认值,可以不设置
global-config:
#主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
id-type: 0
#字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
field-strategy: 2
#驼峰下划线转换
db-column-underline: true
#刷新mapper 调试神器
refresh-mapper: false
#数据库大写下划线转换
#capital-mode: true
#序列接口实现类配置
#key-generator: com.baomidou.springboot.xxx
#逻辑删除配置
#logic-delete-value: 0 # 逻辑已删除值(默认为 1)
#logic-not-delete-value: 1 # 逻辑未删除值(默认为 0)
#自定义填充策略接口实现
# meta-object-handler: com.zhengqing.config.MyMetaObjectHandler
#自定义SQL注入器
#sql-injector: com.baomidou.springboot.xxx
configuration:
# 是否开启自动驼峰命名规则映射:从数据库列名到Java属性驼峰命名的类似映射
map-underscore-to-camel-case: true
cache-enabled: false
# 如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段
# call-setters-on-nulls: true
# 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 解决oracle更新数据为null时无法转换报错,mysql不会出现此情况
jdbc-type-for-null: 'null'




posted @ 2021-07-18 18:29  再小的帆也能远航。  阅读(83)  评论(0编辑  收藏  举报