提高生產(chǎn)力,最全 MyBatis Plus 講解!
如果你每天還在重復(fù)寫(xiě) CRUD 的 SQL,如果你對(duì)這些 SQL 已經(jīng)不耐煩了,那么你何不花費(fèi)一些時(shí)間來(lái)閱讀這篇文章,然后對(duì)已有的老項(xiàng)目進(jìn)行改造,必有收獲!
一、MP 是什么
MP 全稱 Mybatis-Plus ,套用官方的解釋便是成為 MyBatis 最好的搭檔,簡(jiǎn)稱基友。它是在 MyBatis 的基礎(chǔ)上只做增強(qiáng)不做改變,為簡(jiǎn)化開(kāi)發(fā)、提高效率而生。
1. 三大特性
1)潤(rùn)物無(wú)聲
只做增強(qiáng)不做改變,引入它不會(huì)對(duì)現(xiàn)有工程產(chǎn)生影響,如絲般順滑。
2)效率至上
只需簡(jiǎn)單配置,即可快速進(jìn)行單表 CRUD 操作,從而節(jié)省大量時(shí)間。
3)豐富功能
代碼生成、物理分頁(yè)、性能分析等功能一應(yīng)俱全。
2. 支持?jǐn)?shù)據(jù)庫(kù)
mysql 、mariadb 、oracle 、db2 、h2 、hsql 、sqlite 、postgresql 、sqlserver 、presto 、Gauss 、Firebird Phoenix 、clickhouse 、Sybase ASE 、 OceanBase 、達(dá)夢(mèng)數(shù)據(jù)庫(kù) 、虛谷數(shù)據(jù)庫(kù) 、人大金倉(cāng)數(shù)據(jù)庫(kù) 、南大通用數(shù)據(jù)庫(kù)
3. 框架結(jié)構(gòu)

實(shí)話說(shuō),以上這些內(nèi)容只要你打開(kāi)官網(wǎng)也能看到,那么我們接下來(lái)就先來(lái)實(shí)際操作一番!

