一.說明
Mybatis-Plus官網:mp.baomidou.com/
Mybatis-Plus是一個Mybatis框架的增強外掛,根據官方描述,MP只做增強不做改變,引入它不會對現有工程產生影響,如絲般順滑.並且只需簡單配置,即可快速進行 CRUD 操作,從而節省大量時間.程式碼生成,分頁,效能分析等功能一應俱全,最新已經更新到了3.1.1版本了,3.X系列支援lambda語法,讓我在寫條件構造的時候少了很多的"魔法值",從程式碼結構上更簡潔了.
二.專案環境
MyBatis-Plus版本: 3.1.0
SpringBoot版本:2.1.5
JDK版本:1.8
Maven依賴如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- mybatisPlus 核心庫 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.0</version>
</dependency>
<!-- 引入阿里資料庫連線池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.6</version>
</dependency>
</dependencies>
複製程式碼
配置如下:
# 配置埠
server:
port: 8081
spring:
# 配置資料來源
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mp_student?useUnicode=true&characterEncoding=utf-8
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
# mybatis-plus相關配置
mybatis-plus:
# xml掃描,多個目錄用逗號或者分號分隔(告訴 Mapper 所對應的 XML 檔案位置)
mapper-locations: classpath:mapper/*.xml
# 以下配置均有預設值,可以不設定
global-config:
db-config:
#主鍵型別 AUTO:"資料庫ID自增" INPUT:"使用者輸入ID",ID_WORKER:"全域性唯一ID (數字型別唯一ID)", UUID:"全域性唯一ID UUID";
id-type: auto
#欄位策略 IGNORED:"忽略判斷" NOT_NULL:"非 NULL 判斷") NOT_EMPTY:"非空判斷"
field-strategy: NOT_EMPTY
#資料庫型別
db-type: MYSQL
configuration:
# 是否開啟自動駝峰命名規則對映:從資料庫列名到Java屬性駝峰命名的類似對映
map-underscore-to-camel-case: true
# 返回map時true:當查詢資料為空時欄位返回為null,false:不加這個查詢資料為空時,欄位將被隱藏
call-setters-on-nulls: true
# 這個配置會將執行的sql列印出來,在開發或測試的時候可以用
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
複製程式碼
表結構:
CREATE TABLE `user_info` (
`id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`name` varchar(32) DEFAULT NULL COMMENT '姓名',
`age` int(11) DEFAULT NULL COMMENT '年齡',
`skill` varchar(32) DEFAULT NULL COMMENT '技能',
`evaluate` varchar(64) DEFAULT NULL COMMENT '評價',
`fraction` bigint(11) DEFAULT NULL COMMENT '分數',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COMMENT='學生資訊表';
複製程式碼
表資料:
INSERT INTO `user_info` VALUES (1, '小明', 20, '畫畫', '該學生在畫畫方面有一定天賦', 89);
INSERT INTO `user_info` VALUES (2, '小蘭', 19, '遊戲', '近期該學生由於遊戲的原因導致分數降低了', 64);
INSERT INTO `user_info` VALUES (3, '張張', 18, '英語', '近期該學生參加英語比賽獲得二等獎', 90);
INSERT INTO `user_info` VALUES (4, '大黃', 20, '體育', '該學生近期由於參加籃球比賽,導致腳傷', 76);
INSERT INTO `user_info` VALUES (5, '大白', 17, '繪畫', '該學生參加美術大賽獲得三等獎', 77);
INSERT INTO `user_info` VALUES (7, '小龍', 18, 'JAVA', '該學生是一個在改BUG的碼農', 59);
INSERT INTO `user_info` VALUES (9, 'Sans', 18, '睡覺', 'Sans是一個愛睡覺,並且身材較矮骨骼巨大的骷髏小胖子', 60);
INSERT INTO `user_info` VALUES (10, 'papyrus', 18, 'JAVA', 'Papyrus是一個講話大聲、個性張揚的骷髏,給人自信、有魅力的骷髏小瘦子', 58);
INSERT INTO `user_info` VALUES (11, '刪除資料1', 3, '畫肖像', NULL, 61);
INSERT INTO `user_info` VALUES (12, '刪除資料2', 3, NULL, NULL, 61);
INSERT INTO `user_info` VALUES (13, '刪除資料3', 3, NULL, NULL, 61);
INSERT INTO `user_info` VALUES (14, '刪除資料4', 5, '刪除', NULL, 10);
INSERT INTO `user_info` VALUES (15, '刪除資料5', 6, '刪除', NULL, 10);
複製程式碼
二.編寫基礎類
在啟動類上新增掃描DAO的註解
@SpringBootApplication
@MapperScan(basePackages = {"com.mp.demo.dao"}) //掃描DAO
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
複製程式碼
編寫Config配置類
/**
* @Description MybatisPlus配置類
* @Author Sans
* @CreateTime 2019/5/26 17:20
*/
@Configuration
public class MybatisPlusConfig {
/**
* mybatis-plus SQL執行效率外掛【生產環境可以關閉】
*/
@Bean
public PerformanceInterceptor performanceInterceptor() {
return new PerformanceInterceptor();
}
/**
* 分頁外掛
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
複製程式碼
編寫Entity類
/**
* @Description 學生資訊實體類
* @Author Sans
* @CreateTime 2019/5/26 21:41
*/
@Data
@TableName("user_info")//@TableName中的值對應著表名
public class UserInfoEntity {
/**
* 主鍵
* @TableId中可以決定主鍵的型別,不寫會採取預設值,預設值可以在yml中配置
* AUTO: 資料庫ID自增
* INPUT: 使用者輸入ID
* ID_WORKER: 全域性唯一ID,Long型別的主鍵
* ID_WORKER_STR: 字串全域性唯一ID
* UUID: 全域性唯一ID,UUID型別的主鍵
* NONE: 該型別為未設定主鍵型別
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 姓名
*/
private String name;
/**
* 年齡
*/
private Integer age;
/**
* 技能
*/
private String skill;
/**
* 評價
*/
private String evaluate;
/**
* 分數
*/
private Long fraction;
}
複製程式碼
編寫Dao類
/**
* @Description 使用者資訊DAO
* @Author Sans
* @CreateTime 2019/6/8 16:24
*/
public interface UserInfoDao extends BaseMapper<UserInfoEntity> {
}
複製程式碼
編寫Service類
/**
* @Description 使用者業務介面
* @Author Sans
* @CreateTime 2019/6/8 16:26
*/
public interface UserInfoService extends IService<UserInfoEntity> {
}
複製程式碼
編寫ServiceImpl類
/**
* @Description 使用者業務實現
* @Author Sans
* @CreateTime 2019/6/8 16:26
*/
@Service
@Transactional
public class UserInfoSerivceImpl extends ServiceImpl<UserInfoDao, UserInfoEntity> implements UserInfoService {
}
複製程式碼
三.MyBatis-Plus基礎演示
這裡我們看到,service中我們沒有寫任何方法,MyBatis-Plus官方封裝了許多基本CRUD的方法,可以直接使用大量節約時間,MP共通方法詳見IService,ServiceImpl,BaseMapper原始碼,寫入操作在ServiceImpl中已有事務繫結,這裡我們舉一些常用的方法演示.
/**
* @Description UserInfoController
* @Author Sans
* @CreateTime 2019/6/8 16:27
*/
@RestController
@RequestMapping("/userInfo")
public class UserInfoController {
@Autowired
private UserInfoService userInfoService;
/**
* 根據ID獲取使用者資訊
* @Author Sans
* @CreateTime 2019/6/8 16:34
* @Param userId 使用者ID
* @Return UserInfoEntity 使用者實體
*/
@RequestMapping("/getInfo")
public UserInfoEntity getInfo(String userId){
UserInfoEntity userInfoEntity = userInfoService.getById(userId);
return userInfoEntity;
}
/**
* 查詢全部資訊
* @Author Sans
* @CreateTime 2019/6/8 16:35
* @Param userId 使用者ID
* @Return List<UserInfoEntity> 使用者實體集合
*/
@RequestMapping("/getList")
public List<UserInfoEntity> getList(){
List<UserInfoEntity> userInfoEntityList = userInfoService.list();
return userInfoEntityList;
}
/**
* 分頁查詢全部資料
* @Author Sans
* @CreateTime 2019/6/8 16:37
* @Return IPage<UserInfoEntity> 分頁資料
*/
@RequestMapping("/getInfoListPage")
public IPage<UserInfoEntity> getInfoListPage(){
//需要在Config配置類中配置分頁外掛
IPage<UserInfoEntity> page = new Page<>();
page.setCurrent(5); //當前頁
page.setSize(1); //每頁條數
page = userInfoService.page(page);
return page;
}
/**
* 根據指定欄位查詢使用者資訊集合
* @Author Sans
* @CreateTime 2019/6/8 16:39
* @Return Collection<UserInfoEntity> 使用者實體集合
*/
@RequestMapping("/getListMap")
public Collection<UserInfoEntity> getListMap(){
Map<String,Object> map = new HashMap<>();
//kay是欄位名 value是欄位值
map.put("age",20);
Collection<UserInfoEntity> userInfoEntityList = userInfoService.listByMap(map);
return userInfoEntityList;
}
/**
* 新增使用者資訊
* @Author Sans
* @CreateTime 2019/6/8 16:40
*/
@RequestMapping("/saveInfo")
public void saveInfo(){
UserInfoEntity userInfoEntity = new UserInfoEntity();
userInfoEntity.setName("小龍");
userInfoEntity.setSkill("JAVA");
userInfoEntity.setAge(18);
userInfoEntity.setFraction(59L);
userInfoEntity.setEvaluate("該學生是一個在改BUG的碼農");
userInfoService.save(userInfoEntity);
}
/**
* 批量新增使用者資訊
* @Author Sans
* @CreateTime 2019/6/8 16:42
*/
@RequestMapping("/saveInfoList")
public void saveInfoList(){
//建立物件
UserInfoEntity sans = new UserInfoEntity();
sans.setName("Sans");
sans.setSkill("睡覺");
sans.setAge(18);
sans.setFraction(60L);
sans.setEvaluate("Sans是一個愛睡覺,並且身材較矮骨骼巨大的骷髏小胖子");
UserInfoEntity papyrus = new UserInfoEntity();
papyrus.setName("papyrus");
papyrus.setSkill("JAVA");
papyrus.setAge(18);
papyrus.setFraction(58L);
papyrus.setEvaluate("Papyrus是一個講話大聲、個性張揚的骷髏,給人自信、有魅力的骷髏小瘦子");
//批量儲存
List<UserInfoEntity> list =new ArrayList<>();
list.add(sans);
list.add(papyrus);
userInfoService.saveBatch(list);
}
/**
* 更新使用者資訊
* @Author Sans
* @CreateTime 2019/6/8 16:47
*/
@RequestMapping("/updateInfo")
public void updateInfo(){
//根據實體中的ID去更新,其他欄位如果值為null則不會更新該欄位,參考yml配置檔案
UserInfoEntity userInfoEntity = new UserInfoEntity();
userInfoEntity.setId(1L);
userInfoEntity.setAge(19);
userInfoService.updateById(userInfoEntity);
}
/**
* 新增或者更新使用者資訊
* @Author Sans
* @CreateTime 2019/6/8 16:50
*/
@RequestMapping("/saveOrUpdateInfo")
public void saveOrUpdate(){
//傳入的實體類userInfoEntity中ID為null就會新增(ID自增)
//實體類ID值存在,如果資料庫存在ID就會更新,如果不存在就會新增
UserInfoEntity userInfoEntity = new UserInfoEntity();
userInfoEntity.setId(1L);
userInfoEntity.setAge(20);
userInfoService.saveOrUpdate(userInfoEntity);
}
/**
* 根據ID刪除使用者資訊
* @Author Sans
* @CreateTime 2019/6/8 16:52
*/
@RequestMapping("/deleteInfo")
public void deleteInfo(String userId){
userInfoService.removeById(userId);
}
/**
* 根據ID批量刪除使用者資訊
* @Author Sans
* @CreateTime 2019/6/8 16:55
*/
@RequestMapping("/deleteInfoList")
public void deleteInfoList(){
List<String> userIdlist = new ArrayList<>();
userIdlist.add("12");
userIdlist.add("13");
userInfoService.removeByIds(userIdlist);
}
/**
* 根據指定欄位刪除使用者資訊
* @Author Sans
* @CreateTime 2019/6/8 16:57
*/
@RequestMapping("/deleteInfoMap")
public void deleteInfoMap(){
//kay是欄位名 value是欄位值
Map<String,Object> map = new HashMap<>();
map.put("skill","刪除");
map.put("fraction",10L);
userInfoService.removeByMap(map);
}
}
複製程式碼
四.MyBatis-Plus的QueryWrapper條件構造器
當查詢條件複雜的時候,我們可以使用MP的條件構造器,請參考下面的QueryWrapper條件引數說明
查詢方式 | 方法說明 |
---|---|
setSqlSelect | 設定 SELECT 查詢欄位 |
where | WHERE 語句,拼接 + WHERE 條件 |
and | AND 語句,拼接 + AND 欄位=值 |
or | OR 語句,拼接 + OR 欄位=值 |
eq | 等於= |
allEq | 基於 map 內容等於= |
ne | 不等於<> |
gt | 大於> |
ge | 大於等於>= |
lt | 小於< |
le | 小於等於<= |
like | 模糊查詢 LIKE |
notLike | 模糊查詢 NOT LIKE |
in | IN 查詢 |
notIn | NOT IN 查詢 |
isNull | NULL 值查詢 |
isNotNull | IS NOT NULL |
groupBy | 分組 GROUP BY |
having | HAVING 關鍵詞 |
orderBy | 排序 ORDER BY |
orderByAsc | ASC 排序 ORDER BY |
orderByDesc | DESC 排序 ORDER BY |
exists | EXISTS 條件語句 |
notExists | NOT EXISTS 條件語句 |
between | BETWEEN 條件語句 |
notBetween | NOT BETWEEN 條件語句 |
addFilter | 自由拼接 SQL |
last | 拼接在最後,例如:last("LIMIT 1") |
下面我們來舉一些常見的示例
/**
* @Description UserInfoPlusController
* @Author Sans
* @CreateTime 2019/6/9 14:52
*/
@RestController
@RequestMapping("/userInfoPlus")
public class UserInfoPlusController {
@Autowired
private UserInfoService userInfoService;
/**
* MP擴充套件演示
* @Author Sans
* @CreateTime 2019/6/8 16:37
* @Return Map<String,Object> 返回資料
*/
@RequestMapping("/getInfoListPlus")
public Map<String,Object> getInfoListPage(){
//初始化返回類
Map<String,Object> result = new HashMap<>();
//查詢年齡等於18歲的學生
//等價SQL: SELECT id,name,age,skill,evaluate,fraction FROM user_info WHERE age = 18
QueryWrapper<UserInfoEntity> queryWrapper1 = new QueryWrapper<>();
queryWrapper1.lambda().eq(UserInfoEntity::getAge,18);
List<UserInfoEntity> userInfoEntityList1 = userInfoService.list(queryWrapper1);
result.put("studentAge18",userInfoEntityList1);
//查詢年齡大於5歲的學生且小於等於18歲的學生
//等價SQL: SELECT id,name,age,skill,evaluate,fraction FROM user_info WHERE age > 5 AND age <= 18
QueryWrapper<UserInfoEntity> queryWrapper2 = new QueryWrapper<>();
queryWrapper2.lambda().gt(UserInfoEntity::getAge,5);
queryWrapper2.lambda().le(UserInfoEntity::getAge,18);
List<UserInfoEntity> userInfoEntityList2 = userInfoService.list(queryWrapper2);
result.put("studentAge5",userInfoEntityList2);
//模糊查詢技能欄位帶有"畫"的資料,並按照年齡降序
//等價SQL: SELECT id,name,age,skill,evaluate,fraction FROM user_info WHERE skill LIKE '%畫%' ORDER BY age DESC
QueryWrapper<UserInfoEntity> queryWrapper3 = new QueryWrapper<>();
queryWrapper3.lambda().like(UserInfoEntity::getSkill,"畫");
queryWrapper3.lambda().orderByDesc(UserInfoEntity::getAge);
List<UserInfoEntity> userInfoEntityList3 = userInfoService.list(queryWrapper3);
result.put("studentAgeSkill",userInfoEntityList3);
//模糊查詢名字帶有"小"或者年齡大於18的學生
//等價SQL: SELECT id,name,age,skill,evaluate,fraction FROM user_info WHERE name LIKE '%小%' OR age > 18
QueryWrapper<UserInfoEntity> queryWrapper4 = new QueryWrapper<>();
queryWrapper4.lambda().like(UserInfoEntity::getName,"小");
queryWrapper4.lambda().or().gt(UserInfoEntity::getAge,18);
List<UserInfoEntity> userInfoEntityList4 = userInfoService.list(queryWrapper4);
result.put("studentOr",userInfoEntityList4);
//查詢評價不為null的學生,並且分頁
//等價SQL: SELECT id,name,age,skill,evaluate,fraction FROM user_info WHERE evaluate IS NOT NULL LIMIT 0,5
IPage<UserInfoEntity> page = new Page<>();
page.setCurrent(1);
page.setSize(5);
QueryWrapper<UserInfoEntity> queryWrapper5 = new QueryWrapper<>();
queryWrapper5.lambda().isNotNull(UserInfoEntity::getEvaluate);
page = userInfoService.page(page,queryWrapper5);
result.put("studentPage",page);
return result;
}
}
複製程式碼
五.自定義SQL
引入Mybatis-Plus不會對專案現有的 Mybatis 構架產生任何影響,而且Mybatis-Plus支援所有 Mybatis 原生的特性,這也是我喜歡使用它的原因之一,由於某些業務複雜,我們可能要自己去寫一些比較複雜的SQL語句,我們舉一個簡單的例子來演示自定義SQL.
示例:查詢大於設定分數的學生(分數為動態輸入,且有分頁)
編寫Mapper.xml檔案
<mapper namespace="com.mp.demo.dao.UserInfoDao">
<!-- Sans 2019/6/9 14:35 -->
<select id="selectUserInfoByGtFraction" resultType="com.mp.demo.entity.UserInfoEntity" parameterType="long">
SELECT * FROM user_info WHERE fraction > #{fraction}
</select>
</mapper>
複製程式碼
在DAO中加入方法
/**
* 查詢大於該分數的學生
* @Author Sans
* @CreateTime 2019/6/9 14:28
* @Param page 分頁引數
* @Param fraction 分數
* @Return IPage<UserInfoEntity> 分頁資料
*/
IPage<UserInfoEntity> selectUserInfoByGtFraction(IPage<UserInfoEntity> page, Long fraction);
複製程式碼
在service加入方法
/**
* 查詢大於該分數的學生
* @Author Sans
* @CreateTime 2019/6/9 14:27
* @Param page 分頁引數
* @Param fraction 分數
* @Return IPage<UserInfoEntity> 分頁資料
*/
IPage<UserInfoEntity> selectUserInfoByGtFraction(IPage<UserInfoEntity> page,Long fraction);
複製程式碼
在serviceImpl加入方法
/**
* 查詢大於該分數的學生
* @Author Sans
* @CreateTime 2019/6/9 14:27
* @Param page 分頁引數
* @Param fraction 分數
* @Return IPage<UserInfoEntity> 分頁資料
*/
@Override
public IPage<UserInfoEntity> selectUserInfoByGtFraction(IPage<UserInfoEntity> page, Long fraction) {
return this.baseMapper.selectUserInfoByGtFraction(page,fraction);
}
複製程式碼
在Controller中測試
/**
* MP自定義SQL
* @Author Sans
* @CreateTime 2019/6/9 14:37
* @Return IPage<UserInfoEntity> 分頁資料
*/
@RequestMapping("/getInfoListSQL")
public IPage<UserInfoEntity> getInfoListSQL(){
//查詢大於60分以上的學生,並且分頁
IPage<UserInfoEntity> page = new Page<>();
page.setCurrent(1);
page.setSize(5);
page = userInfoService.selectUserInfoByGtFraction(page,60L);
return page;
}
複製程式碼
六.專案原始碼
專案原始碼: gitee.com/liselotte/s…
個人確實很喜歡用MyBatis-Plus,不僅節約時間,程式碼也簡潔乾淨,它給了我那時候從SSM到SpringBoot過度的那種感覺
嗯,這玩意真香~
謝謝大家閱讀,如果喜歡,請收藏點贊,文章不足之處,也請給出寶貴意見.