Mybatis-Plus實(shí)現(xiàn)自定義SQL具體方法
1.簡(jiǎn)介
Mybatis-Plus(以下簡(jiǎn)稱MBP)的初衷是為了簡(jiǎn)化開(kāi)發(fā),而不建議開(kāi)發(fā)者自己寫(xiě)SQL語(yǔ)句的;但是有時(shí)客戶需求比較復(fù)雜,僅使用MBP提供的Service,Mapper與Wrapper進(jìn)行組合,難以實(shí)現(xiàn)可以需求; 這時(shí)我們就要用到自定義的SQL了。
Java 開(kāi)發(fā)使用 mybatis-plus 來(lái)執(zhí)行 sql 操作,往往比 mybatis 能夠省時(shí)省力,因?yàn)?mybatis-plus 封裝了很多常用的接口。但對(duì)于一些更為復(fù)雜的查詢來(lái)說(shuō),mybatis-plus 也相形見(jiàn)絀,還得需要我們自定義 sql 語(yǔ)句。本文就來(lái)介紹一下在使用 mybatis-plus/mybatis 的情況下,如何自定義 sql 語(yǔ)句、動(dòng)態(tài) sql 等。
Mybatis-Plus實(shí)現(xiàn)自定義的方式有以下幾種:
1)注解SQL
2)Wrapper傳參+注解SQL
局限性:不適用于多表關(guān)聯(lián)查詢,查詢字段過(guò)多代碼比較凌亂
3)Wrapper傳參+XML文件SQL:推薦
4)對(duì)象傳參+XML文件SQL
最傳統(tǒng)的寫(xiě)法,流程過(guò)于繁瑣,簡(jiǎn)單的單表查詢時(shí),配置麻煩
2.自定義SQL具體實(shí)現(xiàn)
2.1.注解SQL
Mybatis-plus提供了注解SQL功能,可以通過(guò)注解方式實(shí)現(xiàn)SQL的編寫(xiě),注解SQL的前提是在Mybatis的配置文件中開(kāi)啟注解功能。
我們可以在Mapper的繼承類中,使用完整的自定義SQL;
//多數(shù)據(jù)源情況下,@DS注解用于指定數(shù)據(jù)源 @DS("zw-mysqldb") public interface CarMapper extends BaseMapper<Car> { @Select("select * from car where car_seq = #{carSeq}") Car queryCar(String carSeq); }
@RequestMapping("/ok") public void testCustomSQL2() { Car car = carMapper.queryCar("11"); System.out.println(car.toString()); }
補(bǔ)充:
1)使用@Param注解 當(dāng)以下面的方式進(jìn)行寫(xiě)SQL語(yǔ)句時(shí): @Select("select column from table where userid = #{userid} ") public int selectColumn(int userid); 當(dāng)你使用了使用@Param注解來(lái)聲明參數(shù)時(shí),如果使用 #{} 或 ${} 的方式都可以。 @Select("select column from table where userid = ${userid} ") public int selectColumn(@Param("userid") int userid); 當(dāng)你不使用@Param注解來(lái)聲明參數(shù)時(shí),必須使用使用 #{}方式。如果使用 ${} 的方式,會(huì)報(bào)錯(cuò)。 @Select("select column from table where userid = ${userid} ") public int selectColumn(@Param("userid") int userid); 2)不使用@Param注解 不使用@Param注解時(shí),參數(shù)只能有一個(gè),并且是Javabean。在SQL語(yǔ)句里可以引用JavaBean的屬性,而且只能引用JavaBean的屬性。 // 這里id是user的屬性 @Select("SELECT * from Table where id = ${id}") Enchashment selectUserById(User user);
上面的代碼中使用了注解SQL的方式,通過(guò)@Select注解指定了SQL語(yǔ)句。在方法中使用@Param注解指定參數(shù)名稱,可以方便的進(jìn)行參數(shù)傳遞,參數(shù)名稱與sql參數(shù)名稱一致可省略。
注解SQL的優(yōu)點(diǎn)是代碼簡(jiǎn)潔,可讀性好,同時(shí)也可以結(jié)合Wrapper等方式進(jìn)行復(fù)雜的SQL構(gòu)建。
2.2.Wrapper傳參+注解SQL
使用Wrapper方式的一些使用場(chǎng)景:
1)動(dòng)態(tài)查詢:使用Wrapper可以根據(jù)不同的查詢條件,動(dòng)態(tài)地拼接SQL語(yǔ)句,實(shí)現(xiàn)精確查詢。
2)多表聯(lián)合查詢:在多表聯(lián)合查詢時(shí),使用Wrapper可以方便地拼接SQL語(yǔ)句,實(shí)現(xiàn)多表聯(lián)合查詢。
3)分頁(yè)查詢:在分頁(yè)查詢時(shí),使用Wrapper可以方便地拼接SQL語(yǔ)句,實(shí)現(xiàn)分頁(yè)功能。
4)條件查詢:使用Wrapper可以根據(jù)不同的條件,動(dòng)態(tài)地拼接SQL語(yǔ)句,實(shí)現(xiàn)條件查詢。
5)排序查詢:使用Wrapper可以方便地拼接SQL語(yǔ)句,實(shí)現(xiàn)排序功能
使用SQL結(jié)合Wrapper進(jìn)行復(fù)雜的SQL構(gòu)建時(shí),通常需要完成以下幾個(gè)步驟:
a)創(chuàng)建Wrapper對(duì)象
通過(guò)創(chuàng)建Wrapper對(duì)象,可以方便地進(jìn)行SQL構(gòu)建和條件設(shè)置。下面是創(chuàng)建Wrapper對(duì)象的示例代碼:
QueryWrapper<Entity> wrapper = new QueryWrapper<>();
b)設(shè)置查詢條件
可以使用Wrapper對(duì)象的方法設(shè)置查詢條件,例如eq、ne等方法可以設(shè)置等于、不等于等條件。下面是設(shè)置查詢條件的示例代碼:
wrapper.eq("column1", value1) .ne("column2", value2) .like("column3", value3); //示例 wrapper.eq("car_state", "1") .like("car_id", "渝A");
c)設(shè)置排序條件(非必須)
可以使用Wrapper對(duì)象的orderBy方法設(shè)置排序條件,例如orderByAsc、orderByDesc等方法可以設(shè)置升序、降序等條件。下面是設(shè)置排序條件的示例代碼:
wrapper.orderByAsc("car_id")
d)設(shè)置分頁(yè)條件(非必須)
可以使用Wrapper對(duì)象的方法設(shè)置分頁(yè)條件,例如page方法可以設(shè)置頁(yè)碼和每頁(yè)大小等條件。下面是設(shè)置分頁(yè)條件的示例代碼:
Page<Car> resultPage = new Page<>(1, 10); carMapper.selectByPrimaryKey(resultPage,wrapper)
e)mapper接口
@Select("select * from car ${ew.customSqlSegment}") Page<Car> selectByPrimaryKey(Page<Car> page, @Param(Constants.WRAPPER) QueryWrapper<Car> queryWrapper);
f)執(zhí)行SQL操作
接口的方法執(zhí)行SQL操作,例如selectList、selectPage等方法可以執(zhí)行SQL查詢操作,也可以自定義查詢。下面是執(zhí)行SQL操作的示例完整代碼:
//分頁(yè)查詢方式1 QueryWrapper<Car> wrapper = new QueryWrapper<>(); Page<Car> resultPage = new Page<>(1, 10); wrapper.eq("car_state", "1") .like("car_id", "渝A") .orderByAsc("car_id");//排序 carMapper.selectByPrimaryKey(resultPage,wrapper); //分頁(yè)查詢方式2 IPage<Car> page = new Page<>(1, 10); // 分頁(yè)查詢 LambdaQueryWrapper<Car> qw = new LambdaQueryWrapper<Car>() .like(Car::getCarId, "渝A") // 車牌號(hào) = .eq(Car::getCarState, 1); // 狀態(tài) //selectPage是BaseMapper自帶方法 IPage<Car> userPage = carMapper.selectPage(page, qw);
注意:
1)QueryWrapper中使用自定義uservo類,不能使用LambdaQueryWrapper
2)上邊涉及到 IPage 和 Page 都可以用用于分頁(yè),這里就涉及到MybatisPlus的幾種方式問(wèn)題
xml文件
g)執(zhí)行結(jié)果:
補(bǔ)充:
在實(shí)際應(yīng)用中,我們還可以使用LambdaQueryWrapper和QueryWrapper實(shí)現(xiàn)更多復(fù)雜的查詢操作,以滿足不同的業(yè)務(wù)需求。例如,我們可以使用LambdaQueryWrapper和QueryWrapper進(jìn)行動(dòng)態(tài)查詢,通過(guò)判斷前端傳入的參數(shù),來(lái)組合SQL語(yǔ)句,實(shí)現(xiàn)靈活的查詢操作
public List<UserEntity> getUserList(String name, Integer age) { LambdaQueryWrapper<UserEntity> qw = new LambdaQueryWrapper<UserEntity>() .eq(StringUtils.isNotEmpty(name), UserEntity::getName, name) // 姓名 = name .gt(age != null, UserEntity::getAge, age); // 年齡 > age return userMapper.selectList(qw); }
以上代碼中,我們通過(guò)LambdaQueryWrapper實(shí)現(xiàn)了動(dòng)態(tài)的查詢操作。如果傳入的name參數(shù)不為空,那么就會(huì)添加一個(gè)等于查詢條件;如果傳入的age參數(shù)不為空,那么就會(huì)添加一個(gè)大于查詢條件。
這樣的查詢操作,可以根據(jù)前端傳入的參數(shù),靈活地組合SQL語(yǔ)句,實(shí)現(xiàn)更多的業(yè)務(wù)需求。
注意:
1)mapper方法里的@Param(Constants.WRAPPER) Wrapper query對(duì)象,Constants.WRAPPER的值就是ew。
2)首先判斷ew.emptyOfWhere是否存在where條件,有的話再拼接上去,3)ew.customSqlSegment該值是WHERE + sql語(yǔ)句,還有個(gè)ew.sqlSegment是不包括WHERE字符串
4)${ew.customSqlSegment}是一個(gè)查詢條件占位符,代表Wapper查詢條件。
當(dāng)然,Mybatis-Plus提供了一些自定義SQL方法,例如selectObjs、selectByMap等,可以直接使用,例如:
List<Object> objs = userMapper.selectObjs( new QueryWrapper<User>().select("max(age)").eq("name", "張三") );
2.3.Wrapper傳參+xml文件SQL
Wrapper傳參是Mybatis中的一種高級(jí)操作方式,可以在查詢時(shí)動(dòng)態(tài)傳遞參數(shù)
1)mapper類
Car selectBySeq @Param(Constants.WRAPPER) QueryWrapper<Car> queryWrapper);
2)xml配置文件
<select id="selectBySeq " resultMap="BaseResultMap"> select * from `car` ${ew.customSqlSegment} </select>
3)通過(guò)Wapper傳遞查詢參數(shù)
使用Wrapper動(dòng)態(tài)傳遞參數(shù)
1.使用Wrapper基類,自定義Where后面的SQL語(yǔ)句;
2.使用QueryWrapper
select | select(String... sqlSelect)
例select("id", "name", "age")
上面兩種方式任意選擇一種,參數(shù)都是Wrapper
@RequestMapping("/ok") public void testCustomSQL2() { LambdaQueryWrapper<Car> query = new LambdaQueryWrapper<>(); query.eq(Car::getCarId, "11"); Car car= carMapper.queryCarSeq(query); System.out.println(car.toString()); } //或者 Wrapper wrapper = new QueryWrapper<Car>().eq("car_state", 1).like("cai_id", "渝"); List<Car> userList = carMapper.queryCarSeq(wrapper);
XML文件SQL和Wrapper傳參結(jié)合的優(yōu)點(diǎn)在于提高了代碼的可維護(hù)性、可讀性和安全性,適用于代碼量大,需要多人協(xié)作開(kāi)發(fā)的場(chǎng)景,并且能夠防止SQL注入攻擊
2.4.正常傳參+XML文件SQL
在resources目錄下創(chuàng)建一個(gè)mapper文件夾,然后創(chuàng)建一個(gè)與Mapper接口同名的xml文件,例如UserMapper.xml,定義自定義SQL語(yǔ)句
//xml文件式,myabtis原生方式 Car selectByAnnotationXML(String seq);
在mapper下創(chuàng)建文件UserDao.xml
<select id="selectByAnnotationXML" parameterType="java.lang.String" resultMap="BaseResultMap"> select * from car where car_seq = #{seq,jdbcType=VARCHAR} </select>
這種方式是在接觸mybatis時(shí)候,最基礎(chǔ)的方式
3.總結(jié)
總的來(lái)說(shuō),sql的寫(xiě)法有兩種,一種是直接使用注解寫(xiě)在mapper方法上,一種是寫(xiě)在xml文件中;傳參的方式也有兩種,一種是通過(guò)方法傳參直接在xml文件中組裝sql,一種是通過(guò)Wapper傳遞參數(shù)條件構(gòu)造器
注解的優(yōu)點(diǎn)
- 簡(jiǎn)潔易懂:相比于XML配置,注解的使用更加簡(jiǎn)潔直觀,使代碼更具可讀性和可維護(hù)性。
- 易于調(diào)試:注解配置可以直接在Java類中編寫(xiě),減少了在XML中查找和修改SQL的時(shí)間。
- 更好的性能:在執(zhí)行大量的增刪改操作時(shí),注解配置的性能更高,因?yàn)闆](méi)有XML解析的開(kāi)銷。
注解的缺點(diǎn)
- 不利于維護(hù):將SQL和Java代碼耦合在一起,使得代碼難以維護(hù)和重構(gòu),特別是在涉及到較復(fù)雜SQL的情況下。
- SQL可讀性差:相比于在XML中編寫(xiě)SQL,注解中的SQL語(yǔ)句通常會(huì)更加冗長(zhǎng)和難以讀懂。
XML的優(yōu)點(diǎn)
- 易于維護(hù):將SQL分離出Java代碼,代碼的維護(hù)性更高,特別是在需要修改SQL時(shí)。
- SQL可讀性好:在XML中編寫(xiě)SQL,可以使得SQL的格式更加清晰,可讀性更強(qiáng)。
- 易于管理:XML配置文件可以全局管理,使得項(xiàng)目的結(jié)構(gòu)更加清晰明了。
XML的缺點(diǎn)
- 繁瑣:XML配置相對(duì)于注解,配置較為繁瑣,需要更多的代碼量。
- 性能問(wèn)題:在執(zhí)行大量操作時(shí),XML的解析和讀取會(huì)占用一定的時(shí)間,降低了系統(tǒng)的性能。
總之,注解和XML的選擇應(yīng)根據(jù)項(xiàng)目的實(shí)際情況和需求進(jìn)行決定。對(duì)于簡(jiǎn)單的查詢和操作,注解可能更加適合;而對(duì)于復(fù)雜的查詢和操作,XML則更加適合。
常用方法參考官方文檔
到此這篇關(guān)于Mybatis-Plus實(shí)現(xiàn)自定義SQL具體方法的文章就介紹到這了,更多相關(guān)Mybatis-Plus自定義SQL內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- mybatis-plus自帶QueryWrapper自定義sql實(shí)現(xiàn)復(fù)雜查詢實(shí)例詳解
- MyBatisPlus自定義SQL的實(shí)現(xiàn)
- mybatis-plus使用xml自定義sql語(yǔ)句方式
- MyBatis-plus如何執(zhí)行自定義SQL
- MyBatis-Plus自定義SQL的詳細(xì)過(guò)程記錄
- MyBatis-Plus 自定義sql語(yǔ)句的實(shí)現(xiàn)
- MybatisPlus使用queryWrapper如何實(shí)現(xiàn)復(fù)雜查詢
- MyBatis-Plus自定義SQL和復(fù)雜查詢的實(shí)現(xiàn)
相關(guān)文章
如何實(shí)現(xiàn)Java監(jiān)聽(tīng)器詳解
今天帶大家了解Java監(jiān)聽(tīng)器是如何實(shí)現(xiàn)的及實(shí)現(xiàn)原理是什么,文中有非常詳細(xì)的說(shuō)明,對(duì)正在學(xué)習(xí)的小伙伴們很有幫助,需要的朋友可以參考下2021-06-06Java使用釘釘創(chuàng)建企業(yè)內(nèi)部機(jī)器人的實(shí)現(xiàn)
釘釘?shù)某霈F(xiàn)為企業(yè)節(jié)約了大量人力成本,其中也開(kāi)放了大量的外部api接口方便企業(yè)使用。本文主要介紹了Java使用釘釘創(chuàng)建企業(yè)內(nèi)部機(jī)器人的實(shí)現(xiàn),感興趣的可以了解一下2021-11-11使用JavaIO流和網(wǎng)絡(luò)制作一個(gè)簡(jiǎn)單的圖片爬蟲(chóng)
這篇文章主要介紹了使用JavaIO流和網(wǎng)絡(luò)制作一個(gè)簡(jiǎn)單的圖片爬蟲(chóng),通過(guò)關(guān)鍵字爬取百度圖片,這個(gè)和我們使用搜索引擎搜索百度圖片是一樣的,只是通過(guò)爬蟲(chóng)可以學(xué)習(xí)技術(shù)的使用,需要的朋友可以參考下2023-04-04關(guān)于SpringCloud的微服務(wù)以及組件詳解
這篇文章主要介紹了關(guān)于SpringCloud的微服務(wù)以及組件詳解,是一個(gè)更高層次的、 架構(gòu)視角的綜合性大型項(xiàng)目, 他的目標(biāo)是構(gòu)建一套標(biāo)準(zhǔn)化的微服務(wù)解決方案,需要的朋友可以參考下2023-05-05mybatis調(diào)用存儲(chǔ)過(guò)程的實(shí)例代碼
這篇文章主要介紹了mybatis調(diào)用存儲(chǔ)過(guò)程的實(shí)例,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-10-10Springboot?整合?RabbitMQ?消息隊(duì)列?詳情
這篇文章主要介紹了Springboot整合RabbitMQ?消息隊(duì)列詳情,文章為榮啊主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-08-08在Spring中使用Knife4j進(jìn)行API文檔生成與管理的操作方法
Knife4j 是為Java MVC 框架(如Spring Boot、Spring MVC等)集成 Swagger 生成 API 文檔的增強(qiáng)解決方案,它基于 Swagger 的核心功能,通過(guò)定制化的前端界面和一些額外的特性,本文介紹了在Spring中使用Knife4j進(jìn)行API文檔生成與管理的操作方法,需要的朋友可以參考下2024-12-12