Mybatis動態(tài)調(diào)用表名和字段名的解決方法
一直在使用Mybatis這個ORM框架,都是使用mybatis里的一些常用功能。今天在項(xiàng)目開發(fā)中有個業(yè)務(wù)是需要限制各個用戶對某些表里的字段查詢以及某些字段是否顯示,如某張表的某些字段不讓用戶查詢到。這種情況下,就需要構(gòu)建sql來動態(tài)傳入表名、字段名了?,F(xiàn)在對解決方法進(jìn)行下總結(jié),希望對遇到同樣問題的伙伴有些幫助。
動態(tài)SQL是mybatis的強(qiáng)大特性之一,mybatis在對sql語句進(jìn)行預(yù)編譯之前,會對sql進(jìn)行動態(tài)解析,解析為一個BoundSql對象,也是在此處對動態(tài)sql進(jìn)行處理。下面讓我們先來熟悉了mybatis里#{}與${}的用法:
在動態(tài)sql解析過程,#{}與${}的效果是不一樣的:
#{ } 解析為一個 JDBC 預(yù)編譯語句(prepared statement)的參數(shù)標(biāo)記符。
如以下sql語句
select * from user where name = #{name};
會被解析為:
select * from user where name = ?;
可以看到#{}被解析為一個參數(shù)占位符?。
${ } 僅僅為一個純碎的 string 替換,在動態(tài) SQL 解析階段將會進(jìn)行變量替換
如一下sql語句:
select * from user where name = ${name};
當(dāng)我們傳遞參數(shù)“sprite”時,sql會解析為:
select * from user where name = "sprite";
可以看到預(yù)編譯之前的sql語句已經(jīng)不包含變量name了。
綜上所得, ${ } 的變量的替換階段是在動態(tài) SQL 解析階段,而 #{ }的變量的替換是在 DBMS 中。
#{}與${}的區(qū)別可以簡單總結(jié)如下:
#{}將傳入的參數(shù)當(dāng)成一個字符串,會給傳入的參數(shù)加一個雙引號
${}將傳入的參數(shù)直接顯示生成在sql中,不會添加引號
#{}能夠很大成都上防止sql注入,${}無法防止sql注入
${}在預(yù)編譯之前已經(jīng)被變量替換了,這會存在sql注入的風(fēng)險。如下sql
select * from ${tableName} where name = ${name}
如果傳入的參數(shù)tableName為user; delete user; --,那么sql動態(tài)解析之后,預(yù)編譯之前的sql將變?yōu)椋?/p>
select * from user; delete user; -- where name = ?;
--之后的語句將作為注釋不起作用,頓時我和我的小伙伴驚呆了?。?!看到?jīng)],本來的查詢語句,竟然偷偷的包含了一個刪除表數(shù)據(jù)的sql,是刪除,刪除,刪除?。。≈匾氖虑檎f三遍,可想而知,這個風(fēng)險是有多大。
${}一般用于傳輸數(shù)據(jù)庫的表名、字段名等
能用#{}的地方盡量別用${}
進(jìn)入正題,通過上面的分析,相信大家可能已經(jīng)對如何動態(tài)調(diào)用表名和字段名有些思路了。示例如下:
<select id="getUser" resultType="java.util.Map" parameterType="java.lang.String" statementType="STATEMENT">
select
${columns}
from ${tableName}
where COMPANY_REMARK = ${company}
</select>
要實(shí)現(xiàn)動態(tài)調(diào)用表名和字段名,就不能使用預(yù)編譯了,需添加statementType="STATEMENT"" 。
statementType:STATEMENT(非預(yù)編譯),PREPARED(預(yù)編譯)或CALLABLE中的任意一個,這就告訴 MyBatis 分別使用Statement,PreparedStatement或者CallableStatement。默認(rèn):PREPARED。這里顯然不能使用預(yù)編譯,要改成非預(yù)編譯。
其次,sql里的變量取值是${xxx},不是#{xxx}。
因?yàn)?{}是將傳入的參數(shù)直接顯示生成sql,如${xxx}傳入的參數(shù)為字符串?dāng)?shù)據(jù),需在參數(shù)傳入前加上引號,如:
String name = "sprite"; name = "'" + name + "'";
總結(jié)
以上所述是小編給大家介紹的Mybatis動態(tài)調(diào)用表名和字段名的解決方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
本文轉(zhuǎn)自:http://www.yuanrengu.com/index.php/mybatis1021.html
相關(guān)文章
springboot實(shí)現(xiàn)文件上傳步驟解析
這篇文章主要介紹了springboot實(shí)現(xiàn)文件上傳步驟解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-12-12
Spring Cloud Alibaba Nacos 入門詳解
這篇文章主要介紹了Spring Cloud Alibaba Nacos入門詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-03-03
解決spring懶加載以及@PostConstruct結(jié)合的坑
這篇文章主要介紹了解決spring懶加載以及@PostConstruct結(jié)合的坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12
SpringMVC自定義攔截器實(shí)現(xiàn)過程詳解
這篇文章主要介紹了SpringMVC自定義攔截器實(shí)現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-05-05
Java中由substring方法引發(fā)的內(nèi)存泄漏詳解
這篇文章主要介紹了Java中由substring方法引發(fā)的內(nèi)存泄漏詳解,涉及substring方法引發(fā)的內(nèi)存泄漏簡介,substring的作用和實(shí)現(xiàn)原理等相關(guān)內(nèi)容,具有一定借鑒價值,需要的朋友可以參考下2017-12-12
SpringCloud之Admin服務(wù)監(jiān)控實(shí)現(xiàn)流程示例詳解
這篇文章主要為大家介紹了SpringCloud之Admin服務(wù)監(jiān)控流程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
java基于正則提取字符串中的數(shù)字功能【如提取短信中的驗(yàn)證碼】
這篇文章主要介紹了java基于正則提取字符串中的數(shù)字功能,可用于提取短信中的驗(yàn)證碼,涉及java基于正則的字符串匹配相關(guān)操作技巧,需要的朋友可以參考下2017-01-01
springboot連接不同數(shù)據(jù)庫的寫法詳解
這篇文章主要介紹了springboot連接不同數(shù)據(jù)庫的寫法?,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-04-04