二、MP實(shí)戰(zhàn)
1. 手摸手式項(xiàng)目練習(xí)
1)數(shù)據(jù)庫(kù)及表準(zhǔn)備
sql 語(yǔ)句:
use?test;
CREATE?TABLE?`student`??(
??`id`?int(0)?NOT?NULL?AUTO_INCREMENT,
??`dept_id`?int(0)?NULL?DEFAULT?NULL,
??`name`?varchar(16)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_bin?NULL?DEFAULT?NULL,
??`remark`?varchar(32)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_bin?NULL?DEFAULT?NULL,
??PRIMARY?KEY?(`id`)?USING?BTREE
)?ENGINE?=?InnoDB?AUTO_INCREMENT?=?7?CHARACTER?SET?=?utf8mb4?COLLATE?=?utf8mb4_bin?ROW_FORMAT?=?Dynamic;
--?----------------------------
--?Records?of?student
--?----------------------------
INSERT?INTO?`student`?VALUES?(1,?1,?'小菜',?'關(guān)注小菜不迷路!');
INSERT?INTO?`student`?VALUES?(2,?2,?'小明',?'好好學(xué)習(xí),天天向上!');
2)pom 依賴
<dependency>
????<groupId>org.springframework.bootgroupId>
????<artifactId>spring-boot-starter-testartifactId>
dependency>
<dependency>
????<groupId>org.projectlombokgroupId>
????<artifactId>lombokartifactId>
????<version>1.16.16version>
dependency>
<dependency>
????<groupId>com.baomidougroupId>
????<artifactId>mybatis-plus-boot-starterartifactId>
????<version>3.2.0version>
dependency>
<dependency>
????<groupId>mysqlgroupId>
????<artifactId>mysql-connector-javaartifactId>
????<version>8.0.21version>
dependency>
<dependency>
????<groupId>com.alibabagroupId>
????<artifactId>druidartifactId>
????<version>1.2.1version>
dependency>
<dependency>
????<groupId>junitgroupId>
????<artifactId>junitartifactId>
????<version>4.13.1version>
dependency>
3)配置文件
spring:
??datasource:
????url:?jdbc:mysql://localhost:3306/test
????username:?root
????password:?123456
????driver-class-name:?com.mysql.cj.jdbc.Driver
4)實(shí)體類
@Data
@Builder
@TableName("student")
public?class?User?{
????@TableId(type?=?IdType.AUTO)
????private?Integer?id;
????private?Integer?deptId;
????private?String?name;
????private?String?remark;
}
5)Mapper
public?interface?UserMapper?extends?BaseMapper<User>?{}
6)測(cè)試類
@RunWith(SpringRunner.class)
@SpringBootTest
public?class?MapperTest?{
????@Autowired
????private?UserMapper?userMapper;
????@Test
????public?void?getAll()?{
????????List?users?=?userMapper.selectList(null);
????????users.forEach(System.out::println);
????}
}
/**?OUTPUT:
User(id=1, deptId=1, name=小菜, remark=關(guān)注小菜不迷路!)
User(id=2, deptId=1, name=小明, remark=好好學(xué)習(xí),天天向上!)
**/
小菜結(jié):
在以上的結(jié)果,我們可以看到已經(jīng)打印出了數(shù)據(jù)庫(kù)中的全部數(shù)據(jù)(兩條)。而并沒(méi)有看到平時(shí)我們需要寫(xiě)的 mapper.xml 文件,只是用到了 usermapper 中的 selectList() 方法,而 UserMapper 繼承了 BaseMapper 這個(gè)接口,這個(gè)接口便是 MybatisPlus 提供給我們的,我們?cè)賮?lái)看下這個(gè)接口給我們提供了哪些方法。
2. ?CRUD 基操
1)insert
@Test
public?void?insert()?{
????//這里使用了?lombok?中的建造者模式構(gòu)建對(duì)象
????User?user?=?User.builder().deptId(1).name("小華").remark("小華愛(ài)學(xué)習(xí)").build();
????int?insertFlag?=?userMapper.insert(user);
????log.info("插入影響行數(shù),{}?|?小華的ID:?{}",?insertFlag,?user.getId());
}
/**?OUTPUT:
插入影響行數(shù),1?|?小華的ID:?8
**/
可以看到我們不僅插入了數(shù)據(jù),而且還獲取到了插入數(shù)據(jù)的ID,但是值得注意的是這里的 ID 雖然是自增的,但并非是 MP 默認(rèn)的 ID生成策略,而是我們?cè)趯?shí)體類中指定的:

在 MP 中支持的主鍵生成策略有以下幾種:

我們既然已經(jīng)看到了 @TableId 這個(gè)注解,那我們?cè)賮?lái)關(guān)注一個(gè)常用注解 @TableField
從注解名上我們就可以看出,@TableId 是用來(lái)標(biāo)記主鍵 ID 的,而 @TableField 是用來(lái)標(biāo)記其他字段的。

可以看得出來(lái)這個(gè)注解中存在的值還是比較多的,下面介紹幾個(gè)常用的值:
value
用于解決字段名不一致問(wèn)題和駝峰命名,比如實(shí)體類中屬性名為 remark,但是表中的字段名為 describe ,這個(gè)時(shí)候就可以使用 @TableField(value="describe") 來(lái)進(jìn)行轉(zhuǎn)換。駝峰轉(zhuǎn)換如果在全局中有配置駝峰命名,這個(gè)地方可不寫(xiě)。
exist
用于在數(shù)據(jù)表中不存在的字段,我們可以使用 @TableField(exist = false) 來(lái)進(jìn)行標(biāo)記
condition
用在預(yù)處理 WHERE 實(shí)體條件自定義運(yùn)算規(guī)則,比如我配置了 @TableField(condition = SqlCondition.LIKE),輸出 SQL 為:select 表 where name LIKE CONCAT('%',值,'%'),其中 SqlCondition 值如下:

