最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis 探秘之#{} 與 ${} 參傳差異解碼(數(shù)據(jù)庫連接池筑牢數(shù)據(jù)交互根基)

 更新時間:2024年12月30日 11:18:52   作者:GGBondlctrl  
本文詳細(xì)介紹了MyBatis中的`#{}`和`${}`的區(qū)別與使用場景,包括預(yù)編譯SQL和即時SQL的區(qū)別、安全性問題,以及如何正確使用數(shù)據(jù)庫連接池來提高性能,感興趣的朋友一起看看吧

???1. #{} 與 ${}的使用

我們在之前的學(xué)習(xí)中,了解到了“#{}”,但是這里的${}是什么呢?其實這里的${}也具有參數(shù)傳遞的功能但是我們之前為什么不使用$符號呢?且聽下面的分析過程~~~

1.1integer類型數(shù)據(jù)

我們可以通過id類整型參數(shù)的傳遞進(jìn)行實驗,首先得先創(chuàng)建一個數(shù)據(jù)庫,如下所示:

接下來我們知己使用XML的方式進(jìn)行代碼的編寫:

在Mapper類中:

 List<UserInfo> select2(Integer id);

 這里先定義數(shù)據(jù)的返回類型,然后再在XML文件中實現(xiàn)查詢SQL的方法:

<select id="select2" resultType="com.example.mybatis.Model.UserInfo">
        select * from user_info where id=#{id}
    </select>

然后再測試類進(jìn)行測試后們可以看到如下的打印的日志:

解釋:

可以發(fā)現(xiàn)在SQL查詢語句中,參數(shù)被“?”給替代了,然后下面的參數(shù)就是“2”,此時可以了解到我們輸?的參數(shù)并沒有在后?拼接,id的值是使? ? 進(jìn)?占位. 這種SQL 我們稱之為"預(yù)編譯SQL"

然后我們將這里的“#{ }” 替換成“${}”,具體的情況就是如下所示的:

解釋:

可以發(fā)現(xiàn)此時SQL語句,就沒有“?”,然后下面的paramters參數(shù)就為空了,然后我們就知道${} 會直接進(jìn)?字符替換, ?起對SQL進(jìn)?編譯,不會像#號一樣使用占位符;這種我們就稱之為即時SQL

1.2String類型數(shù)據(jù)

這里我們使用String類來進(jìn)行匹配查詢,具體的操作還是和上面差不多;

Mapper類的代碼如下:

 List<UserInfo> selectAllByUsername(String username);

然后再XML寫SQL語句的操作:

解釋:

此時可以看到,和上面的string類型的數(shù)據(jù)是一樣的,這里會標(biāo)明參數(shù)的類型為string類型,然后再進(jìn)行替換占位的時候會自動添加引號;

然后我們將這里的“#{ }” 替換成“${}”,具體的情況就是如下所示的:

 <select id="selectAllByUsername" resultType="com.example.mybatis.Model.UserInfo">
        select * from user_info where username=${username}
    </select>

這里就是通過輸入的名字進(jìn)行查詢,將這#號替換成了$符號,然后再測試類進(jìn)行測試后打印的日志報錯了,具體的打印日志如下所示:

解釋:

這里可以看到此時的$符號的操作,出現(xiàn)了報錯,原因就是BadSql,我們在上面看到,由于直接代替的原因,查詢條件中字符串沒有出現(xiàn)“ '  '  ”符號,即引號,然后就是SQL語句語法不正確導(dǎo)致錯誤;

解決辦法:

在XML編寫SQL語句的時候進(jìn)行手動添加' ';

代碼如下:

<select id="selectAllByUsername" resultType="com.example.mybatis.Model.UserInfo">
        select * from user_info where username='${username}'
    </select>

此時進(jìn)行測試打印,打印的日志就是如下所示的:

解釋:此時可以看到在字符串添加了“ ' ' ”雙引號,然后參數(shù)仍然為空;

綜上所述:

#{} 使?的是預(yù)編譯SQL, 通過 ? 占位的?式, 提前對SQL進(jìn)?編譯, 然后把參數(shù)填充到SQL語句中. #{} 會根據(jù)參數(shù)類型, ?動拼接引號 '' .
${} 使用的就是即時編譯SQL,會直接進(jìn)?字符替換, ?起對SQL進(jìn)?編譯. 如果參數(shù)為字符串, 需要加上引號 ''

???2. #{} 與 ${}的區(qū)別

2.1性能

當(dāng)客?發(fā)送?條SQL語句給服務(wù)器后, ?致流程如下:

1. 解析語法和語義, 校驗SQL語句是否正確
2. 優(yōu)化SQL語句, 制定執(zhí)?計劃
3. 執(zhí)?并返回結(jié)果

?條 SQL如果?上述流程處理, 我們稱之為 Immediate Statements(即時 SQL) 

但是絕?多數(shù)情況下, 某?條 SQL 語句可能會被反復(fù)調(diào)?執(zhí)?, 或者每次執(zhí)?的時候只有個別的值不同(?如 select 的 where ?句值不同, update 的 set ?句值不同, insert 的 values 值不同). 如果每次都需要經(jīng)過上?的語法解析, SQL優(yōu)化、SQL編譯等,則效率就明顯不?了

總結(jié): 

所以預(yù)編譯SQL就在執(zhí)行上述的優(yōu)化操作后,遇到同樣的SQL語句,就不會對SQL進(jìn)行再次的優(yōu)化編譯了,就直接改變參數(shù),省去了解析優(yōu)化等過程, 以此來提?效率

預(yù)編譯SQL的性能比即時SQL的性能更高;

2.2安全性 

這里出現(xiàn)的安全性就是(SQL注入)

SQL注?:是通過操作輸?的數(shù)據(jù)來修改事先定義好的SQL語句,以達(dá)到執(zhí)?代碼對服務(wù)器進(jìn)?攻擊的?法。由于沒有對??輸?進(jìn)?充分檢查,?SQL?是拼接?成,在??輸?參數(shù)時,在參數(shù)中添加?些SQL關(guān)鍵字,達(dá)到改變SQL運(yùn)?結(jié)果的?的,也可以完成惡意攻擊

注意:這里只針對的就是${ }符號;

假如我們在此符號中添加    ' or 1='1

然后在#{ }運(yùn)行中,可以發(fā)現(xiàn)此時的此時的打印日志告訴我們,這里的字符串在數(shù)據(jù)庫中沒有找到

如下所示:

這里的結(jié)果確實如我們所料,但是在${ }符號中,如下所示:

解釋:

哎奇怪,怎么會出現(xiàn)這種情況,這個字符串在我們的數(shù)據(jù)庫列中就沒有這個字段;但是為啥就全部搜索出來了呢??

因為拼接的問題和原因,所以這里出現(xiàn)了誤判,'  {'    or     1='1}  ' 拼接后成了以下SQL語句

'  '    or     1='1'

解釋:

具體的意思就是為空或者為true,這就是為啥全部搜索出來了,這里存在SQL關(guān)鍵字or;

所以SQL注?是?種?常常?的數(shù)據(jù)庫攻擊?段, SQL注?漏洞也是?絡(luò)世界中最普遍的漏洞之?.
如果發(fā)?在??登錄的場景中, 密碼輸?為 ' or 1='1 , 就可能完成登錄;

總之在后面的學(xué)習(xí)中能用#{} 那么就使用#{ },${ }非特殊情況盡量不要使用 

???3.${ }使用場景

3.1排序

在實現(xiàn)排序功能的時候,由于“desc”不需要使用引號,所以這里我們就可以使用${}符號

具體的代碼如下所示:

<select id="selectAllById" resultType="com.example.mybatis.Model.UserInfo">
        select * from user_info order by id ${sort}
    </select>

這里即時XML的寫法,可以看到此時order by id然后排序關(guān)鍵詞,就不需要引號,那么此時我們就可以使用$符號;

在測試類中的實現(xiàn)代碼:

 @Test
    void selectAllById() {
        userInfoXMLMapper.selectAllById("desc");
    }

我們這里就是按照降序排序進(jìn)行查詢結(jié)果的排序的,最后打印的日志如下所示:

解釋:

