MyBatis分頁查詢與特殊字符處理方式
一、引言
1.1 簡介Mybatis
MyBatis是一種基于Java的持久層框架,它實現(xiàn)了對數(shù)據(jù)庫的操作,并使用Java對象映射關(guān)系表中的記錄,即將關(guān)系數(shù)據(jù)庫中的數(shù)據(jù)映射到Java對象中,提供了一種優(yōu)雅的方式來訪問關(guān)系數(shù)據(jù)庫。
MyBatis最重要的特點是它的SQL映射,使得開發(fā)人員可以使用XML或注解的方式將SQL語句與Java代碼進行解耦,從而提高了代碼的可維護性和可讀性,并降低了整個應(yīng)用程序的復(fù)雜度。MyBatis還支持動態(tài)SQL,這意味著你可以在不同的場景下根據(jù)不同的條件來生成SQL查詢語句。
MyBatis已經(jīng)成為Java開發(fā)領(lǐng)域中最受歡迎的持久層框架之一,廣泛應(yīng)用于企業(yè)級應(yīng)用程序中。
有時候我們需要從不同的角度來理解技術(shù)概念,下面我將用類比的方式介紹MyBatis
MyBatis就像一個翻譯,它將數(shù)據(jù)庫中的信息轉(zhuǎn)化成為Java對象,或者將Java對象的更新操作翻譯成為對數(shù)據(jù)庫的更新。這樣,我們就不需要直接去操作數(shù)據(jù)庫,而是通過MyBatis來完成交互。MyBatis就像翻譯一樣,幫助我們用更加簡單、易懂的方式與數(shù)據(jù)庫進行交互。
在MyBatis中,我們可以使用類似于翻譯所用的“語言工具”——SQL映射,來定義連接數(shù)據(jù)庫的語句。這就像在翻譯時,使用特定的語言工具來對話一樣,我們可以使用SQL映射來定義與數(shù)據(jù)庫交互時的具體步驟。
此外,MyBatis還支持動態(tài)SQL,這意味著我們可以根據(jù)不同的需要,動態(tài)生成SQL語句。我們可以將其想象成翻譯時要根據(jù)不同的場景,采用不同的語言表達。
總的來說,MyBatis就是一個用于數(shù)據(jù)庫交互的“翻譯”,它通過SQL映射實現(xiàn)對數(shù)據(jù)庫的操作,幫助我們更好地理解和使用數(shù)據(jù)庫。
1.2分頁查詢的重要性
- 分頁查詢是指將查詢結(jié)果按照固定的每頁大小分割成若干頁,使得客戶端可以分批次獲取數(shù)據(jù),從而避免一次性獲取過多數(shù)據(jù)導(dǎo)致內(nèi)存溢出或網(wǎng)絡(luò)傳輸延遲過高等問題。在實際項目中,分頁查詢有著非常重要的作用。
- 首先,分頁查詢可以提高系統(tǒng)的性能和效率。如果不進行分頁查詢,在數(shù)據(jù)量比較大的情況下,一次性將所有數(shù)據(jù)都查詢出來,需要占用大量內(nèi)存和計算資源,導(dǎo)致系統(tǒng)緩慢、響應(yīng)時間延長。而通過分頁查詢,每次只查詢指定數(shù)量的數(shù)據(jù),大大縮短了查詢時間,節(jié)省了系統(tǒng)資源。
- 其次,分頁查詢可以提升用戶體驗。在網(wǎng)頁、移動應(yīng)用等場景中,如果用戶需要查看全部數(shù)據(jù),而又需要等待很長時間,會給用戶帶來極差的體驗,甚至?xí)?dǎo)致用戶流失。而通過分頁查詢,用戶可以逐頁查看,不需要等待全部數(shù)據(jù)加載完成,提升了用戶的體驗。
- 最后,分頁查詢在數(shù)據(jù)處理和展示方面也非常有用。在面對大量數(shù)據(jù)時,分頁查詢可以按照實際需要展示數(shù)據(jù),讓用戶更加關(guān)注自己感興趣的數(shù)據(jù),同時也可以更靈活地控制數(shù)據(jù)的展示方式和數(shù)量。
分頁查詢就好比我們在閱讀一本厚厚的書籍時,為了方便閱讀和理解,我們會將書籍按照章節(jié)或者頁碼進行分割,每次只閱讀一頁或者一段內(nèi)容,而不是一次性將整本書全部閱讀完畢。
這樣做的好處是,首先可以提高我們閱讀的效率,不需要一次性讀完整本書,而是按需閱讀,可以更快地找到我們感興趣的內(nèi)容。其次,分頁查詢可以減少我們的記憶負擔,不需要一次性記住整本書的內(nèi)容,而是只需要記住當前閱讀的部分內(nèi)容即可。此外,分頁查詢還可以提供快速定位和導(dǎo)航的功能,我們可以根據(jù)需要跳轉(zhuǎn)到指定的頁碼或者按照特定的條件進行查詢。
類似地,分頁查詢在軟件開發(fā)中也具有類似的作用。當我們需要查詢大量的數(shù)據(jù)時,為了提高查詢效率和用戶體驗,我們可以將數(shù)據(jù)按照一頁一頁的方式進行分割,每次只查詢一頁或者一段數(shù)據(jù),而不是一次性將所有數(shù)據(jù)都查詢出來。這樣可以減少網(wǎng)絡(luò)傳輸量,降低服務(wù)器資源消耗,并且支持快速定位和導(dǎo)航功能,方便用戶快速找到所需的數(shù)據(jù)。
因此,分頁查詢在實際開發(fā)中具有重要性,可以提高查詢效率,減少資源消耗,支持快速定位和導(dǎo)航,以及適應(yīng)數(shù)據(jù)量的動態(tài)變化。通過將數(shù)據(jù)分割成一頁一頁的方式進行查詢,可以更好地滿足用戶的需求,提高系統(tǒng)的性能和用戶體驗。
1.3MyBatis特殊字符處理的挑戰(zhàn)
當我們在使用MyBatis這個數(shù)據(jù)庫操作框架時,有時會涉及到特殊字符的處理,這可能會帶來一些問題。讓我們用更通俗的語言來解釋一下這個情況。
挑戰(zhàn)1:SQL注入漏洞
SQL注入是一種常見的攻擊方式,攻擊者可以通過在用戶輸入中插入惡意SQL代碼來篡改數(shù)據(jù)庫查詢。MyBatis中如果沒有正確處理特殊字符,可能會導(dǎo)致應(yīng)用程序受到SQL注入攻擊。
想象一下,你在一個網(wǎng)站上搜索商品,輸入關(guān)鍵詞后網(wǎng)站會幫你從數(shù)據(jù)庫中找到相關(guān)商品。但是,如果網(wǎng)站沒有正確處理你輸入的內(nèi)容,有些聰明的人可能會在搜索框里輸入一些惡意的代碼,從而讓網(wǎng)站執(zhí)行不正常的操作,甚至可能竊取數(shù)據(jù)。這就好比在搜索框里輸入一些“壞話”,讓網(wǎng)站被欺騙了。
挑戰(zhàn)2:查詢結(jié)果異常
特殊字符可能會干擾數(shù)據(jù)庫查詢,導(dǎo)致查詢結(jié)果不符合預(yù)期。例如,如果查詢中包含未經(jīng)處理的特殊字符,可能會導(dǎo)致查詢條件被解釋錯誤,進而返回不正確的數(shù)據(jù)。
想象一下,你在圖書館借書,但是圖書管理員誤解了你的請求。這可能導(dǎo)致你拿到一本和你想要的完全不同的書。在數(shù)據(jù)庫中,特殊字符可能會讓查詢的時候出現(xiàn)類似的誤解,導(dǎo)致我們得到錯誤的信息。
挑戰(zhàn)3:數(shù)據(jù)完整性問題
特殊字符可能會影響數(shù)據(jù)庫的數(shù)據(jù)完整性。例如,某些特殊字符可能會被誤認為是SQL關(guān)鍵字或操作符,從而破壞原本的查詢邏輯,甚至影響數(shù)據(jù)庫中的數(shù)據(jù)。
假設(shè)你是一位餐廳的服務(wù)員,你接受顧客點餐。如果你沒有聽清楚或者誤解了顧客的點餐要求,可能會讓廚房做出錯誤的菜品。在數(shù)據(jù)庫中,特殊字符可能讓我們誤解用戶的請求,可能導(dǎo)致我們處理錯誤的數(shù)據(jù)。
挑戰(zhàn)4:跨平臺兼容性
不同的數(shù)據(jù)庫系統(tǒng)對于特殊字符的處理方式可能會有所不同。在應(yīng)用程序需要在不同數(shù)據(jù)庫平臺之間切換時,特殊字符的處理可能會變得更加復(fù)雜,需要考慮跨平臺的兼容性問題。
想象一下,你習(xí)慣用母語和朋友交流,但是突然要和外國朋友用另一種語言交流,可能會有些困難。在數(shù)據(jù)庫中,不同的數(shù)據(jù)庫系統(tǒng)也有自己的語言規(guī)則,特殊字符在這些規(guī)則之間可能會有不同的解釋,導(dǎo)致我們在切換數(shù)據(jù)庫平臺時遇到困難。
挑戰(zhàn)5:用戶體驗
用戶輸入的特殊字符如果沒有得到適當處理,可能會導(dǎo)致應(yīng)用程序出現(xiàn)錯誤,影響用戶體驗。為了確保應(yīng)用的穩(wěn)定性和友好性,特殊字符處理是至關(guān)重要的。
想象一下,你在一個購物網(wǎng)站想買一款商品,但是網(wǎng)站出現(xiàn)了錯誤,你無法完成購買。這會讓你感到很糟糕,不是嗎?特殊字符如果沒有被正確處理,可能會導(dǎo)致網(wǎng)站出錯,影響用戶的使用體驗。
為了應(yīng)對這些挑戰(zhàn),就像我們需要用心傾聽朋友的話語一樣,MyBatis在處理特殊字符時需要小心謹慎。我們可以采取一些方法,比如把特殊字符翻譯成一種安全的語言,就像把外語翻譯成我們能理解的語言一樣。或者我們可以事先檢查一下用戶輸入的內(nèi)容,確保它是合法和安全的,就像在點餐前確認一下顧客的需求一樣。通過這些方法,我們可以保護數(shù)據(jù)庫的安全,同時提供良好的用戶體驗。
如何應(yīng)對挑戰(zhàn)
為了有效地應(yīng)對這些挑戰(zhàn),可以考慮以下策略:
參數(shù)化查詢: 在使用MyBatis進行數(shù)據(jù)庫查詢時,盡量使用參數(shù)化查詢而不是將用戶輸入直接插入SQL語句中。參數(shù)化查詢能夠防止惡意輸入被解釋為代碼。
就好比在餐廳點餐時,我們告訴服務(wù)員我們想要的食物,而不是親自去廚房告訴廚師。在數(shù)據(jù)庫查詢中,我們可以使用參數(shù)化查詢,將我們需要的信息告訴MyBatis,它會幫助我們構(gòu)建查詢語句。這樣做可以防止不良的輸入被當作“壞代碼”執(zhí)行。
字符轉(zhuǎn)義: MyBatis提供了字符轉(zhuǎn)義的方法,可以將特殊字符轉(zhuǎn)換為安全的形式,避免其被錯誤解釋。例如,使用<![CDATA[ ]]>
來包裹包含特殊字符的查詢。
像是在寫信時,如果我們想要在信中表達特殊意義的詞匯,我們會用特殊的標記或符號來表示。在MyBatis中,我們可以使用特殊的符號(例如<![CDATA[ ]]>
)來“包裝”包含特殊字符的查詢語句,這樣可以確保這些字符被正確理解,不會引發(fā)錯誤。
輸入驗證: 在接受用戶輸入之前,進行必要的輸入驗證和過濾,確保只有合法的輸入被傳遞給數(shù)據(jù)庫查詢。
就好比在接受朋友的禮物前,我們會先檢查一下禮物是否合適,是不是有什么問題。在數(shù)據(jù)庫查詢中,我們在使用用戶提供的信息前,可以進行驗證和過濾,確保只有合法、安全的內(nèi)容被傳遞給數(shù)據(jù)庫,就像我們只接受合適的禮物一樣。
使用框架工具: MyBatis有一些第三方的分頁插件和安全插件,可以幫助處理分頁和特殊字符問題。例如,PageHelper插件可以簡化分頁查詢,同時提供一些防范SQL注入的措施。
有些時候,我們會使用一些工具來幫助我們完成任務(wù),就像在做家務(wù)時使用掃帚一樣。在MyBatis中,有一些第三方插件可以幫助我們更容易地處理分頁和特殊字符問題。例如,有一個叫做PageHelper的插件可以簡化分頁查詢,同時幫助我們防范SQL注入等問題。
測試和審查: 在實施特殊字符處理的策略后,進行充分的測試和代碼審查,確保特殊字符處理能夠在不同場景下正常工作,并且不會引入新的問題。
在采取措施后,我們通常會檢查一下結(jié)果是否符合預(yù)期,以確保沒有問題出現(xiàn)。在MyBatis中也是一樣,我們可以進行充分的測試,確認特殊字符處理在不同情況下都能正常工作。同時,通過代碼審查,我們可以確保特殊字符處理的策略沒有引入新的錯誤。
總之,MyBatis特殊字符處理的挑戰(zhàn)需要認真對待。通過采取適當?shù)念A(yù)防措施和安全策略,可以有效地減輕這些挑戰(zhàn)帶來的風(fēng)險,保護應(yīng)用程序的安全和穩(wěn)定性。
二、Mybatis分頁查詢
2.1 Mybatis分頁查詢的原理
MyBatis是一種Java持久層框架,用于簡化與數(shù)據(jù)庫的交互操作。在MyBatis中進行分頁查詢是常見的需求,其原理涉及兩個主要方面:SQL語句的編寫和數(shù)據(jù)庫的分頁機制。
以下是MyBatis分頁查詢的基本原理:
SQL語句編寫: 在MyBatis中,你需要編寫支持分頁的SQL語句。通常使用LIMIT
和OFFSET
關(guān)鍵字來實現(xiàn)分頁。LIMIT
用于指定每頁顯示的記錄數(shù),OFFSET
表示從查詢結(jié)果中的第幾條記錄開始獲取數(shù)據(jù)。示例SQL語句:
sql
SELECT * FROM your_tableLIMIT #{pageSize} OFFSET #{offset}
在MyBatis的Mapper XML文件中,你可以通過參數(shù)化的方式傳遞pageSize
和offset
的值。
- Java代碼配置: 在Java代碼中,你需要配置分頁參數(shù)和調(diào)用MyBatis的查詢方法。通常使用一個包含分頁信息的Java對象來傳遞給Mapper中的方法。這個Java對象通常包含當前頁數(shù)、每頁記錄數(shù)等信息。
- 數(shù)據(jù)庫分頁機制: 不同的數(shù)據(jù)庫系統(tǒng)有不同的分頁機制。例如,MySQL使用
LIMIT
和OFFSET
來實現(xiàn)分頁,而Oracle數(shù)據(jù)庫使用ROWNUM
或ROW_NUMBER()
函數(shù)。MyBatis會根據(jù)不同的數(shù)據(jù)庫類型生成相應(yīng)的分頁SQL。 - 執(zhí)行查詢: MyBatis框架會根據(jù)配置和傳遞的參數(shù)生成分頁SQL語句,然后執(zhí)行查詢。查詢結(jié)果將被映射到Java對象中,你可以通過這些對象獲取分頁數(shù)據(jù)。
- 返回結(jié)果: 查詢結(jié)果會包含所請求頁的數(shù)據(jù),你可以將這些數(shù)據(jù)返回給調(diào)用方進行顯示或處理。
在MyBatis中,分頁查詢通常涉及到兩個參數(shù):當前頁碼和每頁記錄數(shù)。MyBatis會根據(jù)這些參數(shù)計算出offset
,以及動態(tài)生成適合數(shù)據(jù)庫類型的分頁SQL語句。以下是一個簡單的MyBatis分頁查詢示例:
java
public interface YourMapper { List<YourEntity> getRecordsWithPagination(@Param("offset") int offset, @Param("pageSize") int pageSize); }
xml
<!-- Mapper XML --> <select id="getRecordsWithPagination" resultType="your.package.YourEntity"> SELECT * FROM your_table LIMIT #{pageSize} OFFSET #{offset} </select>
在調(diào)用MyBatis的查詢方法時,你需要計算offset
的值,這可以通過(currentPage - 1) * pageSize
來實現(xiàn),其中currentPage
是當前頁碼。
MyBatis的分頁查詢原理涉及到SQL語句的編寫、Java代碼的配置和數(shù)據(jù)庫的分頁機制。
通過合理配置和使用參數(shù),你可以在MyBatis中實現(xiàn)有效的分頁查詢功能。
簡單點來解釋MyBatis分頁查詢原理時,你可以把它想象成在圖書館找一本厚厚的書:
- 找書目標: 假設(shè)你要從圖書館的書架上找到一本書,但你不想一次拿太多,想分幾次拿。這本書的內(nèi)容就相當于數(shù)據(jù)庫中的數(shù)據(jù)。
- 拿書策略: 你決定每次拿出固定數(shù)量的書,比如每次拿10本,然后你想從書架的特定位置開始拿,不從第一頁開始,因為這樣效率更高。這個拿書的策略就相當于數(shù)據(jù)庫的分頁操作。
- 書的位置: 你知道你要從書架的第100本開始拿,這是因為之前已經(jīng)拿過前面的書。這個位置就相當于數(shù)據(jù)庫中的偏移量(OFFSET)。
- 每次拿多少: 你決定每次拿10本書,這樣不會太重。這個數(shù)量就相當于數(shù)據(jù)庫中每頁顯示的記錄數(shù)(pageSize)。
- 總共多少本: 你可能還會翻開書來看一下總共有多少本,這樣你就知道要拿幾次才能把整本書拿完。這個總數(shù)就相當于數(shù)據(jù)庫中總記錄數(shù)。
- 整理書籍: 每次拿完書后,你把它們整理在一起,方便后面閱讀。這就相當于把數(shù)據(jù)庫查詢結(jié)果映射到Java對象中,方便后續(xù)處理。
綜合起來,MyBatis分頁查詢原理就像你在圖書館里找書一樣,通過明確的目標、選擇合適的策略、計算書的位置和數(shù)量,以及整理書籍,最終從數(shù)據(jù)庫中獲取所需的分頁數(shù)據(jù)。
Mybatis 內(nèi)部使用 RowBounds 對象進行分頁,需要注意的是,它是針對 ResultSet 結(jié)果集執(zhí)行的內(nèi)存分頁,而非數(shù)據(jù)庫分頁。
所以,生產(chǎn)環(huán)境中,不適合直接使用 MyBatis 原有的 RowBounds 對象進行分頁。而是使用如下兩種方案:
在 SQL 內(nèi)手動書寫數(shù)據(jù)庫分頁的參數(shù)來完成分頁功能,樣例代碼如下:
select * from t_user limit #{start}, #{pageSize}
也可使用開源的分頁插件來完成數(shù)據(jù)庫分頁, 如:
Mybatis-PageHelper
MyBatis-Plus ()
: (未來使用更加廣泛)
注意:由于分頁插件是自動添加limit
拼接,往往針對一些復(fù)雜 SQL, 無法達到最大的 SQL 性能,更推薦手寫分頁 SQL, 也就是第一種方式。
2.2 使用RowBounds進行分頁查詢
使用RowBounds
是在MyBatis中進行分頁查詢的一種方式。
RowBounds
允許你在查詢方法中指定起始偏移量(offset)和要返回的最大記錄數(shù)(limit),從而實現(xiàn)分頁效果。
以下是如何使用RowBounds
進行分頁查詢的步驟:
更新Mapper接口: 首先,在你的Mapper接口中,修改查詢方法的簽名,以便接受RowBounds
參數(shù)。例如:
java
public interface YourMapper { List<YourEntity> getRecordsWithPagination(RowBounds rowBounds); }
編寫Mapper XML: 在Mapper XML文件中,編寫SQL查詢語句,但不再使用LIMIT
和OFFSET
關(guān)鍵字來分頁。相反,你可以使用RowBounds
參數(shù)的信息來處理分頁。示例:
xml
<!-- Mapper XML --> <select id="getRecordsWithPagination" resultType="your.package.YourEntity"> SELECT * FROM your_table </select>
調(diào)用查詢方法: 在Java代碼中,調(diào)用查詢方法時,創(chuàng)建一個RowBounds
對象并傳遞給查詢方法。你需要設(shè)置起始偏移量和最大記錄數(shù)。例如:
java
RowBounds rowBounds = new RowBounds(offset, pageSize); List<YourEntity> records = yourMapper.getRecordsWithPagination(rowBounds);
其中,offset
是計算得出的偏移量,而pageSize
是每頁顯示的記錄數(shù)。
使用RowBounds
的好處是,它更緊密地與MyBatis的核心結(jié)合,但它可能在某些情況下不夠靈活,特別是在一些高級用例中。如果你需要更多的分頁控制,你可能需要考慮其他方式,如基于插件的分頁支持或使用PageHelper
等第三方插件。
總之,使用RowBounds
進行分頁查詢是MyBatis的一種原生方式,它允許你在查詢方法中直接處理分頁參數(shù),而不需要在SQL中使用LIMIT
和OFFSET
關(guān)鍵字。
- 解釋:如何使用
RowBounds
進行分頁查詢,你可以將其類比成閱讀一本書,你只想看書中的某一頁內(nèi)容,而不是從頭到尾閱讀整本書。 - 選擇目標頁: 假設(shè)你正在閱讀一本書,你想跳到書中的某一頁。這個目標頁就相當于數(shù)據(jù)庫中的某個分頁。
- 確定起始位置: 你會在書的目錄或章節(jié)列表中查找目標頁的起始位置,這告訴你在哪一頁開始。這個起始位置就相當于數(shù)據(jù)庫中的偏移量(offset)。
- 閱讀多少頁: 你決定從目標頁開始閱讀多少頁,這個數(shù)量決定了你要閱讀多少內(nèi)容。這個數(shù)量就相當于數(shù)據(jù)庫中每頁的記錄數(shù)(pageSize)。
- 獲取內(nèi)容: 你按照上述信息翻到目標頁的起始位置,并開始閱讀,只關(guān)注閱讀多少頁的內(nèi)容。這個內(nèi)容就相當于數(shù)據(jù)庫中返回的分頁數(shù)據(jù)。
- 整理信息: 你可以將閱讀到的內(nèi)容記錄下來,以備后續(xù)處理。這就相當于將數(shù)據(jù)庫查詢結(jié)果映射到Java對象中,方便后續(xù)使用。
綜合來看,使用RowBounds
進行分頁查詢就像你閱讀一本書的特定頁,你選擇了目標頁、確定了起始位置、閱讀了特定數(shù)量的頁,然后整理了你所讀的內(nèi)容。這種方式讓你只專注于獲取特定頁的內(nèi)容,而不需要處理過多的細節(jié)。
2.3使用插件進行分頁查詢
使用PageHelper插件進行分頁查詢
pom.xml導(dǎo)入PageHelper插件
<!-- ********************** 分頁 Pom依賴 ********************** --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.2</version> </dependency>
mybatis.xml配置攔截器
<plugins> <!-- 配置分頁插件PageHelper, 4.0.0以后的版本支持自動識別使用的數(shù)據(jù)庫 --> <plugin interceptor="com.github.pagehelper.PageInterceptor"> </plugin> </plugins>
Mapper.xml的配置:
<select id="cx4" resultType="com.liao.model.Book" parameterType="java.util.Map" > select <include refid="Base_Column_List" /> from t_mvc_book where bname like concat('%',#{bname},'%') </select>
導(dǎo)入PageBean工具類
package com.liao.util; import javax.servlet.http.HttpServletRequest; import java.io.Serializable; import java.util.Map; public class PageBean implements Serializable { //頁碼 private int page=1; //每頁顯示記錄數(shù) private int rows=10; //總記錄數(shù) private int total=0; //是否分頁 private boolean isPagination=true; //上一次的請求路徑 private String url; //獲取所有的請求參數(shù) private Map<String,String[]> map; public PageBean() { super(); } //設(shè)置請求參數(shù) public void setRequest(HttpServletRequest req) { String page=req.getParameter("page"); String rows=req.getParameter("rows"); String pagination=req.getParameter("pagination"); this.setPage(page); this.setRows(rows); this.setPagination(pagination); this.url=req.getContextPath()+req.getServletPath(); this.map=req.getParameterMap(); } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public Map<String, String[]> getMap() { return map; } public void setMap(Map<String, String[]> map) { this.map = map; } public int getPage() { return page; } public void setPage(int page) { this.page = page; } public void setPage(String page) { if(null!=page&&!"".equals(page.trim())) this.page = Integer.parseInt(page); } public int getRows() { return rows; } public void setRows(int rows) { this.rows = rows; } public void setRows(String rows) { if(null!=rows&&!"".equals(rows.trim())) this.rows = Integer.parseInt(rows); } public int getTotal() { return total; } public void setTotal(int total) { this.total = total; } public void setTotal(String total) { this.total = Integer.parseInt(total); } public boolean isPagination() { return isPagination; } public void setPagination(boolean isPagination) { this.isPagination = isPagination; } public void setPagination(String isPagination) { if(null!=isPagination&&!"".equals(isPagination.trim())) this.isPagination = Boolean.parseBoolean(isPagination); } /** * 獲取分頁起始標記位置 * @return */ public int getStartIndex() { //(當前頁碼-1)*顯示記錄數(shù) return (this.getPage()-1)*this.rows; } /** * 末頁 * @return */ public int getMaxPage() { int totalpage=this.total/this.rows; if(this.total%this.rows!=0) totalpage++; return totalpage; } /** * 下一頁 * @return */ public int getNextPage() { int nextPage=this.page+1; if(this.page>=this.getMaxPage()) nextPage=this.getMaxPage(); return nextPage; } /** * 上一頁 * @return */ public int getPreivousPage() { int previousPage=this.page-1; if(previousPage<1) previousPage=1; return previousPage; } @Override public String toString() { return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", isPagination=" + isPagination + "]"; } }
Mapper類方法:
List<Book> cx4(@Param("bname") String bname);
接口方法:
List<Book> cx4(String bname, PageBean pageBean);
實現(xiàn)接口
@Override public List<Book> cx4(String bname, PageBean pageBean) { if(pageBean!=null && pageBean.isPagination()){ PageHelper.startPage(pageBean.getPage(),pageBean.getRows()); } List<Book> books=bookMapper.cx4("圣墟"); if(pageBean!=null && pageBean.isPagination()){ PageInfo<Book> info = new PageInfo<Book>(books); System.out.println("當前頁:"+ info.getPageNum()); System.out.println("展示記錄數(shù):"+info.getPageSize()); System.out.println("符合查詢條件的總記錄:"+info.getTotal()); pageBean.setTotal((int) info.getTotal()); } return books; }
測試:
@Test public void cx4() { PageBean pageBean=new PageBean();//實例化PageBean pageBean.setPage(2);//第幾頁 pageBean.setRows(15);//顯示的條目 bookBiz.cx4("圣墟",pageBean).forEach(System.out::println);//模糊查詢 }
2.4為什么要重寫MyBatis的分頁?
當我們使用MyBatis來進行數(shù)據(jù)庫操作時,它提供了一個默認的分頁功能,就好比在一本書中,每頁都有固定數(shù)量的字數(shù)。但是,有時候我們的需求可能比較特殊,就像我們希望書中的一頁可以容納更多或者更少的字數(shù)一樣。這時候,我們就需要對MyBatis的分頁功能進行重新設(shè)計,以適應(yīng)我們的特殊需求。
- 特殊需求: 有時候,我們需要按照特定的規(guī)則進行分頁,例如按照不同的條件進行排序,或者按照特殊的算法來分頁。就像我們希望書的每一頁都按照章節(jié)內(nèi)容來分,而不是簡單地按照字數(shù)。
- 特殊數(shù)據(jù)庫: MyBatis的默認分頁插件可以根據(jù)不同的數(shù)據(jù)庫類型自動選擇適合的分頁方法。但是,如果我們使用的是非常特殊的數(shù)據(jù)庫,可能需要自己編寫分頁邏輯,就像我們在一些特殊場合需要用不同的寫作工具一樣。
- 復(fù)雜查詢: 有時候,我們需要進行復(fù)雜的查詢,這些查詢可能無法通過默認的分頁插件實現(xiàn)。就像我們想要在書中找到特定的關(guān)鍵詞所在的頁碼一樣,可能需要更加復(fù)雜的處理。
- 與其他工具整合: 如果我們的項目中還使用了其他框架或者服務(wù),可能需要讓這些工具一起協(xié)作來實現(xiàn)分頁需求。就像我們在多個團隊合作時,需要大家一起努力來達成共同目標。
- 提升性能: 盡管默認分頁插件能夠滿足絕大部分情況,但在處理大量數(shù)據(jù)時,可能會對性能產(chǎn)生影響。這時候,我們可以重新設(shè)計分頁邏輯,以提升查詢性能。
- 特殊數(shù)據(jù)展示: 有時候,我們希望分頁結(jié)果中包含一些特殊的數(shù)據(jù),例如總計數(shù)量、平均值等。就像我們在書的每一頁下面添加一些注釋一樣,這些注釋可能不是原來的內(nèi)容。
原因: Mybatis的分頁功能很弱,它是基于內(nèi)存的分頁(查出所有記錄再按偏移量offset和邊界limit取結(jié)果),在大數(shù)據(jù)量的情況下這樣的分頁基本上是沒有用的
總的來說,重寫MyBatis的分頁功能是為了更好地適應(yīng)我們的特殊需求,就像我們在寫作時需要根據(jù)具體情況來選擇不同的寫作方式。這需要我們對分頁的原理和項目的實際情況有一定的了解,以便更好地滿足我們的業(yè)務(wù)需求。如果默認的分頁功能無法滿足我們的要求,重新設(shè)計分頁邏輯可能會是一個不錯的選擇。
三、特殊字符處理
3.1特殊字符對查詢結(jié)果的影響
特殊字符在數(shù)據(jù)庫查詢結(jié)果中可能會產(chǎn)生不同的影響,取決于數(shù)據(jù)庫查詢語句的構(gòu)造和特殊字符的處理方式。
以下是一些可能的影響情況:
- SQL注入: 如果特殊字符沒有得到正確的處理,惡意用戶可能利用SQL注入攻擊來篡改查詢語句,獲取敏感數(shù)據(jù)或破壞數(shù)據(jù)庫。通過轉(zhuǎn)義字符或參數(shù)化查詢,可以防止這種情況發(fā)生。
- 查詢錯誤: 如果查詢語句中包含未轉(zhuǎn)義的特殊字符,數(shù)據(jù)庫可能會誤解查詢的意圖,導(dǎo)致錯誤的查詢結(jié)果。特別是在需要精確匹配的情況下,如使用
LIKE
運算符時,特殊字符可能引起意外結(jié)果。 - 字符截斷: 如果特殊字符沒有得到正確處理,數(shù)據(jù)庫可能會截斷字符串或?qū)⑵湟暈榉指舴瑥亩鴮?dǎo)致意外的數(shù)據(jù)截斷或分割。
- 特殊符號的顯示: 如果查詢結(jié)果中包含HTML或XML中的特殊字符,如
<
,>
,&
等,可能會影響在網(wǎng)頁或應(yīng)用程序中的顯示效果。這時需要對這些特殊字符進行轉(zhuǎn)義,確保它們能夠正確顯示。 - 轉(zhuǎn)義和反轉(zhuǎn)義問題: 查詢結(jié)果中的特殊字符可能需要在展示時進行轉(zhuǎn)義,但在某些情況下,如果進行了多次轉(zhuǎn)義和反轉(zhuǎn)義,可能會導(dǎo)致特殊字符的處理出現(xiàn)問題。
總之,特殊字符的影響取決于數(shù)據(jù)庫查詢的構(gòu)造、數(shù)據(jù)的處理方式以及在展示時的處理。為了避免問題,應(yīng)當根據(jù)上下文適當?shù)剞D(zhuǎn)義和處理特殊字符,以確保查詢的正確性、安全性和顯示效果。
3.2特殊字符處理的解決方案
根據(jù)情況,您可以選擇其中一個或多個方法來確保在使用 Mybatis 時能夠處理特殊字符并保護應(yīng)用程序的安全性。
針對 Mybatis 中的特殊字符處理,有幾種解決方案可以考慮:
- 使用轉(zhuǎn)義字符: 可以通過在特殊字符前添加轉(zhuǎn)義字符(例如:
\
)來處理特殊字符,以確保它們被正確地插入到 SQL 查詢中。 - 使用正則表達式: 利用正則表達式來檢測并替換掉輸入中的特殊字符,以防止惡意代碼注入。
- 使用預(yù)處理語句: Mybatis 支持使用預(yù)處理語句,這樣數(shù)據(jù)庫會在執(zhí)行查詢之前對輸入進行參數(shù)化處理,從而有效地防止 SQL 注入攻擊。
- 使用特殊字符過濾器: 開發(fā)一個特殊字符過濾器,對輸入進行過濾,將特殊字符或可能引發(fā)安全問題的內(nèi)容進行替換或刪除。
方案一:使用轉(zhuǎn)義字符
轉(zhuǎn)義字符是一種特殊的字符常量。轉(zhuǎn)義字符以反斜線""開頭,后跟一個或幾個字符。轉(zhuǎn)義字符具有特定的含義,不同于字符原有的意義,故稱“轉(zhuǎn)義”字符。例如,在前面各例題printf函數(shù)的格式串中用到的“\n”就是一個轉(zhuǎn)義字符,其意義是“回車換行”。轉(zhuǎn)義字符主要用來表示那些用一般字符不便于表示的控制代碼。
不同的語言有不同的轉(zhuǎn)義符。如HTML轉(zhuǎn)義符、java 轉(zhuǎn)義符、xml 轉(zhuǎn)義符、 oracle 轉(zhuǎn)義符、sql 轉(zhuǎn)義符 、sqlserver 轉(zhuǎn)義符、php 轉(zhuǎn)義符、asp 轉(zhuǎn)義符、vb轉(zhuǎn)義符、 javascript 轉(zhuǎn)義符等等,還有網(wǎng)址中的百分號。
例如:
- HTML的< >&"©分別是 < > & " © 的轉(zhuǎn)義字符
- XML只有5個轉(zhuǎn)義符: < >& " ',分別對應(yīng)<>&"’
轉(zhuǎn)義符使用場景:
例:
- HTML中< > &等字符是有特殊含義的,其中 < > 用于鏈接簽,&用于轉(zhuǎn)義。
- Mybatis中< > 等字符在xml解析中是會報錯的。
特殊字符 | 轉(zhuǎn)義字符 |
---|---|
< | < |
> | > |
& | & |
" | " |
’ | ' |
<= | <= |
>= | >= |
方案二:使用xml的![CDATA[ ]]語法
<![CDATA[ ]]>是xml語法,在<![CDATA[ ]]>內(nèi)部的所有內(nèi)容都會被解析器忽略,不進行轉(zhuǎn)義。
所以在xml中這是一種通用方案。
特殊字符 | <![CDATA[ ]]> |
---|---|
< | <![CDATA[<]]> |
> | <![CDATA[>]]> |
& | <![CDATA[&]]> |
" | <![CDATA["]]> |
’ | <![CDATA[']]> |
<= | <![CDATA[<=]]> |
>= | <![CDATA[>=]]> |
!= | <![CDATA[!=]]> |
四、總結(jié)
Mybatis分頁查詢和特殊字符處理的重要性
當你使用 Mybatis 進行數(shù)據(jù)庫操作時,有兩個關(guān)鍵點至關(guān)重要:
1. 分頁查詢的重要性: 想象你有一個裝滿數(shù)據(jù)的大盒子,而你只能一次拿出一小部分數(shù)據(jù)。如果你試圖一次性拿出所有數(shù)據(jù),你可能會遇到問題:拿不動、耗時很長。分頁查詢就像你每次只拿出盒子里的一部分數(shù)據(jù),這樣做有幾個好處:
速度更快: 不用等到所有數(shù)據(jù)都準備好,所以能更快地開始瀏覽數(shù)據(jù)。不會卡住: 即使數(shù)據(jù)很多,也不會讓你的程序卡住或崩潰。不會忘記: 想象一次要拿出一大堆數(shù)據(jù),你可能會忘記拿哪些了。分頁就像一次只拿幾個,不容易忘記。
2. 特殊字符處理的重要性: 想象你有一個魔法筆,你可以用它寫出各種事物。但有些字會變成魔法,可能會讓你的朋友受傷。處理特殊字符就像你使用那支筆寫字,但在寫之前,你會檢查每個字,如果發(fā)現(xiàn)是魔法字,你會把它們變成普通字。這樣做有幾個好處:
保護朋友: 防止壞人利用魔法字來傷害你的朋友(你的數(shù)據(jù)庫)。保持秩序: 魔法字可能會讓字句變得混亂,處理特殊字符就像保持字句的秩序,讓一切都運行正常。避免麻煩: 如果你不處理特殊字符,你的字句可能變得奇怪,就像句子中出現(xiàn)亂碼,這會引起很多麻煩。
綜上所述,分頁查詢和特殊字符處理在數(shù)據(jù)庫操作中起著類似于整理數(shù)據(jù)和保護數(shù)據(jù)的作用,讓數(shù)據(jù)庫操作更快、更安全、更可靠。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
spring 或者spring boot 調(diào)整bean加載順序的方式
這篇文章主要介紹了spring 或者spring boot 調(diào)整bean加載順序的方式,本文通過實例代碼講解三種調(diào)整類加載順序的方式,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03詳解Spring緩存注解@Cacheable,@CachePut , @CacheEvict使用
這篇文章主要介紹了詳解Spring緩存注解@Cacheable,@CachePut , @CacheEvict使用,非常具有實用價值,需要的朋友可以參考下2017-05-05Java的外部類為什么不能使用private和protected進行修飾的講解
今天小編就為大家分享一篇關(guān)于Java的外部類為什么不能使用private和protected進行修飾的講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-04-04Spring?Cloud中Sentinel的兩種限流模式介紹
如何使用Sentinel做流量控制呢?這篇文章就來為大家詳細介紹了Spring?Cloud中Sentinel的兩種限流模式,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-05-05