Java面試題沖刺第九天–MyBatis
面試題1:你怎麼理解ORM框架,常見的ORM框架都有哪些?
正經回答:
對象關系映射(Object Relational Mapping,簡稱ORM)
,主要實現程序對象到關系數據庫數據的映射。
JAVA編程免不瞭和數據庫打交道,那麼如何高效便捷地操作數據庫,也是一個需要應對的問題,原生的基於JDBC的方式非常低效,而且要寫一大堆無用的模板代碼
,不值得選取。ORM是對JDBC的封裝
,讓我們不需要重復的造輪子,目前已經有很多優秀的ORM框架可供使用瞭,常見的比如Mybatis(batis)、Hibernate、Jpa、Jdo等。
優點:
- ORM是對JDBC的封裝,從而解決瞭JDBC的各種存在問題,提高效率
- 使開發更加對象化
- 可移植性強
- 可以很方便地引入數據緩存之類的附加功能
缺點:
- 自動化進行關系數據庫的映射需要消耗少量系統性能。
- 在處理多表聯查、where條件復雜之類的查詢時,ORM的語法會變得復雜。
市面上主流ORM框架:
- EJB:重量級、高花費的ORM技術,支持JPA,尤其是EJB3低侵入式 的設·計,增加瞭Annotation
- Hibernate:開源,支持JPA ,被選作JBoss的持久層解決方案
- iBatis:”SQL Mapping”框架,Apache軟件基金組織的子項目,後 轉Google Code旗下,ibatis3.x正式更名為Mybatis
- Spring Data JPA:Spring框架中的子模塊
- TopLink:Oracle公司的產品
- Open JPA:Apache軟件基金組織的開源項目
追問1:大傢都在用Mybatis,Mybatis都有哪些優勢?
- Mybatis入門簡單;在使用上,對於熟悉編寫SQL的同學來說,基本上是即學即用。
Mybatis對jdbc的抽象封裝程度更高
,spring jdbc要想實現的細節很多,例如Mybatis封裝瞭更多的對象映射。支持註解
,面對接口開發,效率高,分分鐘解決一個sql。- 對於復雜的SQL,springJDBC編寫麻煩,動態SQL語句設計也麻煩,相比之下,Mybatis更加靈活且人性化。
- mybatis的高度封裝,使得程序員可專註與業務層,開發效率高。所以選擇mybatis的開發公司多。
面試題2:相比較Hibernate與Mybatis,你有哪些看法?
正經回答:
Hibernate與MyBatis都可以是通過SessionFactoryBuider由XML配置文件生成SessionFactory,然後由SessionFactory 生成Session,最後由Session來開啟執行事務和SQL語句。其中SessionFactoryBuider,SessionFactory,Session的生命周期都是差不多的。
Hibernate和MyBatis都支持JDBC和JTA事務處理。
Mybatis優勢
- MyBatis可以進行更為細致的SQL優化,可以減少查詢字段。
- MyBatis容易掌握,而Hibernate門檻較高。
Hibernate優勢
- Hibernate的DAO層開發比MyBatis簡單,Mybatis需要維護SQL和結果映射。
- Hibernate對對象的維護和緩存要比MyBatis好,對增刪改查的對象的維護要方便。
- Hibernate數據庫移植性很好,MyBatis的數據庫移植性不好,不同的數據庫需要寫不同SQL。
- Hibernate有更好的二級緩存機制,可以使用第三方緩存。MyBatis本身提供的緩存機制不佳。
摘自某乎上的經典總結:
Hibernate
- Hibernate功能強大,數據庫無關性好,O/R映射能力強,如果你對Hibernate相當精通,而且對Hibernate進行瞭適當的封裝,那麼你的項目整個持久層代碼會相當簡單,需要寫的代碼很少,開發速度很快,非常爽。
- Hibernate的缺點就是學習門檻不低,要精通門檻更高,而且怎麼設計O/R映射,在性能和對象模型之間如何權衡取得平衡,以及怎樣用好Hibernate方面需要你的經驗和能力都很強才行。
MyBatis
- MyBatis入門簡單,即學即用,提供瞭數據庫查詢的自動對象綁定功能,而且延續瞭很好的SQL使用經驗,對於沒有那麼高的對象模型要求的項目來說,相當完美。
- MyBatis的缺點就是框架還是比較簡陋,功能尚有缺失,雖然簡化瞭數據綁定代碼,但是整個底層數據庫查詢實際還是要自己寫的,工作量也比較大,而且不太容易適應快速數據庫修改。 深入追問: 追問1:Hibernate與Mybatis 的緩存機制都有哪些區別?
相同點:
Hibernate和Mybatis的二級緩存除瞭采用系統默認的緩存機制外,都可以通過實現你自己的緩存或為其他第三方緩存方案,創建適配器來完全覆蓋緩存行為。
不同點:
Hibernate的二級緩存配置在SessionFactory生成的配置文件中進行詳細配置,然後再在具體的表-對象映射中配置是那種緩存。
MyBatis的二級緩存配置都是在每個具體的表-對象映射中進行詳細配置,這樣針對不同的表可以自定義不同的緩存機制。並且Mybatis可以在命名空間中共享相同的緩存配置和實例,通過Cache-ref來實現。
兩者比較: 因為Hibernate對查詢對象有著良好的管理機制,用戶無需關心SQL。所以在使用二級緩存時如果出現臟數據,系統會報出錯誤並提示。
而MyBatis在這一方面,使用二級緩存時需要特別小心。如果不能完全確定數據更新操作的波及范圍,避免Cache的盲目使用。否則,臟數據的出現會給系統的正常運行帶來很大的隱患。
面試題3:Mybatis中的#{}和${}有哪些區別
正經回答:
-- #{} <select id="userLogin" parameterType="java.util.Map" resultMap="userResMap"> select id, username, password, role from user where username = #{username} and password = #{password} </select> -- ${} <select id="userLogin" parameterType="java.util.Map" resultMap="userResMap"> select id, username, password, role from user where username = ${username} and password = ${password} </select>
1.#將傳入的數據都當成一個字符串,會對自動傳入的數據加一個雙引號。
如:where username=#{username},
如果傳入的值是111,那麼解析成sql時的值為where username=“111”, 如果傳入的值是id,則解析成的sql為where username=“id”.
2.$將傳入的數據直接顯示生成在sql中。
如:where username=${username},
如果傳入的值是111,那麼解析成sql時的值為where username=111;
那麼,如果傳入的值是:;drop table user
;會怎麼樣?解析後的sql為:
select id, username, password, role from user where username=;drop table user;
#方式能夠很大程度防止sql註入,$方式無法防止Sql註入。
$方式一般用於傳入數據庫對象,例如傳入表名;
一般能用#的就別用$
,若不得不使用 “${xxx}”
這樣的參數,要手工地做好過濾工作,來防止sql註入攻擊。
在MyBatis中,“${xxx}”
這樣格式的參數會直接參與SQL編譯,從而不能避免註入攻擊。但涉及到動態表名和列名時,隻能使用“${xxx}”
這樣的參數格式。所以,這樣的參數需要我們在代碼中手工進行處理來防止註入。
綜上,我們在編寫MyBatis的映射語句時,盡量采用“#{xxx}”
這樣的格式。若不得不使用“${xxx}”
這樣的參數,要手工地做好過濾工作,來防止SQL註入攻擊。
深入追問:
追問1:什麼是sql註入?
sql註入是一種代碼註入技術,用於攻擊數據驅動的應用,惡意的SQL語句被插入到執行的實體字段中(例如,為瞭轉儲數據庫內容給攻擊者)
說到SQL註入,相信大傢都不陌生,這是黑客同學常用的一種攻擊方式。攻擊者在界面的表單信息或URL上輸入一些奇怪的SQL片段(例如“or ‘1'='1'
”這樣的語句),有可能入侵參數檢驗不足的應用程序。
所以,在我們的應用中需要做一些工作,來防備這樣的攻擊方式。在一些安全性要求很高的應用中(比如銀行軟件),經常使用將SQL語句全部替換為存儲過程這樣的方式,來防止SQL註入。這當然是一種很安全的方式,但我們平時開發中,可能不需要這種死板的方式。
追問2:mybatis是如何做到防止sql註入的?
MyBatis框架作為一款半自動化的持久層框架,其SQL語句都要我們自己手動編寫,這個時候當然需要防止SQL註入。其實,MyBatis的SQL是一個具有“輸入+輸出”的功能,類似於函數的結構,參考上面的兩個例子。
其中,parameterType表示瞭輸入的參數類型,resultType表示瞭輸出的參數類型。回應上文,如果我們想防止SQL註入,理所當然地要在輸入參數上下功夫。上面代碼中使用#的即輸入參數在SQL中拼接的部分,傳入參數後,打印出執行的SQL語句,會看到SQL是這樣的:
select id, username, password, role from user where username=? and password=?
不管輸入什麼參數,打印出的SQL都是這樣的。這是因為MyBatis啟用瞭預編譯功能,在SQL執行前,會先將上面的SQL發送給數據庫進行編譯;執行時,直接使用編譯好的SQL,替換占位符“?”就可以瞭。因為SQL註入隻能對編譯過程起作用,所以這樣的方式就很好地避免瞭SQL註入的問題。
總結
本篇文章就到這裡瞭,希望能給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!
推薦閱讀:
- java中mybatis和hibernate的用法總結
- Mybatis是這樣防止sql註入的
- SQL註入詳解及防范方法
- java中Hibernate面試知識點整理
- mybatis映射和實際類型不一致的問題