MybatisPlus快速入门
MybatisPlus快速入门
使用第三方组件:
1、导入对应的依赖
2、研究依赖是如何配置
3、代码的编写
4、提高扩展技术能力!
步骤
- 创建数据库
mybatis_plus
创建User表
DROP TABLE IF EXISTS user; 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, 'test1@baomidou.com'), (2, 'Jack', 20, 'test2@baomidou.com'), (3, 'Tom', 28, 'test3@baomidou.com'), (4, 'Sandy', 21, 'test4@baomidou.com'), (5, 'Billie', 24, 'test5@baomidou.com'); 真是开发中,version(乐观锁)、deleted(逻辑删除)、gmt_create、gmt_modified
- 编写项目。初始化项目!使用SpringBoot初始化
导入依赖
<!-- 数据库驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!-- MybatisPlus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.5</version> </dependency>
使用MybatisPlus可以节省大量代码,尽量不要同时导入mybatis和mybatisplus 版本差异!、
连接数据库 这一步和Mybatis相同!
#mysql 5驱动不同 com.mysql.cj.jdbc.Driver spring.datasource.username=root spring.datasource.password=juzi spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?userSSL=false&userUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #mysql 8 驱动不同com.mysql.cj.jdbc.Driver 需要增加时区配置 serverTimezone=GMT%2B8
pojo -dao(之前需要 连接mybatis 配置mapper.xml)-service-controller
使用了Mybatis-Plus 之后
pojo
/** * @author: ZzRG * @version: 1.0 * Date: 2022/6/27 */ @Data @AllArgsConstructor @NoArgsConstructor public class User { private Long id; private String name; private Integer age; private String email; }
mapper接口
/** * @author: ZzRG * @version: 1.0 * Date: 2022/6/27 */ //在对应的Mapper上面继承基本的接口 BaseMapper public interface UserMapper extends BaseMapper<User> { // 所有的curd 操作编写完成了 // 不需要像以前那样写一大堆文件 }
- 注意点:我们需要在主启动器上去扫描 我们的Mapper包下的所有接口
@MapperScan("com.zzrg.xuexi.mapper")
测试类中测试
@SpringBootTest class MybatisPlusApplicationTests { //继承了BaserMapper的所有方法都来自父类, 我们也可以写自己的方法 @Autowired private UserMapper userMapper; @Test void contextLoads() { //Wrapper<T>是一个参数 条件构造器 我们可以先不用设置为null //查询所有用户 List<User> users = userMapper.selectList(null); users.forEach(System.out::println); } }
使用
这里的关键所在
1、SQL谁帮我们写的? MyBatis-Plus都写好了
2、方法哪里来的? MyBatis-Plus 都写好了
配置日志
我们所有的sq|现在是不可见的,我们希望知道它是怎么执行的,所以我们必须要看日志!
#配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
配置完日志之后,在学习时候就需要注意这个自动生成的SQL
CRUD扩展
自动插入
insert插入
@Test
public void testInsert(){
User user = new User();
user.setName("ZzRG");
user.setAge(18);
user.setEmail("123@qq.com");
int insert = userMapper.insert(user);//帮我们自动生成id
System.out.println(insert);//受影响的行数
System.out.println(user);//发现id自动回填
}
数据库插入的id的默认值:全局的唯一id
主键生成策略
默认 ID_WORKER全局唯一id
分布式系统的唯一id生成:
雪花算发:
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是︰使用41bit作为毫秒数,10bit作为机器的ID (5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生4096个ID),最后还有一个符号位,永远是0。
主键自增:@TableId(type = IdType.AUTO)
- 我们需要配置主键自增
- 数据库字段一定要自增!
与其他源码解释
public enum IdType{
AUTO(0),//数据库id自增
NONE(1),//未设置主键
INPUT(2),//手动输入
ID_WORKER(3),//默认的全局唯一id
UUID(4),//全局唯一id uuid
ID_WORKER_STR(5);// ID_WORKER 字符串表示法
}
更新操作
@Test
public void testUpdate(){
User user = new User();
user.setId(5L);
//自动拼接动态sql
user.setAge(15)
user.setEmail("123456@qq.com");
int update = userMapper.updateById(user);
System.out.println(update);
System.out.println(user);
}
}
注意:所有的sql都是自动动态配置!
自动填充
创建时间、修改时间!这些个操作一遍都是自动化完成的,我们不希望手动更新!
阿里巴巴开发手册:所有的数据库表:gmt_create、gmt_modified 几乎所有的表都套配置上!且需要自动化!
方法一:数据库级别(工作中不允许使用)
1、在表中新增字段create_time,update_time
2、再次测试插入方法,我们需要先把实体类同步
private Date createTime;
private Date updateTime;
方式二:代码级别
//字段填充内容
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
编写处理器
package com.zzrg.xuexi.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import javax.xml.crypto.Data;
import java.util.Date;
/**
* @author: ZzRG
* @version: 1.0
* Date: 2022/6/27
*/
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入时的填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("开始插入...");
//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) {
log.info("开始更新...");
this.setFieldValByName("updateTime", new Date(),metaObject);
}
}
插入测试
乐观锁
乐观锁:故名思意十分乐观,它总是认为不会出现问题,无论干什么不去上锁!如果出现了问题,再次更新值测试
悲观锁:故名思意十分悲观,它总是认为总是出现问题,无论干什么都会上锁!再去操作!
- 我们这里主要讲解乐观锁机制!乐观锁实现方式:
- 取出记录时,获取当前version·更新时,带上这个version
- 执行更新时,set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
乐观锁:1、查询,获取版本 version = 1
---线程A
update user set name = "kuangshen", version = version + 1
where id = 2 and version = 1
---线程B 抢先完成 这时候version = 2 线程A执行到的时候version不是1 然后会导致修改失败
update user set name = "kuangshen", version = version + 1
where id = 2 and version = 1
测试一下Mp的乐观锁插件
增加字段
2、实体类上添加相应字段
@Version//乐观锁的注解
private Integer version;
3、注册插件
旧方法:
/**
* @author: ZzRG
* @version: 1.0
* Date: 2022/6/27
*/
//扫描mapper文件夹
@MapperScan("com.zzrg.xuexi.mapper")
@EnableTransactionManagement
@Configuration//配置类
public class MybatisPlusConfig {
//注册乐观锁插件 (老版)
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
新版
/**
* @author: ZzRG
* @version: 1.0
* Date: 2022/6/27
*/
//扫描mapper文件夹
@MapperScan("com.zzrg.xuexi.mapper")
@Configuration//配置类
public class MybatisPlusConfig {
//注册乐观锁插件
/**
* 新版
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
}
@Test
public void testOptimisticLocker(){
//查询用户信息
User user = userMapper.selectById(1L);
//修改信息
user.setName("橘子");
user.setEmail("110110@123.com");
//执行更新
userMapper.updateById(user);
}
@Test
public void testOptimisticLocker2(){
//线程1
//查询用户信息
User user = userMapper.selectById(1L);
user.setName("橘子");
user.setEmail("110110@123.com");
//线程2进行插队操作
User user2 = userMapper.selectById(1L);
user2.setName("橘子21");
user2.setEmail("110110@123.com");
userMapper.updateById(user2);
//自旋锁多次尝试提交!
userMapper.updateById(user);//没有乐观锁就会覆盖插队线程2的值
}
查询操作
//批量查询id
@Test
public void testSelectByBatchId(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
users.forEach(System.out::println);
}
//条件查询Map
@Test
public void testSelectByBatchIds(){
HashMap<String, Object> map = new HashMap<>();
//自定义查询可以当多个条件
map.put("name","ZzRG");
map.put("id",1);
map.put("age",3);
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
分页查询
分页在网站上的使用
1、原始limit进行分页
2、pageHler分页插件
3、MybatisPlus内置分页
1、配置拦截器组件即可
@Configuration
@MapperScan("scan.your.mapper.package")
public class MybatisPlusConfig {
/**
* 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
//旧的
@Bean
public ConfigurationCustomizer configurationCustomizer() {
return configuration -> configuration.setUseDeprecatedExecutor(false);
}
}
2、直接使用Page对象即可
@Test
public void selectPage(){
//分页参数
Page<User> pageParams = new Page<>(1,5);
//执行分页
userMapper.selectPage(pageParams,null);
//查看分页参数成员
System.out.println(pageParams);
}
删除操作
//测试删除
@Test
public void testDeleteById(){
userMapper.deleteById(1L);
}
//批量删除
@Test
public void testDeleteBachId(){
userMapper.deleteBatchIds(Arrays.asList(1L,2L,3L));
}
//通过map删除
@Test
public void testDeleteByMap(){
HashMap<String, Object> map = new HashMap<>();
map.put("id",1L);
map.put("name","橘子");
userMapper.deleteByMap (map);
}
在工作会遇到逻辑删除的问题!
逻辑删除
物理删除:从数据库中直接移除
逻辑删除:再数据库中没有被移除,而是通过一个变量来让他失效! deleted =0 => deleted = 1
管理员可以查看被删除的记录!防止数据的丢失,类似于回收站!
1、在数据表中增加字段 :deleted
2、实体类增加 属性
@TableLogic//逻辑删除
private Integer deleted;
3、配置
//逻辑删除的配置
@Bean
public ISqlInjector sqlInjector(){
return new LogicSqlInjector();
}
#配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
记录依旧在数据,但是值确实已经变化!
执行查询语句!后面会自动拼接。
性能分析插件
我们在平时的开发中,会遇到一些慢sql。测试! druid...
作用∶性能分析拦截器,用于输出每条SQL语句及其执行时间
MP也提供性能分析插件,如果超过这个时间就停止运行!
1、导入插件
/**
* SQL执行效率
* @return
*/
@Bean
@Profile({"dev","test"})//设置dev test 环境开启,保证效率
public PerformanceInterceptor performanceInterceptor(){
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(100);//ms 设置sql执行最大时间 如果超过则不执行
performanceInterceptor.setFormat(true);//是否格式化
return performanceInterceptor;
}
配置环境
#设置开发环境
spring.profiles.active=dev
2、测试使用 只要超出设定最大时间就会抛出异常j!
条件构造器
核心部分!!!
写一些复杂SQL的就可以用它代替!