提高生产力,最全 MyBatisPlus 讲解!
如果你每天還在重復(fù)寫 CRUD 的 SQL,如果你對這些 SQL 已經(jīng)不耐煩了,那么你何不花費一些時間來閱讀這篇文章,然后對已有的老項目進行改造,必有收獲!
一、MP 是什么
MP 全稱 Mybatis-Plus ,套用官方的解釋便是成為 MyBatis 最好的搭檔,簡稱基友。它是在 MyBatis 的基礎(chǔ)上只做增強不做改變,為簡化開發(fā)、提高效率而生。
1. 三大特性
1)潤物無聲
只做增強不做改變,引入它不會對現(xiàn)有工程產(chǎn)生影響,如絲般順滑。
2)效率至上
只需簡單配置,即可快速進行單表 CRUD 操作,從而節(jié)省大量時間。
3)豐富功能
代碼生成、物理分頁、性能分析等功能一應(yīng)俱全。
2. 支持?jǐn)?shù)據(jù)庫
mysql 、mariadb 、oracle 、db2 、h2 、hsql 、sqlite 、postgresql 、sqlserver 、presto 、Gauss 、Firebird
Phoenix 、clickhouse 、Sybase ASE 、 OceanBase 、達夢數(shù)據(jù)庫 、虛谷數(shù)據(jù)庫 、人大金倉數(shù)據(jù)庫 、南大通用數(shù)據(jù)庫
3. 框架結(jié)構(gòu)
實話說,以上這些內(nèi)容只要你打開官網(wǎng)也能看到,那么我們接下來就先來實際操作一番!
二、MP實戰(zhàn)
1. 手摸手式項目練習(xí)
1)數(shù)據(jù)庫及表準(zhǔn)備
sql 語句:
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.boot</groupId><artifactId>spring-boot-starter-test</artifactId> </dependency> <!--lombok--> <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.16</version> </dependency> <!--MP插件--> <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.2.0</version> </dependency> <!--Mysql--> <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.21</version> </dependency> <!--?連接池?--> <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.1</version> </dependency> <!--JUNIT--> <dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.1</version> </dependency>3)配置文件
spring:datasource:url:?jdbc:mysql://localhost:3306/testusername:?rootpassword:?123456driver-class-name:?com.mysql.cj.jdbc.Driver4)實體類
@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)測試類
@RunWith(SpringRunner.class) @SpringBootTest public?class?MapperTest?{@Autowiredprivate?UserMapper?userMapper;@Testpublic?void?getAll()?{List<User>?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ù)庫中的全部數(shù)據(jù)(兩條)。而并沒有看到平時我們需要寫的 mapper.xml 文件,只是用到了 usermapper 中的 selectList() 方法,而 UserMapper 繼承了 BaseMapper 這個接口,這個接口便是 MybatisPlus 提供給我們的,我們再來看下這個接口給我們提供了哪些方法。
2. ?CRUD 基操
1)insert
@Test public?void?insert()?{//這里使用了?lombok?中的建造者模式構(gòu)建對象User?user?=?User.builder().deptId(1).name("小華").remark("小華愛學(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生成策略,而是我們在實體類中指定的:
在 MP 中支持的主鍵生成策略有以下幾種:
我們既然已經(jīng)看到了 @TableId 這個注解,那我們再來關(guān)注一個常用注解 @TableField
從注解名上我們就可以看出,@TableId 是用來標(biāo)記主鍵 ID 的,而 @TableField 是用來標(biāo)記其他字段的。
可以看得出來這個注解中存在的值還是比較多的,下面介紹幾個常用的值:
value
用于解決字段名不一致問題和駝峰命名,比如實體類中屬性名為 remark,但是表中的字段名為 describe ,這個時候就可以使用 @TableField(value="describe") 來進行轉(zhuǎn)換。駝峰轉(zhuǎn)換如果在全局中有配置駝峰命名,這個地方可不寫。
exist
用于在數(shù)據(jù)表中不存在的字段,我們可以使用 @TableField(exist = false) 來進行標(biāo)記
condition
用在預(yù)處理 WHERE 實體條件自定義運算規(guī)則,比如我配置了 @TableField(condition = SqlCondition.LIKE),輸出 SQL 為:select 表 where name LIKE CONCAT('%',值,'%'),其中 SqlCondition 值如下:
update
用在預(yù)處理 set 字段自定義注入,比如我配置了 @TableField(update = "%s+1"),其中 %s 會填充字段,輸出 SQL 為:update 表名 set 字段 = 字段+1 where 條件
select
用于是否查詢時約束,如果我們有個字段 remark 是 text 類型的,查詢的時候不想查詢該字段,那么就可以使用 @TableField(select = false) 來約束查詢的時候不查詢該字段
2)update
MybatisPlus 的更新操作存在兩種:
int?updateById(Param("et")?T?entity);int?update(@Param("et")?T?entity,?@Param("ew")?Wrapper<T>?updateWrapper);根據(jù) ID 更新
@Test public?void?update()?{User?user?=?User.builder().id(3).name("小華").remark("小華愛玩游戲").build();userMapper.updateById(user); } /**?更新結(jié)果: User(id=3,?deptId=1,?name=小華,?remark=小華愛玩游戲) **/根據(jù)條件更新
@Test public?void?update()?{UpdateWrapper<User>?updateWrapper?=?new?UpdateWrapper<>();updateWrapper.eq("name","小華").set("remark","小華愛下棋");userMapper.update(null,?updateWrapper); } /**?更新結(jié)果: User(id=3,?deptId=1,?name=小華,?remark=小華愛下棋) **/我們也可以將要更新的條件放進 user 對象 里面:
@Test public?void?update()?{UpdateWrapper<User>?updateWrapper?=?new?UpdateWrapper<>();updateWrapper.eq("name","小華");User?user?=?User.builder().remark("小華愛游泳").build();userMapper.update(user,?updateWrapper); } /**?更新結(jié)果: User(id=3,?deptId=1,?name=小華,?remark=小華愛游泳) **/3)delete
在 MybatisPlus 中刪除的方式相對于更新多,總共有四種:
int?deleteById(Serializable?id);int?deleteByMap(@Param("cm")?Map<String,?Object>?columnMap);int?delete(@Param("ew")?Wrapper<T>?wrapper);int?deleteBatchIds(@Param("coll")?Collection<??extends?Serializable>?idList);根據(jù) ID 刪除
@Test public?void?deleteById()?{userMapper.deleteById(3); } /** SQL語句: DELETE?FROM?student?WHERE?id?=?3; **/根據(jù) Map 刪除
@Test public?void?deleteByMap()?{HashMap<String,?Object>?columnMap?=?new?HashMap<>();columnMap.put("name","小華");columnMap.put("remark","小華愛游泳");userMapper.deleteByMap(columnMap); } /** SQL語句: DELETE?FROM?student?WHRE?name?=?'小華'?AND?remark?=?'小華愛游泳'; **/根據(jù) Wrapper 刪除
@Test public?void?delete()?{UpdateWrapper<User>?wrapper?=?new?UpdateWrapper<>();wrapper.eq("remark","小華愛下棋");userMapper.delete(wrapper); } /** SQL語句: DELETE?FROM?student?WHRE?remark?=?'小華愛下棋'; **/根據(jù) Wrapper 刪除還有另外一種方式,直接將實體類放入 Wrapper 中包裝:
@Test public?void?delete()?{User?user?=?User.builder().remark("小華愛下棋").build();UpdateWrapper<User>?wrapper?=?new?UpdateWrapper<>(user);userMapper.delete(wrapper); } /** SQL語句: DELETE?FROM?student?WHRE?remark?=?'小華愛下棋'; **/根據(jù) ID 批量刪除
@Test public?void?deleteBatchIds()?{List<Integer>?idList?=?new?ArrayList<>();idList.add(4);idList.add(7);userMapper.deleteBatchIds(idList); } /** SQL語句: DELETE?FROM?student?WHERE?id?In?(4,7) **/4)select
查詢操作在我們開發(fā)中是最經(jīng)常用到的,也是重中之重。MybatisPlus 中支持查詢的方法也比較多,如下:
T?selectById(Serializable?id);List<T>?selectBatchIds(@Param("coll")?Collection<??extends?Serializable>?idList);List<T>?selectByMap(@Param("cm")?Map<String,?Object>?columnMap);T?selectOne(@Param("ew")?Wrapper<T>?queryWrapper);Integer?selectCount(@Param("ew")?Wrapper<T>?queryWrapper);List<T>?selectList(@Param("ew")?Wrapper<T>?queryWrapper);List<Map<String,?Object>>?selectMaps(@Param("ew")?Wrapper<T>?queryWrapper);List<Object>?selectObjs(@aram("ew")?Wrapper<T>?queryWrapper);IPage<T>?selectPage(IPage<T>?page,?@Param("ew")?Wrapper<T>?queryWrapper);IPage<Map<String,?Object>>?selectMapsPage(IPage<T>?page,?@Param("ew")?Wrapper<T>?queryWrapper);可以看到總共有 10 個方法,我們接下來一個一個測試
查詢所有
@Test public?void?selectList()?{List<User>?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語句: SELECT?id,?dept_id,?name,?remark?FROM?student; **/查詢數(shù)量
@Test public?void?selectCount()?{QueryWrapper<User>?queryWrapper?=?new?QueryWrapper<>();queryWrapper.like("name","小");System.out.println(userMapper.selectCount(queryWrapper)); } /**?OUTPUT: 2SQL語句: 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語句: SELECT?id,?dept_id,?name,?remark?FROM?student?WHERE?ID?=?1; **/根據(jù) ID 批量查詢
@Test public?void?selectBatchIds()?{List<User>?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語句: SELECT?id,?dept_id,?name,?remark?FROM?student?WHERE?ID?IN?(1,?2); **/根據(jù)條件查詢單條
@Test public?void?selectOne()?{QueryWrapper<User>?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語句:SELECT?id,?name,?dept_id,?remark?FROM?student?WHERE?(name?=?'小菜'); **/根據(jù)條件查詢多條
通過 map 傳遞參數(shù),不是通過 LIKE 查詢,而是通過 = 查詢
@Test public?void?selectByMap()?{HashMap<String,?Object>?columnMap?=?new?HashMap<>();columnMap.put("name","小");List<User>?users?=?userMapper.selectByMap(columnMap);users.forEach(System.out::println); } /**OUTPUT: nullSQL語句: SELECT?id,?name,?dept_id,?remark?FROM?student?WHERE?name?=?'小'; **/如果我們沒有新建實體類進行結(jié)果封裝,我們還可以用 Map 來接收結(jié)果集:
@Test public?void?selectMaps()?{QueryWrapper<User>?queryWrapper?=?new?QueryWrapper<>();queryWrapper.like("name","小");List<Map<String,?Object>>?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語句: SELECT id, name, dept_id, remark FROM student WHERE (name LIKE '%小%'); **/也可以用 Object 對象來接收結(jié)果集:
@Test public?void?selectObjs()?{QueryWrapper<User>?queryWrapper?=?new?QueryWrapper<>();queryWrapper.like("name",?"小");List<Object>?objects?=?userMapper.selectObjs(queryWrapper); } /**OUTPUT: {name=小菜, remark=關(guān)注小菜不迷路!, id=1, dept_id=1} {name=小明, remark=好好學(xué)習(xí),天天向上!, id=2, dept_id=1}SQL語句: SELECT id, name, dept_id, remark FROM student WHERE (name LIKE '%小%'); **/分頁查詢
@Test public?void?selectPage()?{QueryWrapper<User>?queryWrapper?=?new?QueryWrapper<>();queryWrapper.like("name",?"小");Page<User>?page?=?new?Page<>(1,?1);IPage<User>?userIPage?=?userMapper.selectPage(page,?queryWrapper);System.out.println("數(shù)據(jù)總數(shù):"?+?userIPage.getTotal());System.out.println("總頁數(shù):"?+?userIPage.getPages());System.out.println("當(dāng)前頁:"?+?userIPage.getCurrent());System.out.println("頁大小:"?+?userIPage.getSize());userIPage.getRecords().forEach(System.out::println); } /**OUTPUT: 數(shù)據(jù)總數(shù):2 總頁數(shù):2 當(dāng)前頁:1 頁大小:1 User(id=1, deptId=1, name=小菜, remark=關(guān)注小菜不迷路!)SQL語句:SELECT?id,?name,?dept_id,?remarkFROM?studentWHERE?(name?LIKE?'%小%')LIMIT?0,1; **/3. 條件構(gòu)造器
在 CRUD 的基本操作中,我們想要通過條件查詢都是通過 Wrapper 類進行封裝的,上面只是簡單的用到 eq 和 like 操作。事實上這個類十分強大,我們在下面會詳細(xì)進行介紹。
1)allEq
全部 eq 或個別 isNull
allEq(Map<R,?V>?params) allEq(Map<R,?V>?params,?boolean?null2IsNull) allEq(boolean?condition,?Map<R,?V>?params,?boolean?null2IsNull)allEq(BiPredicate<R,?V>?filter,?Map<R,?V>?params) allEq(BiPredicate<R,?V>?filter,?Map<R,?V>?params,?boolean?null2IsNull) allEq(boolean?condition,?BiPredicate<R,?V>?filter,?Map<R,?V>?params,?boolean?null2IsNull)?參數(shù)說明:
param: key 為數(shù)據(jù)庫字段名,value 為字段值
**nullsIsNull:**為 true 則在 map 的 value 為 null 時調(diào)用 isNull 方法,為 false 時則忽略 value 為 null 時不調(diào)用 isNull 方法
filter: 過濾函數(shù),判斷是否允許字段傳入比對條件中
使用示例:
allEq(Map<R, V> params)
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
allEq(BiPredicate<R, V> filter, Map<R, V> params)
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(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:
拼接:主動調(diào)用 or 表示緊接著下一個方法不是用 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)查詢所有的字段,如果有需要也可以通過select方法進行指定字段,如select("id", "name")
4. 配置講解
1)基本配置
configLocation
用于指明 **MyBatis ** 配置文件的位置,如果我們有 MyBatis 的配置文件,需將配置文件的路徑配置到 configLocation 中
SpringBoot:
mybatis-plus.config-location = classpath:mybatis-config.xmlSpringMvc:
<bean?id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"> <property?name="configLocation"?value="classpath:mybatis-config.xml"/> </beanmapperLocations
用于指明 Mapper 所對應(yīng)的 XML 的文件位置,我們在 通用 CRUD 中用到的 Mapper 是直接繼承 MP 提供的 BaseMapper ,我們也可以自定義方法,然后在 XML 文件中自定義 SQL,而這時我們需要告訴 Mapper 所對應(yīng) XML 文件的位置
SpringBoot:
mybatis-plus.mapper-locations = classpath*:mybatis/*.xmlSpringMVC:
<bean?id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"> <property?name="mapperLocations"?value="classpath*:mybatis/*.xml"/> </bean>typeAliasesPackage
用于 MyBatis ?別名包掃描路徑,通過該屬性可以給包中的類注冊別名,注冊后在 Mapper 對應(yīng)的 XML 文件中可以直接使用類名,而不用使用全限定的類名
SpringBoot:
mybatis-plus.type-aliases-package = cbuc.life.beanSpringMVC:
<bean?id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"> <property?name="typeAliasesPackage" value="com.baomidou.mybatisplus.samples.quickstart.entity"/> </bean>2)進階配置
mapUnderScoreToCamelCase
是否開啟自動駝峰命名規(guī)則映射,這個配置的默認(rèn)值是 true,但是這個屬性在 MyBatis 中的默認(rèn)值是 false,所以在我們平時的開發(fā)中都會將這個配置開啟。
#關(guān)閉自動駝峰映射,該參數(shù)不能和mybatis-plus.config-location同時存在 mybatis-plus.configuration.map-underscore-to-camel-case = falsecacheEnabled
全局地開啟或關(guān)閉配置文件中的所有映射器已經(jīng)配置的任何緩存,默認(rèn)為 true。
mybatis-plus.configuration.cache-enabled = false3)DB 策略配置
idType
全局默認(rèn)主鍵類型,設(shè)置后,即可省略實體對象中的@TableId(type = IdType.AUTO)配置。該配置的默認(rèn)值為 ID_WORKER
SpringBoot:
mybatis-plus.global-config.db-config.id-type = autoSpringMVC:
<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. 其他擴展
1)自動填充
有時候我們在插入或更新數(shù)據(jù)的時候,希望有些字段可以自動填充。比如我們平時數(shù)據(jù)表里面會有個 插入時間 或者 更新時間 這種字段,我們會默認(rèn)以當(dāng)前時間填充,在 MP 中我們也可以進行配置。
首先我們需要借助 @TableField(fill = FieldFill.INSERT) 這個注解,在插入時進行填充。
@TableField(fill?=?FieldFill.INSERT) private?String?remark;其中自動填充的模式如下:
public?enum?FieldFill?{/***?默認(rèn)不處理*/DEFAULT,/***?插入時填充字段*/INSERT,/***?更新時填充字段*/UPDATE,/***?插入和更新時填充字段*/INSERT_UPDATE }然后我們再編寫自定義的填充處理模式:
@Component public?class?MyMetaObjectHandler?implements?MetaObjectHandler?{@Overridepublic?void?insertFill(MetaObject?metaObject)?{Object?remark?=?getFieldValByName("remark",?metaObject);if?(null?==?remark)?{setFieldValByName("remark",?"好好學(xué)習(xí)",?metaObject);}}@Overridepublic?void?updateFill(MetaObject?metaObject)?{//自定義更新時填充} }測試:
@Test public?void?testObjectHandler()?{User?user?=?User.builder().deptId(1).name("小明").build();userMapper.insert(user); } /**SQL語句: INSERT?INTO?student?(?name,?dept_id,?remark?) VALUES?(?'小明',?1,?'好好學(xué)習(xí)'?); **/可以看到插入時,已經(jīng)自動將我們填充的字段合并進去。
2)邏輯刪除
在開發(fā)中,很多時候我們刪除數(shù)據(jù)并不需要真正意義上的物理刪除,而是使用邏輯刪除,這樣子查詢的時候需要狀態(tài)條件,確保被標(biāo)記的數(shù)據(jù)不被查詢到。MP 當(dāng)然也支持這樣的功能。
我們需要先為 student 表添加一個字段 status 來聲明數(shù)據(jù)是否被刪除,0 表示被刪除,1表示未刪除,然后也需要在實體類上增加這個屬性:
@TableLogic private?Integer?status;在 application.yaml 中配置:
mybatis-plus:global-config:db-config:logic-delete-value:?0logic-not-delete-value:?1測試:
@Test public?void?testLogicDelete()?{userMapper.deleteById(1); } /**SQL語句: UPDATE?student?SET?status=0 WHERE?id=1?AND?status=1; **/可以看出這段 SQL 并沒有真正刪除,而是進行了邏輯刪除,只是更新了刪除標(biāo)識
3)通用枚舉
如果有性別之類的字段,我們通常會用 0 和 1 來表示,但是查出來我們得進行值轉(zhuǎn)換,這個時候我們就可以使用枚舉來解決這個問題:
首先為 student 表添加一個 sex 字段來表示性別,0 表示女性,1 表示男性,然后定義一個枚舉類:
public?enum?SexEnum?implements?IEnum<Integer>?{MAN(1,?"男"),WOMEN(0,?"女");private?int?code;private?String?value;SexEnum(int?code,?String?value)?{this.code?=?code;this.value?=?value;}@Overridepublic?Integer?getValue()?{return?this.code;}//注意要重寫此方法,不然會將值轉(zhuǎn)換成?‘MAN’,而不是?‘男’@Overridepublic?String?toString()?{return?this.value;} }然后在實體類中添加對應(yīng)屬性:
private?SexEnum?sex;在 application.yaml 中配置:
mybatis-plus:type-enums-package:?cbuc.life.enums測試:
@Test public?void?selectOne()?{QueryWrapper<User>?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語句:SELECT?id,sex,name,dept_id,remark,statusFROM?studentWHERE?status=1?AND?(name?=?'小菜'); **/ 往期推薦千萬不要這樣寫代碼!9種常見的OOM場景演示
2020-11-30
這8種常見的SQL錯誤用法,你還在用嗎?
2020-11-27
Java中竟有18種隊列?45張圖!安排
2020-12-03
關(guān)注我,每天陪你進步一點點!
總結(jié)
以上是生活随笔為你收集整理的提高生产力,最全 MyBatisPlus 讲解!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java中不可或缺的59个小技巧,贼好用
- 下一篇: 聊聊近期的感受和10月文章精选!