原创做品,能够转载,可是请标注出处地址:http://www.javashuo.com/article/p-vrxdqbxt-bc.htmlhtml
第一种是在已存在MyBatis的状况下,直接添加mybatis-plus包便可。java
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>2.1.8</version> </dependency>
第二种是直接添加mybatis-plus的starter,它会自动导入mybatis的依赖包及其余相关依赖包spring
<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。sql
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; } }
public interface AnimalRepository extends BaseMapper<Animal> { }
解说:使用MyBatis Plus后Mapper只要继承BaseMapper接口便可,即便不添加XML映射文件也能够实现该接口提供的增删改查功能,还能够配合Wrapper进行条件操做,固然这些操做都仅仅限于单表操做,一旦涉及多表联查,那么仍是乖乖添加**Mapper.xml来自定义SQL吧!!!数据库
@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; }
@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(); } }
public interface AnimalRepository extends BaseMapper<Animal> { }
@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(); } }
@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接口,不然没法实现自动注入。springboot
@EnableTransactionManagement @Configuration @MapperScan("com.example.springbootdemo.plusmapper") public class MyBatisPlusConfig { //... //sql执行效率插件(性能分析插件) @Bean @Profile({"dev","test"})// 设置 dev test 环境开启 public PerformanceInterceptor performanceInterceptor() { return new PerformanceInterceptor(); } }
说明:
性能分析拦截器,用于输出每条 SQL 语句及其执行时间:mybatis
- maxTime:SQL 执行最大时长,超过自动中止运行,有助于发现问题。
- format:SQL SQL是否格式化,默认false。
注意:性能分析工具最好不要在生产环境部署,只在开发、测试环境部署用于查找问题便可。app
@EnableTransactionManagement @Configuration @MapperScan("com.example.springbootdemo.plusmapper") public class MyBatisPlusConfig { //... // mybatis-plus乐观锁插件 @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); } }
@Version private int version;
注意:ide
- @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; } }
ID_WORKER_STR:字符串全局惟一ID,当插入对象ID为空时,自动填充
最好不要和devTools一块儿使用,由于devTools中的RestartClassLoader会致使MyBatis Plus中的枚举自动映射失败,由于类加载器的不一样从而在MyBatis的TypeHasnlerRegistry的TYPE_HANDLER_MAP集合中找不到对应的枚举类型(存在这个枚举类型,只不过是用AppClassLoader加载的,不一样的加载器致使类型不一样) MyBatis Plus和JPA分页有些不一样,前者从1开始计页数,后者则是从0开始。