转载地址: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")
public class MyBatisPlusConfig {
// mybatis-plus分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
第四步:定义实体
@Data
@Builder
@ToString
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@TableName(value = "ANIMAL")
public class Animal {
@TableId(value = "ID",type = IdType.AUTO)
private Integer id;
@TableField(value = "NAME",exist = true)
private String name;
@TableField(value = "TYPE",exist = true)
private AnimalType type;
@TableField(value = "SEX",exist = true)
private AnimalSex sex;
@TableField(value = "MASTER",exist = true)
private String master;
}
public enum AnimalType implements IEnum {
CAT("1","猫"),DOG("2","狗"),TIGER("3","虎"),MOUSE("4","鼠"),MONKEY("5","猴"),LOAN("6","狮"),OTHER("7","其他");
private final String value;
private final String desc;
AnimalType(final String value,final String desc){
this.value=value;
this.desc = desc;
}
@Override
public Serializable getValue() {
return value;
}
public String getDesc() {
return desc;
}
}
public enum AnimalSex implements IEnum {
MALE("1","公"),FEMALE("2","母");
private final String value;
private final String desc;
AnimalSex(final String value,final String desc){
this.value = value;
this.desc = desc;
}
@Override
public Serializable getValue() {
return value;
}
public String getDesc() {
return desc;
}
}
第五步:定义mapper接口
public interface AnimalRepository extends BaseMapper<Animal> {
}
解说:使用MyBatis Plus后Mapper只要继承BaseMapper接口即可,即使不添加XML映射文件也可以实现该接口提供的增删改查功能,还可以配合Wrapper进行条件操作,当然这些操作都仅仅限于单表操作,一旦涉及多表联查,那么还是乖乖添加**Mapper.xml来自定义SQL吧!!!
第六步:定义service(重点)
@Service
@Log4j2
public class AnimalService {
@Autowired
private AnimalRepository animalRepository;
//增
public ResponseEntity<Animal> addAnimal(final Animal animal) {
animalRepository.insert(animal);
return ResponseEntity.ok(animal);
}
//删
public ResponseEntity<Integer> deleteAnimalById(final int id){
return ResponseEntity.ok(animalRepository.deleteById(id));
}
public ResponseEntity<Integer> deleteAnimals(final Animal animal){
return ResponseEntity.ok(animalRepository.delete(packWrapper(animal, WrapperType.QUERY)));
}
public ResponseEntity<Integer> deleteAnimalsByIds(List<Integer> ids){
return ResponseEntity.ok(animalRepository.deleteBatchIds(ids));
}
public ResponseEntity<Integer> deleteAnimalsByMap(final Animal animal){
Map<String, Object> params = new HashMap<>();
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());
}
return ResponseEntity.ok(animalRepository.deleteByMap(params));
}
//改
public ResponseEntity<Integer> updateAnimals(final Animal animal, final Animal condition){
return ResponseEntity.ok(animalRepository.update(animal, packWrapper(condition, WrapperType.UPDATE)));
}
public ResponseEntity<Integer> updateAnimal(final Animal animal){
Wrapper<Animal> animalWrapper = new UpdateWrapper<>();
((UpdateWrapper<Animal>) animalWrapper).eq("id",animal.getId());
return ResponseEntity.ok(animalRepository.update(animal, animalWrapper));
}
//查
public ResponseEntity<Animal> getAnimalById(final int id){
return ResponseEntity.ok(animalRepository.selectById(id));
}
public ResponseEntity<Animal> getOneAnimal(final Animal animal){
return ResponseEntity.ok(animalRepository.selectOne(packWrapper(animal, WrapperType.QUERY)));
}
public ResponseEntity<List<Animal>> getAnimals(final Animal animal){
return ResponseEntity.ok(animalRepository.selectList(packWrapper(animal, WrapperType.QUERY)));
}
public ResponseEntity<List<Animal>> getAnimalsByIds(List<Integer> ids){
return ResponseEntity.ok(animalRepository.selectBatchIds(ids));
}
public ResponseEntity<List<Animal>> getAnimalsByMap(final Animal animal){
Map<String, Object> params = new HashMap<>();
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());
}
return ResponseEntity.ok(animalRepository.selectByMap(params));
}
public ResponseEntity<List<Map<String, Object>>> getAnimalMaps(final Animal animal){
return ResponseEntity.ok(animalRepository.selectMaps(packWrapper(animal, WrapperType.QUERY)));
}
//查个数
public ResponseEntity<Integer> getCount(final Animal animal){
return ResponseEntity.ok(animalRepository.selectCount(packWrapper(animal, WrapperType.QUERY)));
}
//分页查询
public ResponseEntity<Page<Animal>> getAnimalPage(final Animal animal,final int pageId,final int pageSize){
Page<Animal> page = new Page<>();
page.setCurrent(pageId);
page.setSize(pageSize);
return ResponseEntity.ok((Page<Animal>) animalRepository.selectPage(page,packWrapper(animal, WrapperType.QUERY)));
}
private Wrapper<Animal> packWrapper(final Animal animal, WrapperType wrapperType){
switch (wrapperType){
case QUERY:
QueryWrapper<Animal> wrapper = new QueryWrapper<>();
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());
return wrapper;
case UPDATE:
UpdateWrapper<Animal> wrapper2 = new UpdateWrapper<>();
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());
return wrapper2;
case QUERYLAMBDA:
LambdaQueryWrapper<Animal> wrapper3 = new QueryWrapper<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());
return wrapper3;
case UPDATELAMBDA:
LambdaUpdateWrapper<Animal> wrapper4 = new UpdateWrapper<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());
return wrapper4;
default:return null;
}
}
}
enum WrapperType{
UPDATE,UPDATELAMBDA,QUERY,QUERYLAMBDA;
}
第七步:定义controller
@RestController
@RequestMapping("animal")
@Api(description = "动物接口")
@Log4j2
public class AnimalApi {
@Autowired
private AnimalService animalService;
@RequestMapping(value = "addAnimal",method = RequestMethod.PUT)
@ApiOperation(value = "添加动物",notes = "添加动物",httpMethod = "PUT")
public ResponseEntity<Animal> addAnimal(final Animal animal){
return animalService.addAnimal(animal);
}
@RequestMapping(value = "deleteAnimalById", method = RequestMethod.DELETE)
@ApiOperation(value = "删除一个动物",notes = "根据ID删除动物",httpMethod = "DELETE")
public ResponseEntity<Integer> deleteAnimalById(final int id){
return animalService.deleteAnimalById(id);
}
@RequestMapping(value = "deleteAnimalsByIds",method = RequestMethod.DELETE)
@ApiOperation(value = "删除多个动物",notes = "根据Id删除多个动物",httpMethod = "DELETE")
public ResponseEntity<Integer> deleteAnimalsByIds(Integer[] ids){
return animalService.deleteAnimalsByIds(Arrays.asList(ids));
}
@RequestMapping(value = "deleteAnimals", method = RequestMethod.DELETE)
@ApiOperation(value = "删除动物",notes = "根据条件删除动物",httpMethod = "DELETE")
public ResponseEntity<Integer> deleteAnimalsByMaps(final Animal animal){
return animalService.deleteAnimalsByMap(animal);
}
@RequestMapping(value = "deleteAnimals2", method = RequestMethod.DELETE)
@ApiOperation(value = "删除动物",notes = "根据条件删除动物",httpMethod = "DELETE")
public ResponseEntity<Integer> deleteAnimals(final Animal animal){
return animalService.deleteAnimals(animal);
}
@RequestMapping(value = "getAnimalById",method = RequestMethod.GET)
@ApiOperation(value = "获取一个动物",notes = "根据ID获取一个动物",httpMethod = "GET")
public ResponseEntity<Animal> getAnimalById(final int id){
return animalService.getAnimalById(id);
}
// 注意,这里参数animal不能用RequstBody标注,否则接收不到参数
// @RequestBody只能用在只有一个参数模型的方法中,用于将所有请求体中携带的参数全部映射到这个请求参数模型中
@RequestMapping(value = "getAnimalsByPage")
@ApiOperation(value = "分页获取动物们",notes = "分页获取所有动物", httpMethod = "GET")
public ResponseEntity<Page<Animal>> getAnimalsByPage(@RequestParam final int pageId, @RequestParam final int pageSize, final Animal animal) {
return animalService.getAnimalPage(animal==null?Animal.builder().build():animal, pageId, pageSize);
}
@RequestMapping(value = "updateAnimal")
@ApiOperation(value = "更新动物", notes = "根据条件更新",httpMethod = "POST")
public ResponseEntity<Integer> updateAnimals(final Animal animal){
return animalService.updateAnimal(animal);
}
}
高级功能
代码生成器
分页插件
第一步:添加必要的配置
@EnableTransactionManagement
@Configuration
@MapperScan("com.example.springbootdemo.plusmapper")
public class MyBatisPlusConfig {
@Bean // mybatis-plus分页插件
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
第二步:添加Mapper
public interface AnimalRepository extends BaseMapper<Animal> {
}
第三步:添加service
@Service
@Log4j2
public class AnimalService {
@Autowired
private AnimalRepository animalRepository;
//...
public Page<Animal> getAnimalsByPage(int pageId,int pageSize) {
Page page = new Page(pageId, pageSize);
return (Page<Animal>)animalRepository.selectPage(page,null);
}
}
逻辑删除
所谓逻辑删除是相对于物理删除而言的,MyBatis Plus默认的删除操作是物理删除,即直接调用数据库的delete操作,直接将数据从数据库删除,但是,一般情况下,我们在项目中不会直接操作delete,为了保留记录,我们只是将其标记为删除,并不是真的删除,也就是需要逻辑删除,MyBatis Plus也提供了实现逻辑删除的功能,通过这种方式可以将底层的delete操作修改成update操作。
第一步:添加必要的配置
mybatis-plus:
global-config:
db-config:
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
第二步:添加必要的配置类
@Configuration
public class MyBatisPlusConfiguration {
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
}
第三步:添加字段isDel和注解
@TableLogic
private Integer isDel;
如此一来,我们再执行delete相关操作的时候,底层就会变更为update操作,将isDel值修改为1。
注意:通过此种方式删除数据后,实际数据还存在于数据库中,只是字段isDel值改变了,虽然如此,但是再通过MyBatis Plus查询数据的时候却会将其忽略,就好比不存在一般。
即通过逻辑删除的数据和物理删除的外在表现是一致的,只是内在机理不同罢了。
枚举自动注入
第一种方式
使用注解@EnumValue
使用方式:定义普通枚举,并在其中定义多个属性,将该注解标注于其中一个枚举属性之上,即可实现自动映射,使用枚举name传递,实际入库的却是添加了注解的属性值,查询也是如此,可以将库中数据与添加注解的属性对应,从而获取到枚举值name。
第二种方式
Mybatis Plus中定义了IEnum用来统筹管理所有的枚举类型,我们自定义的枚举只要实现IEnum接口即可,在MyBatis Plus初始化的时候,会自动在MyBatis中handler缓存中添加针对IEnum类型的处理器,我们的自定义的枚举均可使用这个处理器进行处理来实现自动映射。
步骤一:添加必要的配置
mybatis-plus.type-enums-package: com.example.springbootdemo.enums
步骤二:自定义枚举
public enum AnimalType implements IEnum {
CAT("1","猫"),DOG("2","狗"),TIGER("3","虎"),MOUSE("4","鼠"),MONKEY("5","猴"),LOAN("6","狮"),OTHER("7","其他");
private final String value;
private final String desc;
AnimalType(final String value,final String desc){
this.value=value;
this.desc = desc;
}
@Override
public Serializable getValue() {
return value;
}
public String getDesc() {
return desc;
}
}
注意:一定要实现IEnum接口,否则无法实现自动注入。
Sql自动注入
性能分析插件
第一步:添加必要的配置
@EnableTransactionManagement
@Configuration
@MapperScan("com.example.springbootdemo.plusmapper")
public class MyBatisPlusConfig {
//...
//sql执行效率插件(性能分析插件)
@Bean
@Profile({"dev","test"})// 设置 dev test 环境开启
public PerformanceInterceptor performanceInterceptor() {
return new PerformanceInterceptor();
}
}
说明:
性能分析拦截器,用于输出每条 SQL 语句及其执行时间:
- maxTime:SQL 执行最大时长,超过自动停止运行,有助于发现问题。
- format:SQL SQL是否格式化,默认false。
注意:性能分析工具最好不要在生产环境部署,只在开发、测试环境部署用于查找问题即可。
乐观锁插件
第一步:添加必要的配置
@EnableTransactionManagement
@Configuration
@MapperScan("com.example.springbootdemo.plusmapper")
public class MyBatisPlusConfig {
//...
// mybatis-plus乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
第二步:添加@Version
@Version
private int version;
注意:
- @Version支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime;
- 整数类型下 newVersion = oldVersion + 1;
- newVersion 会回写到 entity 中
- 仅支持 updateById(id) 与 update(entity, wrapper) 方法
- 在 update(entity, wrapper) 方法下, wrapper 不能复用!!!
实体主键配置
@Getter
public enum IdType {
/**
* 数据库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);
private int key;
IdType(int key) {
this.key = key;
}
}
- AUTO:自增,适用于类似MySQL之类自增主键的情况
- NONE:不设置???
- INPUT:通过第三方进行逐渐递增,类似Oracle数据库的队列自增
- ID_WORKER:全局唯一ID,当插入对象ID为空时,自动填充
- UUID:全局唯一ID,当插入对象ID为空时,自动填充,一般情况下UUID是无序的
-
ID_WORKER_STR:字符串全局唯一ID,当插入对象ID为空时,自动填充
注意事项
最好不要和devTools一起使用,因为devTools中的RestartClassLoader会导致MyBatis Plus中的枚举自动映射失败,因为类加载器的不同从而在MyBatis的TypeHasnlerRegistry的TYPE_HANDLER_MAP集合中找不到对应的枚举类型(存在这个枚举类型,只不过是用AppClassLoader加载的,不同的加载器导致类型不同)
MyBatis Plus和JPA分页有些不同,前者从1开始计页数,后者则是从0开始。
相关推荐
让我们一起了解如何实现这个"SpringBoot整合MyBatis-Plus小Demo"。 首先,我们需要准备项目的基本结构。创建一个新的SpringBoot项目,引入MyBatis-Plus的相关依赖。在`pom.xml`文件中添加如下内容: ```xml ...
在SpringBoot项目中,整合Mybatis-Plus并实现多数据...以上就是SpringBoot整合Mybatis-Plus实现多数据源动态切换并支持分页查询的详细过程。这个实现方案能够有效地应对复杂的数据库环境,提高系统的灵活性和可扩展性。
本教程将深入探讨如何利用SpringBoot整合Mybatis-Plus,同时支持Oracle和MySQL数据库,并通过Nacos作为注册中心,以及使用Swagger2进行API文档的生成。 首先,让我们了解SpringBoot的核心优势。SpringBoot简化了...
至此,我们就完成了SpringBoot整合MyBatis-Plus实现多表分页查询的基本步骤。通过这种方式,我们可以轻松地处理复杂的关联查询,同时利用MyBatis-Plus的分页功能提高查询效率。记得在实际应用中根据需求调整关联关系...
在本文中,我们将深入探讨如何在SpringBoot项目中整合MyBatis-Plus并利用其逆向工程功能,以实现高效代码生成,从而提高开发效率。首先,MyBatis-Plus是一个针对MyBatis的增强工具,它在不改变MyBatis原有逻辑的基础...
以上就是SpringBoot整合MyBatis-Plus的基本步骤。通过这种方式,你可以充分利用SpringBoot的自动配置和MyBatis-Plus的便捷性,实现快速的数据库操作。在实际开发中,你还可以根据需求配置事务管理、自定义拦截器等...
shiro作为安全框架,主流技术 几乎零XML,极简配置 两套UI实现(bootstrap+layer ui),可以自由切换 报表后端采用技术: SpringBoot整合SSM(Spring+Mybatis-plus+ SpringMvc),spring security 全注解式的权限管理和...
本项目以"springboot+mybatis-plus+shardingsphere 实现读写分离"为主题,结合了Spring Boot的快速开发能力、MyBatis-Plus的简化数据操作以及ShardingSphere的分布式数据库解决方案,旨在提高系统的读取性能和可扩展...
在SpringBoot中整合MyBatis-Plus,需要引入对应的依赖,配置数据源、MyBatis和MyBatis-Plus的相关信息,然后创建Mapper接口和实体类,利用MyBatis-Plus提供的方法进行数据库操作。 在本案例中,可能包含了数据库...
项目【mall-tiny-master】适合初学者熟悉SpringBoot和MyBatis-Plus的整合应用,以及快速构建具有权限管理功能的后台系统。通过学习和实践这个项目,开发者可以掌握如何搭建后端服务、设计数据库模型、实现API接口、...
SpringBoot+mybatis-plus+VUE民宿管理系统后台-毕业设计 升级为mybatis-plus 加入启动页面类。 修改了一些VUE的其它问题。 本系列环境 环境 win11 工具 idea 2018 jdk 1.8 数据库 mysql5.5 maven 3.6.0 项目导入...
报表后端采用技术: SpringBoot整合SSM(Spring+Mybatis-plus+ SpringMvc),spring security 全注解式的权限管理和JWT方式禁用Session,采用redis存储token及权限信息 报表前端采用Bootstrap框架,结合Jquery Ajax,...
springboot + mybatis-plus + database+ 多数据源 + redis + hutool 框架干净,没有其他冗余的成分; 配置了MP的代码生成器,意见生成代码,节省开发时间! 可用于各种定时任务处理,各种夸库操作, 多数据源支持...
<artifactId>mybatis-plus-boot-starter <version>3.4.3 ``` 这里的版本号可能会随着MyBatis-Plus的更新而变化,确保使用的是最新稳定版。 接下来,创建实体类。例如,我们有一个用户实体类`User`: ```java ...
public class MybatisPlusConfig { } ``` 5. 编写Mapper接口 创建UserMapper接口,继承BaseMapper: ```java import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.springframework.stereotype....
<artifactId>mybatis-plus-boot-starter <version>3.5.1 ``` #### 四、新建表 接下来,我们将创建两张表用于分表存储。 ```sql CREATE TABLE `user_0` ( `cid` bigint(25) NOT NULL AUTO_INCREMENT, `name...
1、基于yml 配置方式 ,实现springBoot+sharding-jdbc+mybatis-plus 实现分库分表,读写分离,以及全局表,子表的配置。 2、实现mybatis-plus 整合到springboot 详细使用请看 测试用例
在本教程中,我们将深入探讨如何在Spring Boot项目中整合Mybatis-Plus,实现增、删、改、查(CRUD)操作,并结合Ajax和jQuery进行数据交互。首先,让我们了解下Spring Boot、Mybatis-Plus、Ajax以及jQuery的基础知识...
<artifactId>mybatis-plus-boot-starter <version>3.x.x <groupId>com.alibaba</groupId> <artifactId>easyexcel <version>2.x.x ``` 接下来,我们需要创建一个Excel实体类,这个类的字段应与Excel表头...