Mybatis Plus
快速入门
- maven配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.erf</groupId>
<artifactId>springboot-data</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-data</name>
<description>Demo project for Spring Boot Redis and MySql Plus</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.23</version>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
-
create table
drop table if exists `user`; create table `user`( `id` bigint not null auto_increment, `name` varchar(255) default null, `age` int default null , `email` varchar(255) default null, key `id`(`id`) )engine=InnoDB default charset =utf8; insert into `user`(`name`,`age`,`email`) values ('John1',24,'125jawdi@awd.com'), ('John2',42,'125jawdi@awd.com'), ('John3',42,'125jawdi@awd.com'), ('John4',44,'125jawdi@awd.com');
-
数据库连接
spring.datasource.username=root spring.datasource.password=980980 spring.datasource.url=jdbc:mysql://localhost:3306/ssmbuild?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2d8 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
-
User.java
package com.erf.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor public class User { private int id; private String name; private int age ; private String email; }
-
UserMapper.java
package com.erf.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.erf.pojo.User; import org.springframework.stereotype.Repository; @Repository public interface UserMapper extends BaseMapper<User> { }
-
Application
package com.erf; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @MapperScan("com.erf.mapper") @SpringBootApplication public class SpringbootDataApplication { public static void main(String[] args) { SpringApplication.run(SpringbootDataApplication.class, args); } }
-
test CRUD接口
package com.erf; import com.erf.mapper.UserMapper; import com.erf.pojo.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.util.List; @SpringBootTest class SpringbootDataApplicationTests { @Autowired private UserMapper userMapper; @Test void contextLoads() { List<User> users = userMapper.selectList(null); users.forEach(System.out::println); } }
-
结果显示
User(id=1, name=John1, age=24, email=125jawdi@awd.com)
User(id=2, name=John2, age=42, email=125jawdi@awd.com)
User(id=3, name=John3, age=42, email=125jawdi@awd.com)
User(id=4, name=John4, age=44, email=125jawdi@awd.com)
日志输出
spring.datasource.username=root
spring.datasource.password=980980
spring.datasource.url=jdbc:mysql://localhost:3306/ssmbuild?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2d8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#控制台日志输出
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
主键策略和雪花算法
-
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。
snowflake算法可以根据自身项目的需要进行一定的修改。比如估算未来的数据中心个数,每个数据中心的机器数以及统一毫秒可以能的并发数来调整在算法中所需要的bit数。优点:
不依赖于数据库,灵活方便,且性能优于数据库。ID按照时间在单机上是递增的。
缺点:
在单机上是递增的,但是由于涉及到分布式环境,每台机器上的时钟不可能完全同步,也许有时候也会出现不是全局递增的情况。
-
主键策略
@TableId(type = IdType.ASSIGN_ID) //注意 使用了数据库主键自增的 auto_increment 将会使得 type 不生效
IdType
值 描述 AUTO 数据库ID自增 NONE 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT) INPUT insert前自行set主键值 ASSIGN_ID 分配ID(主键类型为Number(Long和Integer)或String)(since 3.3.0),使用接口 IdentifierGenerator
的方法nextId
(默认实现类为DefaultIdentifierGenerator
雪花算法)ASSIGN_UUID 分配UUID,主键类型为String(since 3.3.0),使用接口 IdentifierGenerator
的方法nextUUID
(默认default方法)ID_WORKER分布式全局唯一ID 长整型类型(please use ASSIGN_ID
)UUID32位UUID字符串(please use ASSIGN_UUID
)ID_WORKER_STR分布式全局唯一ID 字符串类型(please use ASSIGN_ID
)
初始填充策略
-
注解
@TableField(fill = FieldFill.INSERT) String createTime;
-
实现方式
package com.erf.controller; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component; import java.time.LocalDateTime; @Slf4j @Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { log.info("start insert fill ...."); this.strictUpdateFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); } @Override public void updateFill(MetaObject metaObject) { } }
乐观锁
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
-
在实体类的字段上加上
@Version
注解@Version private String name;
-
实现MybatisPlusInterceptor注入
package com.erf.conf; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @MapperScan("com.erf.pojo") public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return mybatisPlusInterceptor; } }
分页查询
-
MybatisPlusInterceptor
@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); } }
-
分页的使用
@Test void contextLoads4(){ Page<User> userPage = new Page<>(3,3); userMapper.selectPage(userPage,null); userPage.getRecords().forEach(System.out::println); }
自动生成代码
不要忘记Application扫描包@MapperScan 注意自动生成的同类名Mapper自动注入失效问题
package com.erf.autocode;
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.rules.NamingStrategy;
public class MysqlGenerator {
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"); //生成路径(一般都是生成在此项目的src/main/java下面)
gc.setAuthor("EatRiceFully"); //设置作者
gc.setOpen(false);
gc.setFileOverride(true); //第二次生成会把第一次生成的覆盖掉
gc.setServiceName("%sService"); //生成的service接口名字首字母是否为I,这样设置就没有
gc.setBaseResultMap(true); //生成resultMap
mpg.setGlobalConfig(gc);
//2、数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/ssmbuild?useUnicode=true&serverTimezone=GMT&useSSL=false&characterEncoding=utf8");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("980980");
mpg.setDataSource(dsc);
// 3、包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName("autotest");
pc.setParent("com.erf");
mpg.setPackageInfo(pc);
// 4、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setSuperControllerClass("com.lcy.demo.sys.controller.BaseController");
strategy.setSuperEntityClass("com.lcy.demo.sys.entity.BaseEntity");
// strategy.setTablePrefix("t_"); // 表名前缀
strategy.setEntityLombokModel(true); //使用lombok
String[] tables = {"books","user"};
strategy.setInclude(tables); // 逆向工程使用的表 如果要生成多个,这里可以传入String[]
mpg.setStrategy(strategy);
//5、执行
mpg.execute();
}
}