MyBatis無縫轉(zhuǎn)MyBatis-plus的基本使用
1.引入依賴
引入MyBatis-plus依賴取代MyBatis
<!--mybatis-plus起步依賴--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3.1</version> </dependency>
2.改造Mapper
繼承BaseMapper
public interface 原來的Mapper extends BaseMapper<這里填入這個mapper對應(yīng)的實體類> { }
3.改造實體類
需要用到以下三個注解
@TableName("這里填寫表名") // 指定數(shù)據(jù)庫表的對應(yīng) @TableId(value = "這里填寫主鍵字段名",type = IdType.AUTO) // 指定主鍵的對應(yīng) @TableField("這里填寫字段名") // 指定字段的對應(yīng)
一個完整的實體類參考如下:
@Data @Builder @NoArgsConstructor @AllArgsConstructor @TableName("table_name") public class tableName implements Serializable { @TableId(value = "table_id",type = IdType.AUTO) private Long tableId; @TableField("table_field") private String tableField; }
注意:
一般情況下我們并不需要給字段添加@TableField
注解,一些特殊情況除外:
成員變量名與數(shù)據(jù)庫字段名不一致
成員變量是以
isXXX
命名,按照JavaBean
的規(guī)范,MybatisPlus
識別字段時會把is
去除,這就導(dǎo)致與數(shù)據(jù)庫不符。成員變量名與數(shù)據(jù)庫一致,但是與數(shù)據(jù)庫的關(guān)鍵字沖突。使用
@TableField
注解給字段名添加轉(zhuǎn)義字符:``
支持的其它屬性如下:
屬性 | 類型 | 必填 | 默認(rèn)值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 數(shù)據(jù)庫字段名 |
exist | boolean | 否 | true | 是否為數(shù)據(jù)庫表字段 |
condition | String | 否 | "" | 字段 where 實體查詢比較條件,有值設(shè)置則按設(shè)置的值為準(zhǔn),沒有則為默認(rèn)全局的 %s=#{%s},參考(opens new window) |
update | String | 否 | "" | 字段 update set 部分注入,例如:當(dāng)在version字段上注解update="%s+1" 表示更新時會 set version=version+1 (該屬性優(yōu)先級高于 el 屬性) |
insertStrategy | Enum | 否 | FieldStrategy.DEFAULT | 舉例:NOT_NULL insert into table_a(<if test="columnProperty != null">column</if>) values (<if test="columnProperty != null">#{columnProperty}</if>) |
updateStrategy | Enum | 否 | FieldStrategy.DEFAULT | 舉例:IGNORED update table_a set column=#{columnProperty} |
whereStrategy | Enum | 否 | FieldStrategy.DEFAULT | 舉例:NOT_EMPTY where <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if> |
fill | Enum | 否 | FieldFill.DEFAULT | 字段自動填充策略 |
select | boolean | 否 | true | 是否進(jìn)行 select 查詢 |
keepGlobalFormat | boolean | 否 | false | 是否保持使用全局的 format 進(jìn)行處理 |
jdbcType | JdbcType | 否 | JdbcType.UNDEFINED | JDBC 類型 (該默認(rèn)值不代表會按照該值生效) |
typeHandler | TypeHander | 否 | 類型處理器 (該默認(rèn)值不代表會按照該值生效) | |
numericScale | String | 否 | "" | 指定小數(shù)點后保留的位數(shù) |
4-1.改造Service
第一種情況:使用條件構(gòu)造器
QueryWrapper
除了新增以外,修改、刪除、查詢的SQL語句都需要指定where條件。因此BaseMapper中提供的相關(guān)方法除了以id
作為where
條件以外,還支持更加復(fù)雜的where
條件。
基本用法:
List<xx> xxList = xxMapper.selectList(new QueryWrapper<xx>());
mapper對象調(diào)用方法,里面?zhèn)鬟f一個queryWrapper對象
其它方法:
UpdateWrapper
基于BaseMapper中的update方法更新時只能直接賦值,對于一些復(fù)雜的需求就難以實現(xiàn)。 例如:更新id為1,2,4
的用戶的余額,扣200,對應(yīng)的SQL應(yīng)該是:
UPDATE user SET balance = balance - 200 WHERE id in (1, 2, 4)
SET的賦值結(jié)果是基于字段現(xiàn)有值的,這個時候就要利用UpdateWrapper中的setSql功能了:
@Test void testUpdateWrapper() { List<Long> ids = List.of(1L, 2L, 4L); // 1.生成SQL UpdateWrapper<User> wrapper = new UpdateWrapper<User>() .setSql("balance = balance - 200") // SET balance = balance - 200 .in("id", ids); // WHERE id in (1, 2, 4) // 2.更新,注意第一個參數(shù)可以給null,也就是不填更新字段和數(shù)據(jù), // 而是基于UpdateWrapper中的setSQL來更新 userMapper.update(null, wrapper); }
LambdaQueryWrapper
無論是QueryWrapper還是UpdateWrapper在構(gòu)造條件的時候都需要寫死字段名稱,會出現(xiàn)字符串魔法值
。這在編程規(guī)范中顯然是不推薦的。 那怎么樣才能不寫字段名,又能知道字段名呢?
其中一種辦法是基于變量的gettter
方法結(jié)合反射技術(shù)。因此我們只要將條件對應(yīng)的字段的getter
方法傳遞給MybatisPlus,它就能計算出對應(yīng)的變量名了。而傳遞方法可以使用JDK8中的方法引用
和Lambda
表達(dá)式。 因此MybatisPlus又提供了一套基于Lambda的Wrapper,包含兩個:
LambdaQueryWrapper
LambdaUpdateWrapper
分別對應(yīng)QueryWrapper和UpdateWrapper
其使用方式如下:
@Test void testLambdaQueryWrapper() { // 1.構(gòu)建條件 WHERE username LIKE "%o%" AND balance >= 1000 QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.lambda() .select(User::getId, User::getUsername, User::getInfo, User::getBalance) .like(User::getUsername, "o") .ge(User::getBalance, 1000); // 2.查詢 List<User> users = userMapper.selectList(wrapper); users.forEach(System.out::println); }
第二種情況:使用自定義SQL
在演示UpdateWrapper的案例中,我們在代碼中編寫了更新的SQL語句:
這種寫法在某些企業(yè)也是不允許的,因為SQL語句最好都維護(hù)在持久層,而不是業(yè)務(wù)層。就當(dāng)前案例來說,由于條件是in語句,只能將SQL寫在Mapper.xml文件,利用foreach來生成動態(tài)SQL。 這實在是太麻煩了。假如查詢條件更復(fù)雜,動態(tài)SQL的編寫也會更加復(fù)雜。
所以,MybatisPlus提供了自定義SQL功能,可以讓我們利用Wrapper生成查詢條件,再結(jié)合Mapper.xml編寫SQL
基本用法
Service
@Test void testCustomWrapper() { // 1.準(zhǔn)備自定義查詢條件 List<Long> ids = List.of(1L, 2L, 4L); QueryWrapper<User> wrapper = new QueryWrapper<User>().in("id", ids); ? // 2.調(diào)用mapper的自定義方法,直接傳遞Wrapper userMapper.deductBalanceByIds(200, wrapper); }
Mapper
package com.itheima.mp.mapper; ? import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.itheima.mp.domain.po.User; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Update; import org.apache.ibatis.annotations.Param; ? public interface UserMapper extends BaseMapper<User> { @Select("UPDATE user SET balance = balance - #{money} ${ew.customSqlSegment}") void deductBalanceByIds(@Param("money") int money, @Param("ew") QueryWrapper<User> wrapper); }
多表關(guān)聯(lián)
理論上來講MyBatisPlus是不支持多表查詢的,不過我們可以利用Wrapper中自定義條件結(jié)合自定義SQL來實現(xiàn)多表查詢的效果。 例如,我們要查詢出所有收貨地址在北京的并且用戶id在1、2、4之中的用戶 要是自己基于mybatis實現(xiàn)SQL,大概是這樣的:
<select id="queryUserByIdAndAddr" resultType="com.itheima.mp.domain.po.User"> SELECT * FROM user u INNER JOIN address a ON u.id = a.user_id WHERE u.id <foreach collection="ids" separator="," item="id" open="IN (" close=")"> #{id} </foreach> AND a.city = #{city} </select>
可以看出其中最復(fù)雜的就是WHERE條件的編寫,如果業(yè)務(wù)復(fù)雜一些,這里的SQL會更變態(tài)。
但是基于自定義SQL結(jié)合Wrapper的玩法,我們就可以利用Wrapper來構(gòu)建查詢條件,然后手寫SELECT及FROM部分,實現(xiàn)多表查詢。
查詢條件這樣來構(gòu)建:
@Test void testCustomJoinWrapper() { // 1.準(zhǔn)備自定義查詢條件 QueryWrapper<User> wrapper = new QueryWrapper<User>() .in("u.id", List.of(1L, 2L, 4L)) .eq("a.city", "北京"); ? // 2.調(diào)用mapper的自定義方法 List<User> users = userMapper.queryUserByWrapper(wrapper); ? users.forEach(System.out::println); }
然后在UserMapper中自定義方法:
@Select("SELECT u.* FROM user u INNER JOIN address a ON u.id = a.user_id ${ew.customSqlSegment}") List<User> queryUserByWrapper(@Param("ew")QueryWrapper<User> wrapper);
當(dāng)然,也可以在UserMapper.xml
中寫SQL:
<select id="queryUserByIdAndAddr" resultType="com.itheima.mp.domain.po.User"> SELECT * FROM user u INNER JOIN address a ON u.id = a.user_id ${ew.customSqlSegment} </select>
4-2.IService使用
4-1的查詢數(shù)據(jù)庫的方式相比Mybatis已經(jīng)很方便了,至少不用再手寫sql語句。
但是還可以更簡便,我們可以直接在Controller接口層實現(xiàn)數(shù)據(jù)庫的調(diào)用。
首先和4-1一樣,需要提前準(zhǔn)備Mapper、pojo、Service、ServiceImpl、Controller
改造Service層
public interface xxService extends IService<你的pojo> { }
改造ServiceImpl層
@Service public class xxServiceImpl extends ServiceImpl<你的Mapper, 你的pojo> implements xxService { }
然后就可以在Controller使用了
新增
- save是新增單個元素
- saveBatch是批量新增
- saveOrUpdate是根據(jù)id判斷,如果數(shù)據(jù)存在就更新,不存在則新增
- saveOrUpdateBatch是批量的新增或修改
刪除
- removeById:根據(jù)id刪除
- removeByIds:根據(jù)id批量刪除
- removeByMap:根據(jù)Map中的鍵值對為條件刪除
- remove(Wrapper<T>):根據(jù)Wrapper條件刪除
修改
- updateById:根據(jù)id修改
- update(Wrapper<T>):根據(jù)UpdateWrapper修改,Wrapper中包含set和where部分
- update(T,Wrapper<T>):按照T內(nèi)的數(shù)據(jù)修改與Wrapper匹配到的數(shù)據(jù)
- updateBatchById:根據(jù)id批量修改
查詢
- getById:根據(jù)id查詢1條數(shù)據(jù)
- getOne(Wrapper<T>):根據(jù)Wrapper查詢1條數(shù)據(jù)
- getBaseMapper:獲取Service內(nèi)的BaseMapper實現(xiàn),某些時候需要直接調(diào)用Mapper內(nèi)的自定義SQL時可以用這個方法獲取到Mapper
?
- listByIds:根據(jù)id批量查詢
- list(Wrapper<T>):根據(jù)Wrapper條件查詢多條數(shù)據(jù)
- list():查詢所有
?
- count():統(tǒng)計所有數(shù)量
- count(Wrapper<T>):統(tǒng)計符合Wrapper條件的數(shù)據(jù)數(shù)量
到此這篇關(guān)于MyBatis無縫轉(zhuǎn)MyBatis-plus的基本使用的文章就介紹到這了,更多相關(guān)MyBatis無縫轉(zhuǎn)MyBatis-plus內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談Java中實現(xiàn)深拷貝的兩種方式—clone() & Serialized
這篇文章主要介紹了Java中實現(xiàn)深拷貝的兩種方式—clone() & Serialized,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03最新Spring Security實戰(zhàn)教程之Spring Security安全框架指南
SpringSecurity是Spring生態(tài)系統(tǒng)中的核心組件,提供認(rèn)證、授權(quán)和防護(hù)機(jī)制,以保護(hù)應(yīng)用免受各種安全威脅,它支持多種認(rèn)證方式,并通過攔截器和過濾器鏈進(jìn)行安全檢查,本文通過搭建SpringBoot+SpringSecurity項目,幫助如何快速上手并應(yīng)用SpringSecurity,感興趣的朋友一起看看吧2025-03-03Java 數(shù)據(jù)結(jié)構(gòu)與算法系列精講之環(huán)形鏈表
無論是靜態(tài)鏈表還是動態(tài)鏈表,有時在解決具體問題時,需要我們對其結(jié)構(gòu)進(jìn)行稍微地調(diào)整。比如,可以把鏈表的兩頭連接,使其成為了一個環(huán)狀鏈表,通常稱為循環(huán)鏈表2022-02-02