javascript
MyBatis+Spring MVC开发指南(一)
前言
MyBatis+Spring MVC這套組合,在實際互聯網項目中非常流行,博主工作中也涉及過,打算由淺入深、系統的寫出來!這個系列將會涵蓋MyBatis開發詳解、Spring MVC開發詳解,以及2者的結合使用,并會分析它們的原理!(可以參考博主的另一篇文章了解Spring MVC原理:《寫出我的第一個框架:迷你版Spring MVC》)
?
沒有MyBatis之前
在早期,我們都是通過原生的JDBC來操作數據庫的,而這種方式存在很多問題。
我們先來看一個例子:
原生JDBC操作方式?
問題有哪些呢?
第一,在創建數據庫連接這塊,程序是需要時創建,用完后關閉。如果頻繁的創建、關閉數據庫連接,顯然存在問題。當然,我們可以通過數據庫連接池來處理這個問題。
第二,硬編碼的地方太多了。比如,數據庫連接相關的一些信息,SQL相關的一些信息。當然,我們可以通過使用配置文件,來避免這個問題。
第三,實質上,我們編寫JDBC是有步驟可循的,比如,我們得先得到數據庫連接對象,得有SQL,有輸入參數,設置參數,去執行SQL,然后遍歷結果集將數據庫SQL執行的結果對象轉化為JAVA對象,然后再去業務處理,最后釋放資源。那么這個過程,實際上是個模板,能不能抽離出來,更好的去完成這個過程呢?
比如,Hibernate,這個純粹的ORM(對象關系映射)框架,讓程序員以面向對象的方式來完成數據庫的操作,功能很強大,SQL都幫我們自動生成了,但是這也帶來了一些其他問題,比如門檻較高,有時候我們想編寫SQL,修改SQL,優化SQL都費勁,在互聯網項目快速迭代開發中,太過笨重了!
基于這些因素,出現了iBatis,并發展為今天的MyBatis,作為Apache的頂級項目,目前已經托管到github下。
?
MyBatis框架的架構
上面我們說了一些JDBC的缺點,而MyBatis是避免了這些問題的。如果讓我們來實現MyBatis的話,我們會怎么想呢?
第一,應該存在一個配置文件A,可以將數據庫的連接信息,事務信息等放入其中;
第二,應該提供一個配置文件B,可以讓程序員編寫SQL,重點需要解決的是如何給SQL傳遞參數,以及如何將結果映射為JAVA對象;
第三,應該提供API可以執行文件B中的SQL
基于上面的分析,我們來看一下MyBatis的架構:
MyBatis的架構?
這里,我們先簡單了解些概念:
SqlSessionFactory用于創建SqlSession,SqlSession即操作DB的接口,其內部借助Executor執行器完成對數據庫的操作。
全局配置文件,就是圖中的SqlMapConfig.xml;SQL文件即是Mapper.xml文件。
對于MappedStatement而言,會完成輸入映射以及輸出映射。
?
Quick Start
這里先寫個簡單的DEMO帶大家初步了解下。
POM依賴:
pom.xml?
MyBatis的全局配置文件:
SqlMapConfig.xml?
需要注意下:
第一,我們把MySQL的一些連接信息放入到db.properties中,使用<properties>標簽加載屬性文件,并通過${XXX}的方式引用。
第二,要知道現在的日志框架有很多,這里使用<settings>設置下日志使用LOG4J實現。
第三,我們說SQL結果集要完成到JAVA對象的映射,那么根據反射的原理,我們都能猜到必須要提供帶包路徑的全限定名稱,那么為了簡化,提供<typeAliases>標簽進行別名映射處理。提供了2種方式,一個是單個的類型別名映射,一個是基于包掃描的批量映射。當然批量映射的別名就是類名。
第四,需要<mappers>標簽加載SQL文件。同上面一樣,也提供了基于包掃描的批量加載。
log4j.properties:
log4j.properties?
在開發階段,顯然,我們希望MyBatis能夠為我們打印SQL日志,方便調試,排查問題。
SQL配置:
Student.xml?
需要關注下:
第一,namespace,顧名思義,命名空間,其實是想隔離SQL,不過到了MyBatis和Spring結合使用時,具有特殊的意義。這里暫且使用全限定類名。
第二,<select>等SQL Command標簽需要一個ID,還需要輸入參數parameterType,輸出參數映射resultType等。其實這些在MyBatis的底層封裝成了一個MappedStatement對象。當然定位這個對象,需要namespace.id的方式。
第三,${value} VS #{xxx}
其實2者,都可以接受JAVA簡單類型,如int,也可以接受POJO,Map等復雜類型。如果是JAVA簡單類型,那么$的方式必須是${value},而#{}可以隨意,是因為在這種情況下,$會通過反射getValue()的方式取值。如果是POJO等復雜類型,2者其實都可以通過OGNL表達式取到,只不過#會額外的進行JAVA類型到數據庫類型的轉換,而$沒有類型處理過程,它直接拼接。也就是說#會使用預編譯成?,而$將在SQL編譯階段就采取替換操作,可能帶來SQL注入的問題。所以在實際開發中,我們當然優先采用#的方式取值。
測試程序:
Test?
測試程序,并沒有太多可以說的,關注2點即可:
第一,selectOne VS selectList
顯然,我們需要清楚的知道,SQL返回的結果集是一條記錄,還是多條記錄,如果使用selectOne那么必須最多返回一條記錄。那么返回多條記錄與返回一條記錄的時候,resultType有變化么?(其實是不變的。)
第二,SqlSession
SqlSessionFactoryBuilder -> SqlSessionFactory -> SqlSession
我們重點關注的是SqlSession,它其實是一個interface,定義了很多操作數據庫的接口,而且extends Closeable,很明確是需要close的。
它的實現類DefaultSqlSession中有一些數據域(比如說autoCommit,在默認情況下是不開啟自動提交的),而且方法也并不是Synchronized,這說明SqlSession并不是線程安全的,因此我們應該是局部使用SqlSession,使用完畢后close掉。
?
Mapper代理開發
其實,除了Mapper代理開發外,還有一種原始Dao開發的方式。原始Dao開發方式的思路大致是這樣的:
第一,我們提供Dao接口,有增、刪、改、查的方法。
第二,我們提供Dao的實現類,在實現類中,我們利用Spring注入SqlSessionFactory,然后在各個方法中得到SqlSession,進行操作后,關閉SqlSession即可。
這種方式,重復的代碼太多,已經OUT了,目前使用最多的就是Mapper代理開發。
提供Mapper.java接口:
Mapper接口?
提供與之對應的Mapper.xml文件:
StudentMapper.xml?
在全局配置文件中加載Mapper.xml:
加載mapper.xml配置?
測試代碼示例:
調用方式?
從這里,你應該可以看出Mapper的開發應該遵循一些規范,這樣MyBatis才可以自動幫助我們生成XXXMapper類的代理實現類。(說白了,這些規范,就是為了利用反射)
第一,保證XXXMapper.xml中的namespace同XXXMapper.java的全限定名稱一致
第二,保證XXXMapper.xml中的Statement的ID同XXXMapper.java的方法名稱一致
第三,保證XXXMapper.xml中的Statement的輸入參數的類型(parameterType)、輸出參數的類型(resultType)同XXXMapper.java的保持一致
從這里,你大致可以了解到Mapper代理開發,程序員主要關注的就是Mapper.java以及Mapper.xml的生成,可以說極大的簡化了工作量!
?
關于自增主鍵返回
很多時候,我們面臨這樣的需求,A表的字段ID是主鍵,而且是auto_increment自動增長的;我們完成A表的插入后,希望得到主鍵,以便后續的操作,比如另外一個表B,和表A存在主外鍵關系。
MyBatis當然早就替我們想好了,只需要稍微配置下,就可以將MySQL自動生成的主鍵取出設置到對應的JAVA對象的屬性上。
看一個例子:
自動獲取主鍵設置?
特別注意keyProperty是表示將獲取到的自動增長的值設置到哪個Field域上。
?
關于動態SQL
我們知道,在JSP中,可以使用JSTL標簽開發;而動態SQL就是類似于JSTL的一組標簽,可以幫助我們靈活的生成SQL,比如實現判斷,遍歷數組/集合,SQL片段的復用等。值得關注的是,有些標簽還挺智能,比如<where>還可以替你去掉第一個and.....
本篇博客并不會說明各個標簽的使用方式,這樣的例子,網上很多,大家可以參考。一句話,在開發階段,我們只需要讓MyBatis打印SQL,我們就能明白,我們的動態SQL是不是使用對了!
?
到這里,本篇博客就準備結束了,下一篇博客將會為大家介紹MyBatis的一些高級開發知識~
See U next time~
作者:張豐哲
鏈接:https://www.jianshu.com/p/91a32e3d4b26
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權并注明出處。
總結
以上是生活随笔為你收集整理的MyBatis+Spring MVC开发指南(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我是如何指数级提升开发技术的?
- 下一篇: 【手写系列】透彻理解MyBatis设计思