上面的兩行就是SQL語句和參數(shù),參數(shù)為空,然后即時SQL進(jìn)行拼接,SQL語句就成為了一個查詢語句按照降排序的方式進(jìn)行查詢結(jié)果的展示;

3.2模糊查詢

代碼如下所示:

 <select id="selectByUsername" resultType="com.example.mybatis.Model.UserInfo">
        select * from user_info where username like '%${username}%'
    </select>

這里也是不需要引號,然后也可以使用$符號,在測試類中代碼:

@Test
    void selectByUsername() {
        userInfoXMLMapper.selectByUsername("o");
    }

最后打印的日志如下所示:

解釋:

這里的模糊查詢,中間的參數(shù)是不需要自動添加引號的,并且這里的模糊查詢的條件就是查找名字里包含“o”的那一段數(shù)據(jù);

但是這里由于注入等安全性,這里我們可以使用#進(jìn)行另一種寫法,具體的代碼如下所示:

 <select id="selectByUsername2" resultType="com.example.mybatis.Model.UserInfo">
        select * from user_info where username like concat('%',#{username},'%')
    </select>

解釋:

這里使用concat關(guān)鍵字,實現(xiàn)需要引號的拼接操作,這樣就可以使用#{}來進(jìn)行參數(shù)的傳遞,幾避免了SQL注入的安全問題,還可能提高了執(zhí)行的效率;

???4.數(shù)據(jù)庫連接池

4.1介紹

數(shù)據(jù)庫連接池負(fù)責(zé)分配、管理和釋放數(shù)據(jù)庫連接,它允許應(yīng)?程序重復(fù)使??個現(xiàn)有的數(shù)據(jù)庫連接,?不是再重新建??個

沒有使?數(shù)據(jù)庫連接池的情況: 每次執(zhí)?SQL語句, 要先創(chuàng)建?個新的連接對象, 然后執(zhí)?SQL語句, SQL語句執(zhí)?完, 再關(guān)閉連接對象釋放資源. 這種重復(fù)的創(chuàng)建連接, 銷毀連接?較消耗資源

使?數(shù)據(jù)庫連接池的情況: 程序啟動時, 會在數(shù)據(jù)庫連接池中創(chuàng)建?定數(shù)量的Connection對象, 當(dāng)客?請求數(shù)據(jù)庫連接池, 會從數(shù)據(jù)庫連接池中獲取Connection對象, 然后執(zhí)?SQL, SQL語句執(zhí)?完, 再把Connection歸還給連接池 

優(yōu)點:

1. 減少了?絡(luò)開銷
2. 資源重?
3. 提升了系統(tǒng)的性能 

4.2使用

常?的數(shù)據(jù)庫連接池:

• C3P0
• DBCP
• Druid
• Hikari

主流就是Hikari,Druid;

我們的SpringBoot默認(rèn)使用的就是Hikari;日志如下所示:

可以看到這就是springboot默認(rèn)使用的就是Hikari;

???5.總結(jié)

本期小編主要講解了關(guān)于#{ },${ },的區(qū)別與如何進(jìn)行使用,講解了兩者的性能比較,比較重要的SQL注入的問題,以及簡單的闡述了數(shù)據(jù)庫連接池的介紹~~~

到此這篇關(guān)于MyBatis 探秘:#{} 與 ${} 參傳差異解碼,數(shù)據(jù)庫連接池筑牢數(shù)據(jù)交互根基的文章就介紹到這了,更多相關(guān)MyBatis #{} 與 ${} 參傳差異解碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

黄山市| 浦县| 调兵山市| 南陵县| 芦溪县| 平昌县| 梨树县| 赣州市| 汨罗市| 工布江达县| 琼结县| 溧阳市| 萝北县| 七台河市| 平邑县| 普安县| 丹寨县| 陇川县| 清涧县| 达州市| 修武县| 成都市| 孝昌县| 当阳市| 海口市| 香格里拉县| 马龙县| 明光市| 冀州市| 磐石市| 黑水县| 延津县| 观塘区| 三都| 林周县| 莒南县| 白玉县| 磐石市| 周口市| 如皋市| 汉寿县|