狂神Mybatis-Plus学习视频
早就想学了,没办法事情太多就只能鸽到现在
听前辈们说还是挺好学的,不知道学起来会怎么样
随看随记
简介
- MyBatis-Plus 是搭配MyBatis一起使用的。
快速入门
跟随视频和官方文档进行学习
- 正常使用Mybatis的写代码顺序
- 编写实体类 POJO层
- 编写mapper DAO层
- 调用mapper Service层
- Mybatis-Plus的顺序类似,主要区别在于在于Dao层的编写上,可以同同其减少大量代码的编写
spring: datasource: username: root password: 123456 url: jdbc:mysql://localhost:3306/mybatisplus?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC driver-class-name: com.mysql.cj.jdbc.Driver
- 实体类的编写 很普通的使用@Lombok的编写
@Data @AllArgsConstructor @NoArgsConstructor public class User { private Long id; private String name; private Integer age; private String email; }
- mapper接口的编写 通过添加@Mapper注释,来对Mapper接口进行装配 从而避免了在启动类添加@MapperScan进行Mapper扫描
- 这里的重点就是不要忘记接口UserMapper继承BaseMapper接口
@Mapper @Repository public interface UserMapper extends BaseMapper<User> {}
- 添加测试类
@Autowired UserMapper userMapper; @Test void contextLoads() { List<User> users = userMapper.selectList(null); System.out.println(users); }
日志配置
- 控制台输出
mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
- 我查了一下Mybatis使用log4j 没找到能用的,如有需要到时候再找吧。
主键生成策略与雪花算法
-
@Test public void insertTest(){ User user = new User(); user.setAge(1); user.setEmail("qweqweqwe@qq.com"); user.setName("paleatta"); int flag = userMapper.insert(user); System.out.println(flag); }
- 分布式系统唯一ID生成方案汇总
- 可以通过以下的方式对主键ID的标记方式进行设定
其中包括@TableId(type = IdType.ASSIGN_ID) private Long id;
- 默认为NONE
- AUTO(0), 自增主键填入 注意在中用这个的时候要把数据中的主键自增也选择上
- INPUT(2), 自行主键插入 需要手动加主键,否则赋值为null
- ASSIGN_ID(3),雪花算法主键插入 结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。
- ASSIGN_UUID(4),UUID主键插入
- ID_WORKER(3),雪花算法主键插入 已过时
- UUID(4);UUID主键插入 已过时
更新操作
-
@Test public void updateTest(){ User user = new User(); user.setId(1L); user.setAge(1); user.setEmail("qweqweqwe@qq.com"); user.setName("paleatta"); int flag = userMapper.updateById(user); System.out.println(flag); }
- MyBatis-Plus 会根据传入的对象进行自动匹配到其需要更新的字段
- 当改成这样后
public void updateTest(){ User user = new User(); user.setId(1L); user.setAge(1); // user.setEmail("qweqweqwe@qq.com"); user.setName("paleatta"); int flag = userMapper.updateById(user); System.out.println(flag); }
- 会实现自动匹配
自动填充
- 首先说一点,我把handle放错文件夹了,我找这个错误找了半天,我一直以为是那个语句的问题。
- 实体类添加@TableField注解
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
- 在和controller同级建文件夹,将对应的值进行填充
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("start insert fill ....");
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
- 从我调试中发现,Mybatis-Plus是根据INSERT 和INSERT_UPDATE标签来对是否进入处理器进行处理的,如果有赋值,就直接赋值,如果没有就直接赋值为null。
乐观锁处理
- 乐观锁是一种对于高并发的处理 可以理解成将version作为一个flag,每次运行时会修改这个flag,通过判断这个flag的修改程度来判断是否触发了高并发问题。
- 其处理方式为 version只是一个代称,指的是被@Version注解的变量
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
- 在最新版的开发档案中有点问题,开发档案中只给了@version,但是没给配置类需要在增加MybatisPlus的配置类,并配置以下信息。 就可以使用了
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor optimisticLockerInnerInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
- 通过乐观锁实现的操作都必须是在已经有查询记录的基础上才可以使用,即如果使用,必须先找出对应ID的记录(selectById),对updateById(user) 与 update(entity, wrapper) 方法有效。支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime。
@Test
public void updateTest(){
User user = userMapper.selectById(1L);
user.setId(1L);
user.setAge(12);
// user.setEmail("qweqweqwe@qq.com");
user.setName("paleatta");
userMapper.updateById(user);
}
查询
- 普通查询 没啥好说的
- 查询单个就直接用ID就可以。selectById
- 查询多个ID时,需要使用集合类。这里使用了。集合工具类Arrays进行操作。selectBatchIds
- 简易的指定查询,需要使用Map类,通过键值对的形式及逆行查询selectByMap
@Test
public void queryTest(){
User user = userMapper.selectById(1L);
System.out.println(user);
List<User> users = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L));
users.forEach(System.out::println);
HashMap<String,Object> hashMap = new HashMap<>();
hashMap.put("name","paleatta");
List<User> userList = userMapper.selectByMap(hashMap);
System.out.println(userList);
}
- 分页查询
- 首先配置页进行配置
- 编写测试代码
- 先建立Page类的对象,对象中包含了当前页的页码以及每页的数目
- 通过electPage(page, wrapper)进行查询
- 通过page.get*()来获得想要的结果
注意看测试代码的输出,不要直接输出users,里面什么都没有,结果都在page对象里
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new
PaginationInnerInterceptor(DbType.MYSQL));
//DbType后面要对应上自己的所连接的数据库的类型,不一定要是MYSQL
return interceptor;
}
@Bean
public ConfigurationCustomizer configurationCustomizer() {
return configuration -> configuration.setUseDeprecatedExecutor(false);
}
@Test
public void queryPageTest(){
Page<User> page = new Page<>(1,5);
// List<User> selectPageVo();
Page<User> users = userMapper.selectPage(page, null);
System.out.println(page.getCurrent());
System.out.println(page.getRecords());
System.out.println(page.getTotal());
System.out.println(page.getPages());
System.out.println(page.getCountId());
System.out.println(users);
}
逻辑删除
- 普通删除和查询类似,这里就不写了
- 逻辑删除的本质是将deleted作为查询的一个标志,将删除操作转换成更新daleted属性值操作。如果为1则直接将其过滤掉,不会被查询到。如果为0,则表示为未被过滤掉,仍然可以查询到。数据库中是不会被删除的。
- 其结果为0,逻辑删除(更新)失败;为1,逻辑删除(更新)成功
mybatis-plus:
global-config:
db-config:
logic-delete-field: deleted # 全局逻辑删除的实体字段名
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
@TableLogic
private Integer deleted
@Test
public void logicDelTest(){
System.out.println(userMapper.deleteById(1343076393042391042L));
}
性能检测插件
- 最新版的MP已经将其移除了 推荐使用P6Spy ,如有需要后面再学习吧。
Wrapper条件查询器
- 常用的wrapper,包括
- eq(比较), between(介于两者之间), notlike(不像),like(像 %q% ),likeRight(q%) ,likeLeft(q%) ,isNull(为空), isNotNull(不为空), insql(嵌套查询), orderByAsc(升序排序),orderByDesc(降序排序)
- 以eq为例如下。
@Test
public void test1() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
qqueryWrapper.eq("version", 1)
.likeRight("email","qwe")
.isNotNull("deleted")
.orderByAsc("age")
.between("id", "2", "4"); //q%
userMapper.selectList(queryWrapper).forEach(System.out::println);
}
Preparing: SELECT id,name,age,email,deleted,version,create_time,update_time
FROM user WHERE deleted=0 AND (version = ? AND email LIKE ? AND
deleted IS NOT NULL AND id BETWEEN ? AND ?) ORDER BY age ASC
==> Parameters: 1(Integer), qwe%(String), 2(String), 4(String)
- insql可能以后会用,现在好像比较推荐联表查询,所以这里就不练习了。
自动代码生成器
`
- 代码生成器按需使用,根据自己的情况进行更改,最后再运行一下main就可以了
- 最后不要忘记加上最后的配置
package com.paleatta.mybatisplus;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.ArrayList;
/**
* @description: 代码自动生成器
* @program: mybatisplus
* @author: paleatta
* @date: 2020-12-28 15:08
* @version: jdk1.8
**/
// 执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
public class CodeGenerator {
public static void main(String[] args) {
// 需要构建一个 代码自动生成器 对象
AutoGenerator mpg = new AutoGenerator();
// 配置策略
// 1、全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");//设置输出文件夹
gc.setAuthor("paleatta");
gc.setOpen(false);//是否打开文件夹
gc.setFileOverride(false); // 是否覆盖
gc.setServiceName("%sService"); // 去Service的I前缀
gc.setIdType(IdType.ASSIGN_ID);//设置主键唯一策略
gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型
gc.setSwagger2(true); //是否使用swagger2
mpg.setGlobalConfig(gc);
//2、设置数据源
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/mybatisplus?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");//驱动器
dsc.setUsername("root");//账号
dsc.setPassword("123456");//密码
dsc.setDbType(DbType.MYSQL);//数据库类型
mpg.setDataSource(dsc);
//3、包的配置
PackageConfig pc = new PackageConfig();
pc.setModuleName("mybatisplus");//模块的名称
pc.setParent("com.paleatta");//在哪个包下
pc.setEntity("pojo");//实体类包名
pc.setMapper("mapper");//Dao层包名
pc.setService("service");//service层包名
pc.setController("controller");//controller层包名
mpg.setPackageInfo(pc);
//4、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("user", "user1"); // 设置要映射的数据库的表名
strategy.setNaming(NamingStrategy.underline_to_camel);//支持下划线转驼峰
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//支持下划线转驼峰
strategy.setEntityLombokModel(true); // 自动lombok;
strategy.setLogicDeleteFieldName("deleted");//设置逻辑删除标志
// 自动填充配置
// 这里是自动对创建时间和更新时间进行配置
// gmt_create gmt_modified 国际通用创建时间和更新时间
TableFill createTime = new TableFill("create_time", FieldFill.INSERT);
TableFill updateTime = new TableFill("update_time",
FieldFill.INSERT_UPDATE);
ArrayList<TableFill> tableFills = new ArrayList<>();
tableFills.add(createTime);
tableFills.add(updateTime);
strategy.setTableFillList(tableFills);
// 乐观锁
strategy.setVersionFieldName("version");//乐观锁标志位
strategy.setRestControllerStyle(true);//restful风格设置
strategy.setControllerMappingHyphenStyle(true);//驼峰转连字符,我也不太懂啥意思
//localhost:8080/hello_id_2
mpg.setStrategy(strategy);
mpg.execute(); //执行
}
}
<!-- 代码自动生成器的maven配置 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<!-- 设置为默认风格 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>
<!-- 下面两个是swagger2的maven配置 不用的话可以不配置 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!-- 目前感觉没啥用 -->
<!-- https://mvnrepository.com/artifact/io.swagger.core.v3/swagger-annotations -->
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>2.1.5</version>
</dependency>