MyBatis_Plus
文章目录
- MyBatis_Plus
- 0. 必备知识
- 1.快速入门
- 1.1什么是MyBatis_Plus
- 1.2快速使用
- 2.配置日志
- 3.CURD的扩展
- 3.1Insert
- 3.2 update
- 3.3自动填充
- 3.4乐观锁
- 3.5delete
- 4.select
- 4.1基本查询
- 4.2分页查询
- 4.3条件构造器
- 5.代码自动生成器
0. 必备知识
使用第三方组件一般步骤
-
导入对应依赖
-
研究依赖如何配置
-
代码如何编写
-
提高技术扩展能力
对于MyBatis-Plus的学习我们也将按照上面4步进行学习
常见网站
MVN仓库
MyBatisPlus官网
1.快速入门
1.1什么是MyBatis_Plus
- 简称MP,是一个MyBatis的增强工具,在其基础上只做增强,不做修改
- 引入MP,就不再需要导入MyBatis了
1.2快速使用
1.添加依赖
-
父工程的
Spring Boot Starter
版本2.5+ -
添加依赖
spring-boot-starter
spring-boot-starter-test
这两个如果创建了springboot项目则大概率存在,注意检查是否已经存在
-
mybatis-plus-boot-starter
:mybatis plus -
MySQL Connector/J
:数据库驱动 -
Project Lombok
:简化java代码,@Data
,@NoArgsConstructor
,@AllArgsConstructor
,生成常见方法 -
mybatis-plus-generator
:代码生成器, -
Spring Boot Starter JDBC
2.安装插件lombok
这是为了让IDEA正确处理Lombok注解
3.配置
首先我们需要了解到,在Springboot项目中,使用.properties
和.yml
配置是等效的,均可以正常识别并使用.
在这里我们使用.properties
配置
spring.datasource.username=root
spring.datasource.password=232156
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
-
mybatis_plus ?
:对应使用的数据库的名称 -
serverTimezone=Asia/Shanghai
:配置时区 -
useUnicode=true&characterEncoding=utf-8
:字符编码解码格式 -
MySql5之前的
- 驱动不同,采用该驱动
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
- 不需要时区配置
4.编写代码
- 编写顺序:
pojo-mapper-service-controller
主要设计两个包的代码编写
-
pojo:存放实体类,
//注解就是利用lombok来自动生成一些方法 @Data @NoArgsConstructor @AllArgsConstructor public class User { private Integer id; private String name; private Integer age; private String email; }
-
mapper:存放对应使用的接口,在这一步,所有的CURD就已经全部实现完了
//必须继承BaseMapper类 @Mapper public interface UserMapper extends BaseMapper<User> { }
-
在主程序入口添加
@MapperScan
,来快速扫描mapper//括号中填写具体的mapper文件夹路径 @MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")
-
测试
@SpringBootTest class MyBatisPlusApplicationTests { //所有方法都来自父类 //也可以编写自己的文件 @Autowired private UserMapper userMapper; @Test void contextLoads() { //参数是wapper List<User> users=userMapper.selectList(null); System.out.println(users); } }
问题思考
- 谁帮我们编写的SQL:MyBatisPlus
- 方法哪里来?MyBatis_Plus写好了
2.配置日志
我们所有sql是不可见的,我们希望知道他是怎么执行的,所以必须要看日志
#配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
- 自动生成的id
3.CURD的扩展
3.1Insert
主键生成策略
-
自增id:实体类配置(对应数据库中的也需要对应的设置)
@TabledId(type=IdType.AUTO) NONE:未设置主键 INPUT:手动输入,需要我们手动输入 ID_WORKER:默认全局唯一ID UUID:全局唯一id uuid ID_WORKER_STR:ID_WORKER字符串表示法
-
UUID
-
Redis生成ID
雪花算法
-
雪花算法(多用于分布式):snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。
-
其核心思想是使用41bit作为毫秒数,10bit作为机器ID(5bit数据中心,5bit机器ID),12bit作为毫秒的流水号(每个节点每毫秒产生4096个id),最后一个符号位永远为0.可以保证全球唯一
3.2 update
- 注意在这里传入的参数实际是一个对象
@Test
public void testUpdate(){
User user=new User();
user.setId(1);
user.setName("曹操");
//参数实际是一个对象
int i=userMapper.updateById(user);
System.out.println(i);
}
3.3自动填充
-
数据库的级别的自动填充
- 修改数据库(给对应的字段添加默认值)
-
修改实体类(与数据库同步)
-
再次执行更新操作即可
代码级别
-
不设置默认值
-
实体类字段上增加注解
@TableField(fill = FieldFill.INSERT)//插入执行,更新不执行 private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE)//插入更新都执行 private Date updateTime;
-
编写处理器处理该注解(放在hadler包中)
@Slf4j//日志 @Component//丢到springboot里 一定不要忘记把处理器加到Ioc容器中! public class MyMetaObjectHandler extends MetaObjectHandler {//extends?? @Override//插入时的填充策略 public void insertFill(MetaObject metaObject) { log.info("==start insert ······=="); //setFieldValByName(java.lang.String fieldName, java.lang.Object fieldVal, org.apache.ibatis.reflection.MetaObject metaObject) this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); } @Override//更新时的填充策略 public void updateFill(MetaObject metaObject) { log.info("==start update ······=="); this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); } }
-
测试即可
- 更新
- 插入
3.4乐观锁
- 乐观锁:他总是认为不会出现问题,无论做什么都不会去上锁!如果出现问题,就再次更新值测试‘
- 悲观锁:认为总是出现问题,无论干什么都会上锁
- 当你跟新一条记录时,希望这条记录没有被别人更新
乐观锁的实现
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新,
set version=newVersion where version=oldVersion
- 如果version不对则更新失败
-
给数据库增加version字段
-
实体类增加对应字段即注解
@Version//乐观锁version注解 private Integer version;
-
注册组件:新建文件
config.MyBatisPlusConfig
文件@MapperScan("com.upupstudy.mybatis_plus.mapper")//在主程序入口就可以删除对应的扫描了 @EnableTransactionManagement//事务管理 @Configuration//代表这是配置类 public class MyBatisPlusConfig { //注册乐观锁插件 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() {//拦截器 MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());//乐观锁插件 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));//分页插件 return interceptor; } }
-
测试
3.5delete
- 物理删除:直接在数据库中删除
- 新增一个字段:用改值来标记是否被删除(0在1删)
-
新增一个
deleted
字段 -
实体类添加对应属性
@TableLogic//逻辑删除注解 private Integer deleted;
-
配置
#配置逻辑删除 没删除的为0 删除的为1 mybatis-plus.global-config.db-config.logic-delete-value=1 mybatis-plus.global-config.db-config.logic-not-delete-value=0
-
测试
- 将对应项的deleted值进行更新
- 但是查询时,无法查询该项
userMapper.deleteById(1)//看似删除,其实执行的时更新操作
4.select
4.1基本查询
-
单个查询
@Test//通过id查询单个用户 public void testSelectById(){ User user = userMapper.selectById(1); System.out.println(user); }
-
批量查询
@Test//通过id查询多个用户 public void testSelectBatchIds(){ List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3)); users.forEach(System.out::println); //System.out.println(users); }
-
条件查询
@Test//通过条件查询之一 map public void testMap(){ HashMap<String, Object> map = new HashMap<>(); //自定义要查询的条件 map.put("name","张飞"); map.put("age",18); List<User> users = userMapper.selectByMap(map); users.forEach(System.out::println); }
4.2分页查询
常见的分页方法
- limit方法
- pageHelper第三方插件
- MP内置分页插件
-
设置拦截器组件
@MapperScan("com.upupstudy.mybatis_plus.mapper") @EnableTransactionManagement//事务管理 @Configuration//代表这是配置类 public class MyBatisPlusConfig { //注册乐观锁插件 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() {//拦截器 MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());//乐观锁插件 //************新增分页插件*************** interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));//分页插件 return interceptor; } }
-
直接使用page对象分页查询
/* *与前端连用,只需要从前端向后传输一个current参数即可 * */ @Test//测试分页查询 public void testPage(){ //参数一current:当前页 参数二size:页面大小 //使用了分页插件之后,所有的分页操作都变得简单了 Page<User> page = new Page<>(2,5); userMapper.selectPage(page,null); page.getRecords().forEach(System.out::println); System.out.println("总页数==>"+page.getTotal()); }
4.3条件构造器
- 具体条件可在官网查看,这里不一一列出
@Test
public void testWrapper1() {
//参数是一个wrapper ,条件构造器,和刚才的map对比学习!
//查询name不为空,email不为空,age大于18的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.isNotNull("name")
.isNotNull("email")
.ge("age",18);//年龄大于18
List<User> userList = userMapper.selectList(wrapper);
userList.forEach(System.out::println);
5.代码自动生成器
可以快速生成Entity,Mapper,Mapper XML,Service,Controller等各个模块的代码,极大的提高了开发效率
1.导入依赖
mybatis-plus-generator
Freemarker
2.代码编写:建议放在测试文件夹中
-
交互生成
FastAutoGenerator.create(DATA_SOURCE_CONFIG) // 全局配置 .globalConfig((scanner, builder) -> builder.author(scanner.apply("请输入作者名称?")).fileOverride()) // 包配置 .packageConfig((scanner, builder) -> builder.parent(scanner.apply("请输入包名?"))) // 策略配置 .strategyConfig((scanner, builder) -> builder.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all"))) .controllerBuilder().enableRestStyle().enableHyphenStyle() .entityBuilder().enableLombok().addTableFills( new Column("create_time", FieldFill.INSERT) ).build()) /* 模板引擎配置,默认 Velocity 可选模板引擎 Beetl 或 Freemarker .templateEngine(new BeetlTemplateEngine()) .templateEngine(new FreemarkerTemplateEngine()) */ .execute(); // 处理 all 情况 protected static List<String> getTables(String tables) { return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(",")); }
-
快速生成
FastAutoGenerator.create("url", "username", "password")//对应到.properites中的sql配置
.globalConfig(builder -> {
builder.author("baomidou") // 设置作者
//建议注释
.enableSwagger() // 开启 swagger 模式,0
//建议注释
.fileOverride() // 覆盖已生成文件,建议注释
.outputDir("D://"); // java一级目录下,绝对路径
})
.dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
int typeCode = metaInfo.getJdbcType().TYPE_CODE;
if (typeCode == Types.SMALLINT) {
// 自定义类型转换
return DbColumnType.INTEGER;
}
return typeRegistry.getColumnType(metaInfo);
}))
.packageConfig(builder -> {
builder.parent("com.baomidou.mybatisplus.samples.generator") // 填写到与主程序同一级目录
.moduleName("system") // 设置父包模块名,为这个文件夹命名
.pathInfo(Collections.singletonMap(OutputFile.xml, "D://")); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.addInclude("t_simple") // 设置需要生成的表名
.addTablePrefix("t_", "c_"); // 设置过滤表前缀
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
配置方法
详细解释