update
用在預(yù)處理 set 字段自定義注入,比如我配置了 @TableField(update = "%s+1"),其中 %s 會(huì)填充字段,輸出 SQL 為:update 表名 set 字段 = 字段+1 where 條件
select
用于是否查詢時(shí)約束,如果我們有個(gè)字段 remark 是 text 類型的,查詢的時(shí)候不想查詢?cè)撟侄?,那么就可以使?@TableField(select = false) 來(lái)約束查詢的時(shí)候不查詢?cè)撟侄?/p>
2)update
MybatisPlus 的更新操作存在兩種:
int?updateById(Param("et")?T?entity);
int?update(@Param("et")?T?entity,?@Param("ew")?Wrapper?updateWrapper) ;
根據(jù) ID 更新
@Test
public?void?update()?{
????User?user?=?User.builder().id(3).name("小華").remark("小華愛(ài)玩游戲").build();
????userMapper.updateById(user);
}
/**?更新結(jié)果:
User(id=3,?deptId=1,?name=小華,?remark=小華愛(ài)玩游戲)
**/
根據(jù)條件更新
@Test
public?void?update()?{
????UpdateWrapper?updateWrapper?=?new?UpdateWrapper<>();
????updateWrapper.eq("name","小華").set("remark","小華愛(ài)下棋");
????userMapper.update(null,?updateWrapper);
}
/**?更新結(jié)果:
User(id=3,?deptId=1,?name=小華,?remark=小華愛(ài)下棋)
**/
我們也可以將要更新的條件放進(jìn) user 對(duì)象 里面:
@Test
public?void?update()?{
????UpdateWrapper?updateWrapper?=?new?UpdateWrapper<>();
????updateWrapper.eq("name","小華");
????User?user?=?User.builder().remark("小華愛(ài)游泳").build();
????userMapper.update(user,?updateWrapper);
}
/**?更新結(jié)果:
User(id=3,?deptId=1,?name=小華,?remark=小華愛(ài)游泳)
**/
3)delete
在 MybatisPlus 中刪除的方式相對(duì)于更新多,總共有四種:
int?deleteById(Serializable?id);
int?deleteByMap(@Param("cm")?Map?columnMap) ;
int?delete(@Param("ew")?Wrapper?wrapper) ;
int?deleteBatchIds(@Param("coll")?Collection?extends?Serializable>?idList);
根據(jù) ID 刪除
@Test
public?void?deleteById()?{
????userMapper.deleteById(3);
}
/** SQL語(yǔ)句:
DELETE?FROM?student?WHERE?id?=?3;
**/
根據(jù) Map 刪除
@Test
public?void?deleteByMap()?{
????HashMap?columnMap?=?new?HashMap<>();
????columnMap.put("name","小華");
????columnMap.put("remark","小華愛(ài)游泳");
????userMapper.deleteByMap(columnMap);
}
/** SQL語(yǔ)句:
DELETE?FROM?student?WHRE?name?=?'小華'?AND?remark?=?'小華愛(ài)游泳';
**/
根據(jù) Wrapper 刪除
@Test
public?void?delete()?{
????UpdateWrapper?wrapper?=?new?UpdateWrapper<>();
????wrapper.eq("remark","小華愛(ài)下棋");
????userMapper.delete(wrapper);
}
/** SQL語(yǔ)句:
DELETE?FROM?student?WHRE?remark?=?'小華愛(ài)下棋';
**/
根據(jù) Wrapper 刪除還有另外一種方式,直接將實(shí)體類放入 Wrapper 中包裝:
@Test
public?void?delete()?{
????User?user?=?User.builder().remark("小華愛(ài)下棋").build();
????UpdateWrapper?wrapper?=?new?UpdateWrapper<>(user);
????userMapper.delete(wrapper);
}
/** SQL語(yǔ)句:
DELETE?FROM?student?WHRE?remark?=?'小華愛(ài)下棋';
**/
根據(jù) ID 批量刪除
@Test
public?void?deleteBatchIds()?{
????List?idList?=?new?ArrayList<>();
????idList.add(4);
????idList.add(7);
????userMapper.deleteBatchIds(idList);
}
/** SQL語(yǔ)句:
DELETE?FROM?student?WHERE?id?In?(4,7)
**/
4)select
查詢操作在我們開(kāi)發(fā)中是最經(jīng)常用到的,也是重中之重。MybatisPlus 中支持查詢的方法也比較多,如下:
T?selectById(Serializable?id);
List?selectBatchIds(@Param("coll")?Collection?extends?Serializable>?idList) ;
List?selectByMap(@Param("cm")?Map?columnMap) ;
T?selectOne(@Param("ew")?Wrapper?queryWrapper) ;
Integer?selectCount(@Param("ew")?Wrapper?queryWrapper) ;
List?selectList(@Param("ew")?Wrapper?queryWrapper) ;
List可以看到總共有 10 個(gè)方法,我們接下來(lái)一個(gè)一個(gè)測(cè)試
查詢所有
@Test
public?void?selectList()?{
????List?users?=?userMapper.selectList(null);
????users.forEach(System.out::println);
}
/**?
?OUTPUT:
User(id=1, deptId=1, name=小菜, remark=關(guān)注小菜不迷路!)
User(id=2, deptId=1, name=小明, remark=好好學(xué)習(xí),天天向上!)
?SQL語(yǔ)句:
SELECT?id,?dept_id,?name,?remark?FROM?student;
**/
查詢數(shù)量
@Test
public?void?selectCount()?{
????QueryWrapper?queryWrapper?=?new?QueryWrapper<>();
????queryWrapper.like("name","小");
????System.out.println(userMapper.selectCount(queryWrapper));
}
/**?
?OUTPUT:
2
?SQL語(yǔ)句:
SELECT?COUNT(?1?)?FROM?student?WHERE?(name?LIKE?'%小%');
**/
根據(jù) ID 查詢
@Test
public?void?selectById()?{
????User?user?=?userMapper.selectById(1);
????System.out.println(user);
}
/**?
?OUTPUT:
User(id=1, deptId=1, name=小菜, remark=關(guān)注小菜不迷路!)
?SQL語(yǔ)句:
SELECT?id,?dept_id,?name,?remark?FROM?student?WHERE?ID?=?1;
**/
根據(jù) ID 批量查詢
@Test
public?void?selectBatchIds()?{
????List?users?=?userMapper.selectBatchIds(Arrays.asList(1,?2));
????users.forEach(System.out::println);
}
/**?
?OUTPUT:
User(id=1, deptId=1, name=小菜, remark=關(guān)注小菜不迷路!)
User(id=2, deptId=1, name=小明, remark=好好學(xué)習(xí),天天向上!)
?SQL語(yǔ)句:
SELECT?id,?dept_id,?name,?remark?FROM?student?WHERE?ID?IN?(1,?2);
**/
根據(jù)條件查詢單條
@Test
public?void?selectOne()?{
????QueryWrapper?queryWrapper?=?new?QueryWrapper<>();
????queryWrapper.eq("name","小菜");
????User?user?=?userMapper.selectOne(queryWrapper);
????System.out.println(user);
}
/**
?OUTPUT:
User(id=1, deptId=1, name=小菜, remark=關(guān)注小菜不迷路!)
?SQL語(yǔ)句:
?SELECT?id,?name,?dept_id,?remark?FROM?student?WHERE?(name?=?'小菜');
**/
根據(jù)條件查詢多條
通過(guò) map 傳遞參數(shù),不是通過(guò) LIKE 查詢,而是通過(guò) = 查詢
@Test
public?void?selectByMap()?{
????HashMap?columnMap?=?new?HashMap<>();
????columnMap.put("name","小");
????List?users?=?userMapper.selectByMap(columnMap);
????users.forEach(System.out::println);
}
/**
?OUTPUT:
null
?SQL語(yǔ)句:
SELECT?id,?name,?dept_id,?remark?FROM?student?WHERE?name?=?'小';
**/
如果我們沒(méi)有新建實(shí)體類進(jìn)行結(jié)果封裝,我們還可以用 Map 來(lái)接收結(jié)果集:
@Test
public?void?selectMaps()?{
????QueryWrapper?queryWrapper?=?new?QueryWrapper<>();
????queryWrapper.like("name","小");
????List>?maps?=?userMapper.selectMaps(queryWrapper);
????maps.forEach(System.out::println);
}
/**
?OUTPUT:
{name=小菜, remark=關(guān)注小菜不迷路!, id=1, dept_id=1}
{name=小明, remark=好好學(xué)習(xí),天天向上!, id=2, dept_id=1}
?SQL語(yǔ)句:
SELECT id, name, dept_id, remark FROM student WHERE (name LIKE '%小%');
**/
也可以用 Object 對(duì)象來(lái)接收結(jié)果集:
@Test
public?void?selectObjs()?{
????QueryWrapper?queryWrapper?=?new?QueryWrapper<>();
????queryWrapper.like("name",?"小");
????List 分頁(yè)查詢
@Test
public?void?selectPage()?{
????QueryWrapper?queryWrapper?=?new?QueryWrapper<>();
????queryWrapper.like("name",?"小");
????Page?page?=?new?Page<>(1,?1);
????IPage?userIPage?=?userMapper.selectPage(page,?queryWrapper);
????System.out.println("數(shù)據(jù)總數(shù):"?+?userIPage.getTotal());
????System.out.println("總頁(yè)數(shù):"?+?userIPage.getPages());
????System.out.println("當(dāng)前頁(yè):"?+?userIPage.getCurrent());
????System.out.println("頁(yè)大小:"?+?userIPage.getSize());
????userIPage.getRecords().forEach(System.out::println);
}
/**
?OUTPUT:
數(shù)據(jù)總數(shù):2
總頁(yè)數(shù):2
當(dāng)前頁(yè):1
頁(yè)大小:1
User(id=1, deptId=1, name=小菜, remark=關(guān)注小菜不迷路!)
?SQL語(yǔ)句:
?SELECT?id,?name,?dept_id,?remark
?FROM?student
?WHERE?(name?LIKE?'%小%')
?LIMIT?0,1;
**/
3. 條件構(gòu)造器

在 CRUD 的基本操作中,我們想要通過(guò)條件查詢都是通過(guò) Wrapper 類進(jìn)行封裝的,上面只是簡(jiǎn)單的用到 eq 和 like 操作。事實(shí)上這個(gè)類十分強(qiáng)大,我們?cè)谙旅鏁?huì)詳細(xì)進(jìn)行介紹。
1)allEq
全部 eq 或個(gè)別 isNull
allEq(Map?params)
allEq(Map?params,?boolean?null2IsNull)
allEq(boolean?condition,?Map?params,?boolean?null2IsNull)
????
allEq(BiPredicate?filter,?Map?params)
allEq(BiPredicate?filter,?Map?params,?boolean?null2IsNull)
allEq(boolean?condition,?BiPredicate?filter,?Map?params,?boolean?null2IsNull)?
參數(shù)說(shuō)明:
param: key 為數(shù)據(jù)庫(kù)字段名,value 為字段值
**nullsIsNull:**為 true 則在 map 的 value 為 null 時(shí)調(diào)用 isNull 方法,為 false 時(shí)則忽略 value 為 null 時(shí)不調(diào)用 isNull 方法
filter: 過(guò)濾函數(shù),判斷是否允許字段傳入比對(duì)條件中
使用示例:
allEq(Mapparams)
@Test
public?void?testAllEq()?{
????QueryWrapper?queryWrapper?=?new?QueryWrapper<>();
????Map?params?=?new?HashMap<>();
????params.put("name","小菜");
????params.put("dept_id",1);
????params.put("remark",null);
????queryWrapper.allEq(params);?//會(huì)調(diào)用?isNull?方法
????userMapper.selectList(queryWrapper);
}
/**?
?結(jié)果:
{}
?SQL語(yǔ)句:
?SELECT?id,name,dept_id,remark
?FROM?student
?WHERE?(name?=?'小菜'?AND?dept_id?=?1?AND?remark?IS?NULL);
?**/
allEq(Mapparams, boolean null2IsNull)
@Test
public?void?testAllEq()?{
????QueryWrapper?queryWrapper?=?new?QueryWrapper<>();
????Map?params?=?new?HashMap<>();
????params.put("name","小菜");
????params.put("dept_id",1);
????params.put("remark",null);
????queryWrapper.allEq(params,?false);?//不會(huì)調(diào)用?isNull?方法
????userMapper.selectList(queryWrapper);
}
/**?
?結(jié)果:
User(id=1, deptId=1, name=小菜, remark=關(guān)注小菜不迷路!)
?SQL語(yǔ)句:
?SELECT?id,name,dept_id,remark
?FROM?student
?WHERE?(name?=?'小菜'?AND?dept_id?=?1);
?**/
allEq(boolean condition, Mapparams, boolean null2IsNull)
@Test
public?void?testAllEq()?{
????QueryWrapper?queryWrapper?=?new?QueryWrapper<>();
????Map?params?=?new?HashMap<>();
????params.put("name","小菜");
????params.put("dept_id",1);
????params.put("remark",null);
????queryWrapper.allEq(false,params,false);?//不會(huì)帶入條件進(jìn)行查詢
????userMapper.selectList(queryWrapper);
}
/**?
?結(jié)果:
{name=小菜, remark=關(guān)注小菜不迷路!, id=1, dept_id=1}
{name=小明, remark=好好學(xué)習(xí),天天向上!, id=2, dept_id=1}
?SQL語(yǔ)句:
?SELECT?id,name,dept_id,remark
?FROM?student;
?**/
allEq(BiPredicatefilter, Map params)
@Test
public?void?testAllEq()?{
????QueryWrapper?queryWrapper?=?new?QueryWrapper<>();
????Map?params?=?new?HashMap<>();
????params.put("name",?"小菜");
????params.put("dept_id",?1);
????params.put("remark",?null);
????//只有?key?中含有?“m”?才會(huì)用作條件判斷
????queryWrapper.allEq((k,?v)?->?(k.contains("m")),?params);
????userMapper.selectList(queryWrapper);
}
/**?
?結(jié)果:
0
?SQL語(yǔ)句:
?SELECT?id,name,dept_id,remark
?FROM?student
?WHERE?(name?=?'小菜'?AND?remark?IS?NULL);
?**/
2)比較操作
eq: 相當(dāng)于 =ne: 相當(dāng)于 !=gt: ?相當(dāng)于 >ge: 相當(dāng)于 >=lt: ? 相當(dāng)于 <le: ? 相當(dāng)于 <=between: ? 相當(dāng)于 between ... and ...notBetween: ? 相當(dāng)于 not between ... and ...in: ? 相當(dāng)于 in(.., .., ..)notIn: ? 相當(dāng)于 not in(.., .., ..)
3)模糊查詢
like: like("name","小菜") --> name like "%小菜%"notLike: notLike("name","小菜") --> name not like "%小菜%"likeLeft: ? like("name","小菜") --> name like "%小菜"likeRight: like("name","小菜") --> name like "小菜%"
4)排序
orderBy:
orderBy(boolean?condition,?boolean?isAsc,?R...?columns)
orderBy(true, true, "id", "name") --> order by id ASC, name ASC
orderByAsc:
orderByAsc("id","name") --> order by id ASC, name ASC
orderByDesc:
orderByDesc("id","name) --> order by id Desc, name Desc
5)邏輯查詢
or:
拼接:主動(dòng)調(diào)用 or 表示緊接著下一個(gè)方法不是用 and 連接!(不調(diào)用 or 則默認(rèn)為使用 and 連接), eq("id",1).or().eq("name","老王")
嵌套:or(i -> i.eq("name", "李白").ne("status", "活著"))
and:
嵌套:and(i -> i.eq("name", "李白").ne("status", "活著"))
6)select
在MP查詢中,默認(rèn)查詢所有的字段,如果有需要也可以通過(guò)select方法進(jìn)行指定字段,如select("id", "name")
4. 配置講解
1)基本配置
configLocation
用于指明 **MyBatis ** 配置文件的位置,如果我們有 MyBatis 的配置文件,需將配置文件的路徑配置到 configLocation 中
SpringBoot:
mybatis-plus.config-location = classpath:mybatis-config.xml
SpringMvc:
<bean?id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property?name="configLocation"?value="classpath:mybatis-config.xml"/>
bean
mapperLocations
用于指明 Mapper 所對(duì)應(yīng)的 XML 的文件位置,我們?cè)?通用 CRUD 中用到的 Mapper 是直接繼承 MP 提供的 BaseMapper ,我們也可以自定義方法,然后在 XML 文件中自定義 SQL,而這時(shí)我們需要告訴 Mapper 所對(duì)應(yīng) XML 文件的位置
SpringBoot:
mybatis-plus.mapper-locations = classpath*:mybatis/*.xml
SpringMVC:
<bean?id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property?name="mapperLocations"?value="classpath*:mybatis/*.xml"/>
bean>
typeAliasesPackage
用于 MyBatis ?別名包掃描路徑,通過(guò)該屬性可以給包中的類注冊(cè)別名,注冊(cè)后在 Mapper 對(duì)應(yīng)的 XML 文件中可以直接使用類名,而不用使用全限定的類名
SpringBoot:
mybatis-plus.type-aliases-package = cbuc.life.bean
SpringMVC:
<bean?id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property?name="typeAliasesPackage"
value="com.baomidou.mybatisplus.samples.quickstart.entity"/>
bean>
2)進(jìn)階配置
mapUnderScoreToCamelCase
是否開(kāi)啟自動(dòng)駝峰命名規(guī)則映射,這個(gè)配置的默認(rèn)值是 true,但是這個(gè)屬性在 MyBatis 中的默認(rèn)值是 false,所以在我們平時(shí)的開(kāi)發(fā)中都會(huì)將這個(gè)配置開(kāi)啟。
#關(guān)閉自動(dòng)駝峰映射,該參數(shù)不能和mybatis-plus.config-location同時(shí)存在
mybatis-plus.configuration.map-underscore-to-camel-case = false
cacheEnabled
全局地開(kāi)啟或關(guān)閉配置文件中的所有映射器已經(jīng)配置的任何緩存,默認(rèn)為 true。
mybatis-plus.configuration.cache-enabled = false
3)DB 策略配置
idType
全局默認(rèn)主鍵類型,設(shè)置后,即可省略實(shí)體對(duì)象中的@TableId(type = IdType.AUTO)配置。該配置的默認(rèn)值為 ID_WORKER
SpringBoot:
mybatis-plus.global-config.db-config.id-type = auto
SpringMVC:
<bean?id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
?<property?name="dataSource"?ref="dataSource"/>
????<property?name="globalConfig">
????????<bean?class="com.baomidou.mybatisplus.core.config.GlobalConfig">
????????????<property?name="dbConfig">
????????????????<bean?????????class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
?????????????????<property?name="idType"?value="AUTO"/>
????????????????bean>
????????????property>
????????bean>
????property>
bean>
tablePrefix
表名前綴,全局配置后可省略@TableName()配置。該配置的默認(rèn)值為 null
SpringBoot:
mybatis-plus.global-config.db-config.table-prefix = yq_
SpringMVC:
<bean?id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
????<property?name="dataSource"?ref="dataSource"/>
????<property?name="globalConfig">
????????<bean?class="com.baomidou.mybatisplus.core.config.GlobalConfig">
????????????<property?name="dbConfig">
????????????????<bean????????????class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
?????????????????<property?name="idType"?value="AUTO"/>
?????????????????<property?name="tablePrefix"?value="yq_"/>
????????????????bean>
????????????property>
????????bean>
????property>
bean>
5. 其他擴(kuò)展
1)自動(dòng)填充
有時(shí)候我們?cè)诓迦牖蚋聰?shù)據(jù)的時(shí)候,希望有些字段可以自動(dòng)填充。比如我們平時(shí)數(shù)據(jù)表里面會(huì)有個(gè) 插入時(shí)間 或者 更新時(shí)間 這種字段,我們會(huì)默認(rèn)以當(dāng)前時(shí)間填充,在 MP 中我們也可以進(jìn)行配置。
首先我們需要借助 @TableField(fill = FieldFill.INSERT) 這個(gè)注解,在插入時(shí)進(jìn)行填充。
@TableField(fill?=?FieldFill.INSERT)
private?String?remark;
其中自動(dòng)填充的模式如下:
public?enum?FieldFill?{
????/**
????*?默認(rèn)不處理
????*/
????DEFAULT,
????/**
????*?插入時(shí)填充字段
????*/
????INSERT,
????/**
????*?更新時(shí)填充字段
????*/
????UPDATE,
????/**
????*?插入和更新時(shí)填充字段
????*/
????INSERT_UPDATE
}
然后我們?cè)倬帉?xiě)自定義的填充處理模式:
@Component
public?class?MyMetaObjectHandler?implements?MetaObjectHandler?{
????@Override
????public?void?insertFill(MetaObject?metaObject)?{
????????Object?remark?=?getFieldValByName("remark",?metaObject);
????????if?(null?==?remark)?{
????????????setFieldValByName("remark",?"好好學(xué)習(xí)",?metaObject);
????????}
????}
????@Override
????public?void?updateFill(MetaObject?metaObject)?{
??//自定義更新時(shí)填充
????}
}
測(cè)試:
@Test
public?void?testObjectHandler()?{
????User?user?=?User.builder().deptId(1).name("小明").build();
????userMapper.insert(user);
}
/**
?SQL語(yǔ)句:
INSERT?INTO?student?(?name,?dept_id,?remark?)
VALUES?(?'小明',?1,?'好好學(xué)習(xí)'?);
**/
可以看到插入時(shí),已經(jīng)自動(dòng)將我們填充的字段合并進(jìn)去。
2)邏輯刪除
在開(kāi)發(fā)中,很多時(shí)候我們刪除數(shù)據(jù)并不需要真正意義上的物理刪除,而是使用邏輯刪除,這樣子查詢的時(shí)候需要狀態(tài)條件,確保被標(biāo)記的數(shù)據(jù)不被查詢到。MP 當(dāng)然也支持這樣的功能。
我們需要先為 student 表添加一個(gè)字段 status 來(lái)聲明數(shù)據(jù)是否被刪除,0 表示被刪除,1表示未刪除,然后也需要在實(shí)體類上增加這個(gè)屬性:
@TableLogic
private?Integer?status;
在 application.yaml 中配置:
mybatis-plus:
??global-config:
????db-config:
??????logic-delete-value:?0
??????logic-not-delete-value:?1
測(cè)試:
@Test
public?void?testLogicDelete()?{
????userMapper.deleteById(1);
}
/**
?SQL語(yǔ)句:
UPDATE?student?SET?status=0
WHERE?id=1?AND?status=1;
**/
可以看出這段 SQL 并沒(méi)有真正刪除,而是進(jìn)行了邏輯刪除,只是更新了刪除標(biāo)識(shí)
3)通用枚舉
如果有性別之類的字段,我們通常會(huì)用 0 和 1 來(lái)表示,但是查出來(lái)我們得進(jìn)行值轉(zhuǎn)換,這個(gè)時(shí)候我們就可以使用枚舉來(lái)解決這個(gè)問(wèn)題:
首先為 student 表添加一個(gè) sex 字段來(lái)表示性別,0 表示女性,1 表示男性,然后定義一個(gè)枚舉類:
public?enum?SexEnum?implements?IEnum?{
????MAN(1,?"男"),
????WOMEN(0,?"女");
????private?int?code;
????private?String?value;
????SexEnum(int?code,?String?value)?{
????????this.code?=?code;
????????this.value?=?value;
????}
????@Override
????public?Integer?getValue()?{
????????return?this.code;
????}
????
????//注意要重寫(xiě)此方法,不然會(huì)將值轉(zhuǎn)換成?‘MAN’,而不是?‘男’
????@Override
????public?String?toString()?{
????????return?this.value;
????}
}
然后在實(shí)體類中添加對(duì)應(yīng)屬性:
private?SexEnum?sex;
在 application.yaml 中配置:
mybatis-plus:
??type-enums-package:?cbuc.life.enums
測(cè)試:
@Test
public?void?selectOne()?{
????QueryWrapper?queryWrapper?=?new?QueryWrapper<>();
????queryWrapper.eq("name",?"小菜");
????User?user?=?userMapper.selectOne(queryWrapper);
????System.out.println(user);
}
/**
?輸出結(jié)果:
User(id=1, deptId=1, name=小菜, remark=關(guān)注小菜不迷路!, status=1, sex=男)
?SQL語(yǔ)句:
?SELECT?id,sex,name,dept_id,remark,status
?FROM?student
?WHERE?status=1?AND?(name?=?'小菜');
**/
END
這篇文章寫(xiě)到這里就告一段落了哦,內(nèi)容有點(diǎn)長(zhǎng),不過(guò)如果能完整看下來(lái),我相信你肯定能夠很好的使用 MybatisPlus 啦!路漫漫,小菜與你一同求索!







關(guān)注Java技術(shù)??锤喔韶?/strong>


