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

原創做品,能夠轉載,可是請標註出處地址:http://www.javashuo.com/article/p-vrxdqbxt-bc.htmlhtml

SpringBoot整合MyBatis-plus

步驟

第一步:添加必要的依賴

第一種是在已存在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;
    }
}

第五步:定義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接口,不然沒法實現自動注入。springboot

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 語句及其執行時間: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

@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;
    }
}
  • 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開始。

相關文章
相關標籤/搜索