Mybatis-Plus
Posted aBiu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis-Plus相关的知识,希望对你有一定的参考价值。
参考地址:https://mp.baomidou.com/guide/quick-start.html
快速入手:
SpringBoot项目依赖:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.2.RELEASE</version> <relativePath/> </parent>
引入 spring-boot-starter
、spring-boot-starter-test
、mybatis-plus-boot-starter
、lombok
依赖:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.3.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
在 application.yml
配置文件中添加相关配置:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true spring.datasource.username=root spring.datasource.password=root mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
在 Spring Boot 启动类中添加 @MapperScan
注解,扫描 Mapper 文件夹:
@MapperScan("com.biao.mapper") @SpringBootApplication public class MybatisPlusApplication { public static void main(String[] args) { SpringApplication.run(MybatisPlusApplication.class, args); } }
编写实体类 User.java
(此处使用了 Lombok 简化代码)
@Data public class User { private Long id; private String name; private Integer age; private String email; }
编写Mapper类
// mapper 接口继承一个接口,BaseMapper public interface UserMapper extends BaseMapper<User> { }
在测试类测试:
@Autowired private UserMapper userMapper; @Test public void testSelect() { System.out.println(("----- selectAll method test ------")); List<User> userList = userMapper.selectList(null); Assert.assertEquals(5, userList.size()); userList.forEach(System.out::println); }
测试完毕,那么,这些sql 是谁写的呢?
配置日志
所有的sql现在是不可见的,如果要知道它是怎么执行的,就要看日志。
只需要一行,在配置文件添加: mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
CRUD 扩展
所有sql 都是自动 动态配置的
插入测试
public void insert(){ User user = new User(); user.setName("wangbiao"); user.setAge(3); user.setEmail("1371850216@qq.com"); // 没有set id,它会自动生成id // 数据库插入的默认id,是全局唯一的 int insert = userMapper.insert(user); }
id 生成策略
uuid 自增id 雪花算法 redis zookeeper
参考地址:https://www.cnblogs.com/haoxinyue/p/5208136.html
Twitter的snowflake算法
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。具体实现的代码可以参看https://github.com/twitter/snowflake。
修改方法:
public void update(){ User user = new User(); user.setId(123L); // 根据id 修改数据 user.setName("aBiu~"); int i = userMapper.updateById(user); }
填充策略
设置数据库对应的实体类:
@Data public class User { @TableId(type = IdType.ASSIGN_ID) // 默认就是这个 private Long id; private String name; private Integer age; private String email; @TableField(fill = FieldFill.INSERT) // 设置新增时间 private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE) // 设置修改时候,新增时间也要添加 private Date updateTime; }
既然设置了新增,要配置,写个handler 的配置类并重写两个方法:
@Slf4j @Component public class MyMetaObjectHandler implements MetaObjectHandler { // 插入时的填充策略 @Override public void insertFill(MetaObject metaObject) { // 根据实体类的 createTime updateTime 字段,添加或 修改数据时执行这个方法,添加一个时间 this.setFieldValByName("createTime",new Date(),metaObject); this.setFieldValByName("updateTime",new Date(),metaObject); } // 修改时的填充策略 @Override public void updateFill(MetaObject metaObject) { // 修改时只修改 修改时间的字段数据 this.setFieldValByName("updateTime",new Date(),metaObject); } }
乐观锁机制:
实现方式:
取出记录时,获取当前 version
更新时,带上这个 version
执行更新时,set version,where 判断version 版本
如果version 版本不对,就更新失败。
乐观锁插件
1、给数据库增加version 字段,设置默认值1,就是初始时给 1
2、给对应的实体类添加属性字段,增加注解:@Version
@Version private Integer version;
3、注册组件
在config 包里配置,写一个MyBatisPlusConfig
// 事务注解 @EnableTransactionManagement @Configuration public class MyBatisPlusConfig { // 注册乐观锁插件 @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); } }
分页查询
1、配置拦截器:
官网代码:
//Spring boot方式 @Configuration @MapperScan("com.baomidou.cloud.service.*.mapper*") public class MybatisPlusConfig { @Bean public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false // paginationInterceptor.setOverflow(false); // 设置最大单页限制数量,默认 500 条,-1 不受限制 // paginationInterceptor.setLimit(500); // 开启 count 的 join 优化,只针对部分 left join paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true)); return paginationInterceptor; } }
我们只需要在配置文件写个方法,写一行代码即可;找到那个配置类
// 事务注解 @EnableTransactionManagement @Configuration public class MyBatisPlusConfig { // 注册乐观锁插件 @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); } // 分页插件 @Bean public PaginationInterceptor paginationInterceptor(){ return new PaginationInterceptor(); } }
2、测试
// 测试分页查询 public void testPage(){ // 第一页,每一页显示5条数据 Page<User> page = new Page<>(1, 5); userMapper.selectPage(page,null); page.getRecords().forEach(System.out::println); }
这个page 有很多方法,比如上一页下一页总数。。。
删除操作
mapper 可以直接点 出来删除方法,通过id,map,批量,三种删除方式,直接执行即可
通过id删除: userMapper.deleteById(1L);
通过id批量删除: userMapper.deleteBatchIds(Arrays.asList(1,2,3));
通过map删除:
HashMap<String, Object> map = new HashMap<>(); // name 是属性,数据库字段 map.put("name","wangbiao"); userMapper.deleteByMap(map);
逻辑删除
在数据库中没有被删除,只是通过一个变量来让它失效。
1、在数据库表中添加一个deleted 字段,实体类中添加一个相应的属性,不要忘记加注解 @TableLogic
@TableLogic // 逻辑删除 private Integer deleted;
2、配置:
# 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2) mybatis-plus.global-config.db-config.logic-delete-field= flag # 逻辑已删除值(默认为 1) mybatis-plus.global-config.db-config.logic-delete-value= 1 # 逻辑未删除值(默认为 0) mybatis-plus.global-config.db-config.logic-not-delete-value= 0
3、再次执行删除: userMapper.deleteById(1L);
就是逻辑删除,不会真正删除,记录依旧在数据库,但是值已经发生变化。
但是再次查询这条数据,会查不到的,自动会过滤掉逻辑删除的。
条件构造器(重点)
一些复杂的sql 就可以使用它来代替。
参考地址:https://mp.baomidou.com/guide/wrapper.html#abstractwrapper
示例:返回多条数据
public void test(){ QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.isNotNull("name") // name 不为空的 .isNotNull("email") // email 不为空的 .ge("age",21); // age 大于21 的,但是好像等于21 的也会查出来 userMapper.selectList(wrapper).forEach(System.out::println); }
还有很多条件可以加,like(模糊)、orderBy(排序)等等,很多,
参考官方地址:https://mp.baomidou.com/guide/wrapper.html#eq
示例2:查询一条数据的:如果明知道是查出来的是多条数据,就不要用这个
public void test(){ QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("name","wangbiao"); // 查询名字等于wangbiao 的 User user = userMapper.selectOne(wrapper); System.out.println(user); }
示例3:between 查询xx 到 xx 之间的总数
public void test(){ QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.between("age",20,30); // 查询年龄20到30之间的 Integer i = userMapper.selectCount(wrapper); System.out.println(i); }
示例4:模糊查询
@Test public void test(){ QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.notLike("name","a"); // 查询名字不包含a 的 List<Map<String, Object>> maps = userMapper.selectMaps(wrapper); maps.forEach(System.out::println); }
@Test public void test(){ QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.likeRight("name","a") // 查询包含a 的 .likeLeft("name","a"); // 左跟 右 就是代表模糊查询时候的% 百分号在左边还是在右边,两个都写代表左右两个% 都有 List<Map<String, Object>> maps = userMapper.selectMaps(wrapper); maps.forEach(System.out::println); }
示例5:in 查询
public void test(){ QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.inSql("id","select id from user where age < 21"); // 这里可以写sql,也可以在上一行先查出来,再放到这里当条件 List<Object> objects = userMapper.selectObjs(wrapper); objects.forEach(System.out::println); // 返回的是id }
示例6:orderBy
@Test public void test(){ QueryWrapper<User> wrapper = new QueryWrapper<>(); // 通过id 进行排序 wrapper.orderByDesc("id"); // 降序,有对应的升序 及其他排序方法 List<User> users = userMapper.selectList(wrapper); users.forEach(System.out::println); }
代码生成器
确认添加这些依赖:-- 这里少了swagger API 的依赖,到时生成的实体类会导入swagger注解失败报错
<dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.3.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.3.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
生成代码模板类:
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; // 代码自动生成器 public class ShengChengCode { public static void main(String[] args) { // 构建一个代码生成器 AutoGenerator mpg = new AutoGenerator(); // 配置策略 // 1、全局配置 GlobalConfig gconfig = new GlobalConfig(); String propertyPath = System.getProperty("user.dir"); gconfig.setOutputDir(propertyPath+"/src/main/java"); gconfig.setAuthor("wangbiao"); gconfig.setOpen(false); gconfig.setFileOverride(false); // 是否覆盖 gconfig.setServiceName("%Service"); // 去Service 的i 前缀 gconfig.setIdType(IdType.ID_WORKER); gconfig.setDateType(DateType.ONLY_DATE); gconfig.setSwagger2(true); mpg.setGlobalConfig(gconfig); // set 到自动生成器里 // 2、设置数据源 DataSourceConfig dsc = new DataSourceConfig(); dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true"); dsc.setDriverName("com.mysql.jdbc.Driver"); dsc.setUsername("root"); dsc.setPassword("root"); dsc.setDbType(DbType.MYSQL); mpg.setDataSource(dsc); // set 到自动生成器里 // 3、包的设置 PackageConfig pc = new PackageConfig(); pc.setModuleName("blog"); pc.setParent("com.biao"); pc.setEntity("po"); pc.setMapper("mapper"); pc.setService("service"); pc.setController("ctrl"); mpg.setPackageInfo(pc); // set 到自动生成器里 // 4、策略配置 --- 这个是最重要的 StrategyConfig strategy = new StrategyConfig(); strategy.setInclude("user"); // 设置要映射的表,可以写多个表,逗号,隔开 strategy.setNaming(NamingStrategy.underline_to_camel); // 包的命名规则 strategy.setColumnNaming(NamingStrategy.underline_to_camel); // 列的名字规则 strategy.setEntityLombokModel(true); // 支持lombok 注解 // strategy.setLogicDeleteFieldName("deleted"); // 逻辑删除字段 // 自动填充 创建和修改的字段自动填充 // TableFill create = new TableFill("create", FieldFill.INSERT); // TableFill modified = new TableFill("modified", FieldFill.INSERT_UPDATE); // ArrayList<TableFill> list = new ArrayList<>(); // list.add(gmtCreate); // list.add(gmtModified); // strategy.setTableFillList(list); // 乐观锁配置 // strategy.setVersionFieldName("version"); // strategy.setRestControllerStyle(true); // strategy.setControllerMappingHyphenStyle(true); mpg.setStrategy(strategy); // 执行 mpg.execute(); } }
确定数据库和配置,启动这个main 方法即可
以上是关于Mybatis-Plus的主要内容,如果未能解决你的问题,请参考以下文章