首页 文章资讯内容详情

SpringBoot整合系列--整合MyBatis-plus

2026-06-01 4 花语

本文内容纲要:

-SpringBoot整合MyBatis-plus -步骤 -第一步:添加必要的依赖 -第二步:添加必要的配置 -第三步:添加必要的配置类 -第四步:定义实体 -第五步:定义mapper接口 -第六步:定义service(重点) -第七步:定义controller -高级功能 -代码生成器 -分页插件 -逻辑删除 -枚举自动注入 -Sql自动注入 -性能分析插件 -乐观锁插件 -实体主键配置 -注意事项

原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/10125279.html

SpringBoot整合MyBatis-plus

步骤

第一步:添加必要的依赖

第一种是在已存在MyBatis的情况下,直接添加mybatis-plus包即可。

<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>2.1.8</version> </dependency>

第二种是直接添加mybatis-plus的starter,它会自动导入mybatis的依赖包及其他相关依赖包

<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.1</version> </dependency>

第二步:添加必要的配置

注意:Mybatis-plus是MyBatis的再封装,添加MyBatis-plus之后我们的设置针对的应该是MyBatis-plus,而不是MyBatis。

mybatis-plus: mapper-locations:classpath*:/mapper/*.xml type-aliases-package:com.example.springbootdemo.entity type-aliases-super-type:java.lang.Object type-handlers-package:com.example.springbootdemo.typeHandler type-enums-package:com.example.springbootdemo.enums

第三步:添加必要的配置类

@EnableTransactionManagement @Configuration @MapperScan("com.example.springbootdemo.plusmapper") publicclassMyBatisPlusConfig{ //mybatis-plus分页插件 @Bean publicPaginationInterceptorpaginationInterceptor(){ returnnewPaginationInterceptor(); } }

第四步:定义实体

@Data @Builder @ToString @EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor @TableName(value="ANIMAL") publicclassAnimal{ @TableId(value="ID",type=IdType.AUTO) privateIntegerid; @TableField(value="NAME",exist=true) privateStringname; @TableField(value="TYPE",exist=true) privateAnimalTypetype; @TableField(value="SEX",exist=true) privateAnimalSexsex; @TableField(value="MASTER",exist=true) privateStringmaster; } publicenumAnimalTypeimplementsIEnum{ CAT("1","猫"),DOG("2","狗"),TIGER("3","虎"),MOUSE("4","鼠"),MONKEY("5","猴"),LOAN("6","狮"),OTHER("7","其他"); privatefinalStringvalue; privatefinalStringdesc; AnimalType(finalStringvalue,finalStringdesc){ this.value=value; this.desc=desc; } @Override publicSerializablegetValue(){ returnvalue; } publicStringgetDesc(){ returndesc; } } publicenumAnimalSeximplementsIEnum{ MALE("1","公"),FEMALE("2","母"); privatefinalStringvalue; privatefinalStringdesc; AnimalSex(finalStringvalue,finalStringdesc){ this.value=value; this.desc=desc; } @Override publicSerializablegetValue(){ returnvalue; } publicStringgetDesc(){ returndesc; } }

第五步:定义mapper接口

publicinterfaceAnimalRepositoryextendsBaseMapper<Animal>{ }

解说:使用MyBatisPlus后Mapper只要继承BaseMapper接口即可,即使不添加XML映射文件也可以实现该接口提供的增删改查功能,还可以配合Wrapper进行条件操作,当然这些操作都仅仅限于单表操作,一旦涉及多表联查,那么还是乖乖添加**Mapper.xml来自定义SQL吧!!!

第六步:定义service(重点)

@Service @Log4j2 publicclassAnimalService{ @Autowired privateAnimalRepositoryanimalRepository; //增 publicResponseEntity<Animal>addAnimal(finalAnimalanimal){ animalRepository.insert(animal); returnResponseEntity.ok(animal); } //删 publicResponseEntity<Integer>deleteAnimalById(finalintid){ returnResponseEntity.ok(animalRepository.deleteById(id)); } publicResponseEntity<Integer>deleteAnimals(finalAnimalanimal){ returnResponseEntity.ok(animalRepository.delete(packWrapper(animal,WrapperType.QUERY))); } publicResponseEntity<Integer>deleteAnimalsByIds(List<Integer>ids){ returnResponseEntity.ok(animalRepository.deleteBatchIds(ids)); } publicResponseEntity<Integer>deleteAnimalsByMap(finalAnimalanimal){ Map<String,Object>params=newHashMap<>(); if(Objects.nonNull(animal.getId())){ params.put("ID",animal.getId()); } if(StringUtils.isNotEmpty(animal.getName())){ params.put("NAME",animal.getName()); } if(Objects.nonNull(animal.getType())){ params.put("TYPE",animal.getType()); } if(Objects.nonNull(animal.getSex())){ params.put("SEX",animal.getSex()); } if(StringUtils.isNotEmpty(animal.getMaster())){ params.put("MASTER",animal.getMaster()); } returnResponseEntity.ok(animalRepository.deleteByMap(params)); } //改 publicResponseEntity<Integer>updateAnimals(finalAnimalanimal,finalAnimalcondition){ returnResponseEntity.ok(animalRepository.update(animal,packWrapper(condition,WrapperType.UPDATE))); } publicResponseEntity<Integer>updateAnimal(finalAnimalanimal){ Wrapper<Animal>animalWrapper=newUpdateWrapper<>(); ((UpdateWrapper<Animal>)animalWrapper).eq("id",animal.getId()); returnResponseEntity.ok(animalRepository.update(animal,animalWrapper)); } //查 publicResponseEntity<Animal>getAnimalById(finalintid){ returnResponseEntity.ok(animalRepository.selectById(id)); } publicResponseEntity<Animal>getOneAnimal(finalAnimalanimal){ returnResponseEntity.ok(animalRepository.selectOne(packWrapper(animal,WrapperType.QUERY))); } publicResponseEntity<List<Animal>>getAnimals(finalAnimalanimal){ returnResponseEntity.ok(animalRepository.selectList(packWrapper(animal,WrapperType.QUERY))); } publicResponseEntity<List<Animal>>getAnimalsByIds(List<Integer>ids){ returnResponseEntity.ok(animalRepository.selectBatchIds(ids)); } publicResponseEntity<List<Animal>>getAnimalsByMap(finalAnimalanimal){ Map<String,Object>params=newHashMap<>(); if(Objects.nonNull(animal.getId())){ params.put("ID",animal.getId()); } if(StringUtils.isNotEmpty(animal.getName())){ params.put("NAME",animal.getName()); } if(Objects.nonNull(animal.getType())){ params.put("TYPE",animal.getType()); } if(Objects.nonNull(animal.getSex())){ params.put("SEX",animal.getSex()); } if(StringUtils.isNotEmpty(animal.getMaster())){ params.put("MASTER",animal.getMaster()); } returnResponseEntity.ok(animalRepository.selectByMap(params)); } publicResponseEntity<List<Map<String,Object>>>getAnimalMaps(finalAnimalanimal){ returnResponseEntity.ok(animalRepository.selectMaps(packWrapper(animal,WrapperType.QUERY))); } //查个数 publicResponseEntity<Integer>getCount(finalAnimalanimal){ returnResponseEntity.ok(animalRepository.selectCount(packWrapper(animal,WrapperType.QUERY))); } //分页查询 publicResponseEntity<Page<Animal>>getAnimalPage(finalAnimalanimal,finalintpageId,finalintpageSize){ Page<Animal>page=newPage<>(); page.setCurrent(pageId); page.setSize(pageSize); returnResponseEntity.ok((Page<Animal>)animalRepository.selectPage(page,packWrapper(animal,WrapperType.QUERY))); } privateWrapper<Animal>packWrapper(finalAnimalanimal,WrapperTypewrapperType){ switch(wrapperType){ caseQUERY: QueryWrapper<Animal>wrapper=newQueryWrapper<>(); if(Objects.nonNull(animal.getId())) wrapper.eq("ID",animal.getId()); if(StringUtils.isNotEmpty(animal.getName())) wrapper.eq("name",animal.getName()); if(Objects.nonNull(animal.getType())) wrapper.eq("type",animal.getType()); if(Objects.nonNull(animal.getSex())) wrapper.eq("sex",animal.getSex()); if(StringUtils.isNotEmpty(animal.getMaster())) wrapper.eq("master",animal.getMaster()); returnwrapper; caseUPDATE: UpdateWrapper<Animal>wrapper2=newUpdateWrapper<>(); if(Objects.nonNull(animal.getId())) wrapper2.eq("ID",animal.getId()); if(StringUtils.isNotEmpty(animal.getName())) wrapper2.eq("name",animal.getName()); if(Objects.nonNull(animal.getType())) wrapper2.eq("type",animal.getType()); if(Objects.nonNull(animal.getSex())) wrapper2.eq("sex",animal.getSex()); if(StringUtils.isNotEmpty(animal.getMaster())) wrapper2.eq("master",animal.getMaster()); returnwrapper2; caseQUERYLAMBDA: LambdaQueryWrapper<Animal>wrapper3=newQueryWrapper<Animal>().lambda(); if(Objects.nonNull(animal.getId())) wrapper3.eq(Animal::getId,animal.getId()); if(StringUtils.isNotEmpty(animal.getName())) wrapper3.eq(Animal::getName,animal.getName()); if(Objects.nonNull(animal.getType())) wrapper3.eq(Animal::getType,animal.getType()); if(Objects.nonNull(animal.getSex())) wrapper3.eq(Animal::getSex,animal.getSex()); if(StringUtils.isNotEmpty(animal.getMaster())) wrapper3.eq(Animal::getMaster,animal.getMaster()); returnwrapper3; caseUPDATELAMBDA: LambdaUpdateWrapper<Animal>wrapper4=newUpdateWrapper<Animal>().lambda(); if(Objects.nonNull(animal.getId())) wrapper4.eq(Animal::getId,animal.getId()); if(StringUtils.isNotEmpty(animal.getName())) wrapper4.eq(Animal::getName,animal.getName()); if(Objects.nonNull(animal.getType())) wrapper4.eq(Animal::getType,animal.getType()); if(Objects.nonNull(animal.getSex())) wrapper4.eq(Animal::getSex,animal.getSex()); if(StringUtils.isNotEmpty(animal.getMaster())) wrapper4.eq(Animal::getMaster,animal.getMaster()); returnwrapper4; default:returnnull; } } } enumWrapperType{ UPDATE,UPDATELAMBDA,QUERY,QUERYLAMBDA; }

第七步:定义controller

@RestController @RequestMapping("animal") @Api(description="动物接口") @Log4j2 publicclassAnimalApi{ @Autowired privateAnimalServiceanimalService; @RequestMapping(value="addAnimal",method=RequestMethod.PUT) @ApiOperation(value="添加动物",notes="添加动物",httpMethod="PUT") publicResponseEntity<Animal>addAnimal(finalAnimalanimal){ returnanimalService.addAnimal(animal); } @RequestMapping(value="deleteAnimalById",method=RequestMethod.DELETE) @ApiOperation(value="删除一个动物",notes="根据ID删除动物",httpMethod="DELETE") publicResponseEntity<Integer>deleteAnimalById(finalintid){ returnanimalService.deleteAnimalById(id); } @RequestMapping(value="deleteAnimalsByIds",method=RequestMethod.DELETE) @ApiOperation(value="删除多个动物",notes="根据Id删除多个动物",httpMethod="DELETE") publicResponseEntity<Integer>deleteAnimalsByIds(Integer[]ids){ returnanimalService.deleteAnimalsByIds(Arrays.asList(ids)); } @RequestMapping(value="deleteAnimals",method=RequestMethod.DELETE) @ApiOperation(value="删除动物",notes="根据条件删除动物",httpMethod="DELETE") publicResponseEntity<Integer>deleteAnimalsByMaps(finalAnimalanimal){ returnanimalService.deleteAnimalsByMap(animal); } @RequestMapping(value="deleteAnimals2",method=RequestMethod.DELETE) @ApiOperation(value="删除动物",notes="根据条件删除动物",httpMethod="DELETE") publicResponseEntity<Integer>deleteAnimals(finalAnimalanimal){ returnanimalService.deleteAnimals(animal); } @RequestMapping(value="getAnimalById",method=RequestMethod.GET) @ApiOperation(value="获取一个动物",notes="根据ID获取一个动物",httpMethod="GET") publicResponseEntity<Animal>getAnimalById(finalintid){ returnanimalService.getAnimalById(id); } //注意,这里参数animal不能用RequstBody标注,否则接收不到参数 //@RequestBody只能用在只有一个参数模型的方法中,用于将所有请求体中携带的参数全部映射到这个请求参数模型中 @RequestMapping(value="getAnimalsByPage") @ApiOperation(value="分页获取动物们",notes="分页获取所有动物",httpMethod="GET") publicResponseEntity<Page<Animal>>getAnimalsByPage(@RequestParamfinalintpageId,@RequestParamfinalintpageSize,finalAnimalanimal){ returnanimalService.getAnimalPage(animal==null?Animal.builder().build():animal,pageId,pageSize); } @RequestMapping(value="updateAnimal") @ApiOperation(value="更新动物",notes="根据条件更新",httpMethod="POST") publicResponseEntity<Integer>updateAnimals(finalAnimalanimal){ returnanimalService.updateAnimal(animal); } }

高级功能

代码生成器

分页插件

第一步:添加必要的配置 @EnableTransactionManagement @Configuration @MapperScan("com.example.springbootdemo.plusmapper") publicclassMyBatisPlusConfig{ @Bean//mybatis-plus分页插件 publicPaginationInterceptorpaginationInterceptor(){ returnnewPaginationInterceptor(); } } 第二步:添加Mapper publicinterfaceAnimalRepositoryextendsBaseMapper<Animal>{ } 第三步:添加service @Service @Log4j2 publicclassAnimalService{ @Autowired privateAnimalRepositoryanimalRepository; //... publicPage<Animal>getAnimalsByPage(intpageId,intpageSize){ Pagepage=newPage(pageId,pageSize); return(Page<Animal>)animalRepository.selectPage(page,null); } }

逻辑删除

所谓逻辑删除是相对于物理删除而言的,MyBatisPlus默认的删除操作是物理删除,即直接调用数据库的delete操作,直接将数据从数据库删除,但是,一般情况下,我们在项目中不会直接操作delete,为了保留记录,我们只是将其标记为删除,并不是真的删除,也就是需要逻辑删除,MyBatisPlus也提供了实现逻辑删除的功能,通过这种方式可以将底层的delete操作修改成update操作。 第一步:添加必要的配置 mybatis-plus: global-config: db-config: logic-delete-value:1#逻辑已删除值(默认为1) logic-not-delete-value:0#逻辑未删除值(默认为0) 第二步:添加必要的配置类 @Configuration publicclassMyBatisPlusConfiguration{ @Bean publicISqlInjectorsqlInjector(){ returnnewLogicSqlInjector(); } } 第三步:添加字段isDel和注解 @TableLogic privateIntegerisDel; 如此一来,我们再执行delete相关操作的时候,底层就会变更为update操作,将isDel值修改为1。

注意:通过此种方式删除数据后,实际数据还存在于数据库中,只是字段isDel值改变了,虽然如此,但是再通过MyBatisPlus查询数据的时候却会将其忽略,就好比不存在一般。

即通过逻辑删除的数据和物理删除的外在表现是一致的,只是内在机理不同罢了。

枚举自动注入

第一种方式 使用注解@EnumValue 使用方式:定义普通枚举,并在其中定义多个属性,将该注解标注于其中一个枚举属性之上,即可实现自动映射,使用枚举name传递,实际入库的却是添加了注解的属性值,查询也是如此,可以将库中数据与添加注解的属性对应,从而获取到枚举值name。 第二种方式 MybatisPlus中定义了IEnum用来统筹管理所有的枚举类型,我们自定义的枚举只要实现IEnum接口即可,在MyBatisPlus初始化的时候,会自动在MyBatis中handler缓存中添加针对IEnum类型的处理器,我们的自定义的枚举均可使用这个处理器进行处理来实现自动映射。 步骤一:添加必要的配置 mybatis-plus.type-enums-package:com.example.springbootdemo.enums 步骤二:自定义枚举 publicenumAnimalTypeimplementsIEnum{ CAT("1","猫"),DOG("2","狗"),TIGER("3","虎"),MOUSE("4","鼠"),MONKEY("5","猴"),LOAN("6","狮"),OTHER("7","其他"); privatefinalStringvalue; privatefinalStringdesc; AnimalType(finalStringvalue,finalStringdesc){ this.value=value; this.desc=desc; } @Override publicSerializablegetValue(){ returnvalue; } publicStringgetDesc(){ returndesc; } }

注意:一定要实现IEnum接口,否则无法实现自动注入。

Sql自动注入

性能分析插件

第一步:添加必要的配置 @EnableTransactionManagement @Configuration @MapperScan("com.example.springbootdemo.plusmapper") publicclassMyBatisPlusConfig{ //... //sql执行效率插件(性能分析插件) @Bean @Profile({"dev","test"})//设置devtest环境开启 publicPerformanceInterceptorperformanceInterceptor(){ returnnewPerformanceInterceptor(); } }

说明:

性能分析拦截器,用于输出每条SQL语句及其执行时间: maxTime:SQL执行最大时长,超过自动停止运行,有助于发现问题。 format:SQLSQL是否格式化,默认false。

注意:性能分析工具最好不要在生产环境部署,只在开发、测试环境部署用于查找问题即可。

乐观锁插件

第一步:添加必要的配置 @EnableTransactionManagement @Configuration @MapperScan("com.example.springbootdemo.plusmapper") publicclassMyBatisPlusConfig{ //... //mybatis-plus乐观锁插件 @Bean publicOptimisticLockerInterceptoroptimisticLockerInterceptor(){ returnnewOptimisticLockerInterceptor(); } } 第二步:添加@Version @Version privateintversion;

注意:

@Version支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime; 整数类型下newVersion=oldVersion+1; newVersion会回写到entity中 仅支持updateById(id)与update(entity,wrapper)方法 在update(entity,wrapper)方法下,wrapper不能复用!!!

实体主键配置

@Getter publicenumIdType{ /** *数据库ID自增 */ AUTO(0), /** *该类型为未设置主键类型 */ NONE(1), /** *用户输入ID *该类型可以通过自己注册自动填充插件进行填充 */ INPUT(2), /*以下3种类型、只有当插入对象ID为空,才自动填充。*/ /** *全局唯一ID(idWorker) */ ID_WORKER(3), /** *全局唯一ID(UUID) */ UUID(4), /** *字符串全局唯一ID(idWorker的字符串表示) */ ID_WORKER_STR(5); privateintkey; IdType(intkey){ this.key=key; } } AUTO:自增,适用于类似MySQL之类自增主键的情况 NONE:不设置??? INPUT:通过第三方进行逐渐递增,类似Oracle数据库的队列自增 ID_WORKER:全局唯一ID,当插入对象ID为空时,自动填充 UUID:全局唯一ID,当插入对象ID为空时,自动填充,一般情况下UUID是无序的 ID_WORKER_STR:字符串全局唯一ID,当插入对象ID为空时,自动填充

注意事项

最好不要和devTools一起使用,因为devTools中的RestartClassLoader会导致MyBatisPlus中的枚举自动映射失败,因为类加载器的不同从而在MyBatis的TypeHasnlerRegistry的TYPE_HANDLER_MAP集合中找不到对应的枚举类型(存在这个枚举类型,只不过是用AppClassLoader加载的,不同的加载器导致类型不同) MyBatisPlus和JPA分页有些不同,前者从1开始计页数,后者则是从0开始。

本文内容总结:SpringBoot整合MyBatis-plus,步骤,第一步:添加必要的依赖,第二步:添加必要的配置,第三步:添加必要的配置类,第四步:定义实体,第五步:定义mapper接口,第六步:定义service(重点),第七步:定义controller,高级功能,代码生成器,分页插件,逻辑删除,枚举自动注入,Sql自动注入,性能分析插件,乐观锁插件,实体主键配置,注意事项,

原文链接:https://www.cnblogs.com/V1haoge/p/10125279.html