SpringBoot整合MyBatis-plus

SpringBoot整合MyBatis-plus

步驟

第一步:添加必要的依賴

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

<code><dependency>
<groupid>com.baomidou/<groupid>
<artifactid>mybatis-plus/<artifactid>
<version>2.1.8/<version>
/<dependency>/<code>

第二種是直接添加mybatis-plus的starter,它會自動導入mybatis的依賴包及其他相關依賴包

<code><dependency>
<groupid>com.baomidou/<groupid>
<artifactid>mybatis-plus-boot-starter/<artifactid>
<version>3.0.1/<version>
/<dependency>/<code>

第二步:添加必要的配置

注意:Mybatis-plus是MyBatis的再封裝,添加MyBatis-plus之後我們的設置針對的應該是MyBatis-plus,而不是MyBatis。

<code>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/<code>

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

<code>@EnableTransactionManagement
@Configuration
@MapperScan("com.example.springbootdemo.plusmapper")
public class MyBatisPlusConfig {

// mybatis-plus分頁插件
@Bean
public PaginationInterceptor paginationInterceptor() {

return new PaginationInterceptor();
}

}/<code>

第四步:定義實體

<code>@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;
}/<code>
<code>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;
}
}/<code>
<code>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;
}
}/<code>

第五步:定義mapper接口

<code>public interface AnimalRepository extends BaseMapper<animal> {
}/<animal>/<code>

解說:使用MyBatis Plus後Mapper只要繼承BaseMapper接口即可,即使不添加XML映射文件也可以實現該接口提供的增刪改查功能,還可以配合Wrapper進行條件操作,當然這些操作都僅僅限於單表操作,一旦涉及多表聯查,那麼還是乖乖添加**Mapper.xml來自定義SQL吧!!!

第六步:定義service(重點)

<code>@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> 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>> getAnimals(final Animal animal){
return ResponseEntity.ok(animalRepository.selectList(packWrapper(animal, WrapperType.QUERY)));

}

public ResponseEntity<list>> getAnimalsByIds(List<integer> ids){
return ResponseEntity.ok(animalRepository.selectBatchIds(ids));
}

public ResponseEntity<list>> getAnimalsByMap(final Animal animal){
Map<string> 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>>> 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>> 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;
}/<animal>/<animal>/<animal>/<animal>/<animal>/<animal>/<animal>/<animal>/<animal>/<page>/<integer>/<list>/<string>/<list>/<integer>/<list>/<list>/<animal>/<animal>/<animal>/<animal>/<integer>/<integer>/<string>/<integer>/<integer>/<integer>/<integer>/<integer>/<animal>/<code>

第七步:定義controller

<code>@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>> 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);
}
}/<integer>/<page>/<animal>/<integer>/<integer>/<integer>/<integer>/<animal>/<code>

高級功能

代碼生成器

分頁插件

第一步:添加必要的配置

<code>@EnableTransactionManagement
@Configuration
@MapperScan("com.example.springbootdemo.plusmapper")
public class MyBatisPlusConfig {
@Bean // mybatis-plus分頁插件
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}/<code>

第二步:添加Mapper

<code>public interface AnimalRepository extends BaseMapper<animal> {
}/<animal>/<code>

第三步:添加service

<code>@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);
}
}/<animal>/<animal>/<code>

邏輯刪除

<code>所謂邏輯刪除是相對於物理刪除而言的,MyBatis Plus默認的刪除操作是物理刪除,即直接調用數據庫的delete操作,直接將數據從數據庫刪除,但是,一般情況下,我們在項目中不會直接操作delete,為了保留記錄,我們只是將其標記為刪除,並不是真的刪除,也就是需要邏輯刪除,MyBatis Plus也提供了實現邏輯刪除的功能,通過這種方式可以將底層的delete操作修改成update操作。/<code>

第一步:添加必要的配置

<code>mybatis-plus:
global-config:
db-config:
logic-delete-value: 1 # 邏輯已刪除值(默認為 1)
logic-not-delete-value: 0 # 邏輯未刪除值(默認為 0)/<code>

第二步:添加必要的配置類

<code>@Configuration
public class MyBatisPlusConfiguration {


@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
}/<code>

第三步:添加字段isDel和註解

<code>@TableLogic
private Integer isDel;/<code>
<code>如此一來,我們再執行delete相關操作的時候,底層就會變更為update操作,將isDel值修改為1。/<code>

注意:通過此種方式刪除數據後,實際數據還存在於數據庫中,只是字段isDel值改變了,雖然如此,但是再通過MyBatis Plus查詢數據的時候卻會將其忽略,就好比不存在一般。 即通過邏輯刪除的數據和物理刪除的外在表現是一致的,只是內在機理不同罷了。

枚舉自動注入

第一種方式

<code>使用註解@EnumValue
使用方式:定義普通枚舉,並在其中定義多個屬性,將該註解標註於其中一個枚舉屬性之上,即可實現自動映射,使用枚舉name傳遞,實際入庫的卻是添加了註解的屬性值,查詢也是如此,可以將庫中數據與添加註解的屬性對應,從而獲取到枚舉值name。/<code>

第二種方式

<code>Mybatis Plus中定義了IEnum用來統籌管理所有的枚舉類型,我們自定義的枚舉只要實現IEnum接口即可,在MyBatis Plus初始化的時候,會自動在MyBatis中handler緩存中添加針對IEnum類型的處理器,我們的自定義的枚舉均可使用這個處理器進行處理來實現自動映射。/<code>

步驟一:添加必要的配置

<code>mybatis-plus.type-enums-package: com.example.springbootdemo.enums/<code>

步驟二:自定義枚舉

<code>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;
}
}/<code>

注意:一定要實現IEnum接口,否則無法實現自動注入。

Sql自動注入

性能分析插件

第一步:添加必要的配置

<code>@EnableTransactionManagement
@Configuration
@MapperScan("com.example.springbootdemo.plusmapper")
public class MyBatisPlusConfig {
//...
//sql執行效率插件(性能分析插件)
@Bean
@Profile({"dev","test"})// 設置 dev test 環境開啟
public PerformanceInterceptor performanceInterceptor() {
return new PerformanceInterceptor();
}
}/<code>

說明: 性能分析攔截器,用於輸出每條 SQL 語句及其執行時間:

maxTime:SQL 執行最大時長,超過自動停止運行,有助於發現問題。 format:SQL SQL是否格式化,默認false。

注意:性能分析工具最好不要在生產環境部署,只在開發、測試環境部署用於查找問題即可。

樂觀鎖插件

第一步:添加必要的配置

<code>@EnableTransactionManagement
@Configuration
@MapperScan("com.example.springbootdemo.plusmapper")
public class MyBatisPlusConfig {
//...
// mybatis-plus樂觀鎖插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}/<code>

第二步:添加@Version

<code>@Version
private int version;/<code>

注意:

@Version支持的數據類型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime; 整數類型下 newVersion = oldVersion + 1; newVersion 會回寫到 entity 中 僅支持 updateById(id) 與 update(entity, wrapper) 方法 在 update(entity, wrapper) 方法下, wrapper 不能複用!!!

實體主鍵配置

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

原創作品,可以轉載,但是請標註出處地址:https://www.cnblogs.com/V1haoge/p/10125279.html


分享到:


相關文章: