mybatis與springdata的一些簡單比較與思考

主題

  最近在用mybatis作項目,有一些感觸想記錄下,主要是mybatis(以及它的一些插件)相比較於Spring data(或者jpa,hibernate等)的優點地方.html

 

感觸

我以爲mybatis相比於Spring data的最大的幾個優點的地方在於:spring

 

動態查詢

不論是在以前的公司仍是如今的公司都有不少這樣的業務..好比進來先是一個查詢界面,有N多條件,而後下面是個根據條件分頁查詢的數據,查出數據之後你能夠進行一些修改呀查看呀等等操做.sql

這樣的業務若是是Spring data來作的話比較麻煩.數據庫

由於上面的條件用戶是能夠輸入也能夠不輸入的.在本來的公司我看到有幾種解決方法:json

1.本身動態的拼接hql.因此service的代碼裏會出現不少if(StringUtils.isEmpty(xxxx查詢條件)){hql += "and xxx條件 = :XXX參數"}相似於這樣的代碼.這樣首先是hql拼接,可讀性是比較差的,另外SQL是在service層拼接的.可能代碼複用的機率會小一點.session

2.公司有本身的封裝(http://www.cnblogs.com/abcwt112/p/5874401.html).簡單來講就是指定一下這個查詢是對應哪一個entity.而後根據傳過來的request裏的paramter找到entity對應的field而後仍是拼接sql....只不過本身在service裏不用拼接了...能夠稍微簡化一些代碼...可是不是很靈活..有些功能還沒封裝.好比or的條件鏈接就不行.只能拼接and...而後不能嵌套查詢..因此能夠說是1方法的簡化版可是相比於本身拼接SQL有些經常使用的功能作不到.mybatis

3.雖然公司我一直沒看到有人用過.可是我知道.Spring data是在jpa外包裝了一層,jpa是有criteria的查詢方式的.spring data也有相應的Specifications的那種查詢方式.這種方法能夠幫助咱們動態拼接查詢條件..(這種查詢方式我用的不多.可能說的不必定對).我以爲這種查詢方式有個最不方便的地方在於若是要多表關聯查詢,你的entity裏沒有@onetomany或者@manytomany或者@onetoone這樣的關鍵的話你是取不到另外關聯的那張表的..這樣的話你就不可能拼接那個where條件..這樣的狀況仍是蠻常見的,由於表的關聯太多了.不是全部的關聯都寫成了成員域..因此這種查詢方法也是有缺陷的..架構

總結下的話就是Spring data動態查詢拼接SQL比較麻煩..主要是在service裏常常要判斷XXX參數用戶有沒有輸入..有輸入就hql+=....看起來SQL不直觀.都不知道完整的SQL結構,也很容易拼錯.框架

 

這樣的業務若是mybatis來作:eclipse

1.按照我如今公司的套路,大概是最簡單粗暴的.咱們mybatis沒用任何插件,也沒有自動生成任何XML.純手寫.

那麼我要作的也就是在XML裏寫個查詢SQL對應的select語句.而後再拼接條件的時候能夠用<if>標籤去過濾就好了.

這樣的好處就是SQL比較直觀,到底查什麼表一目瞭然,而後由於拼接SQL至關因而在dao層,因此複用機率會大一些.好比其餘業務也要查這張表的數據,能夠複用.

 

Entity與DTO

這個問題主要是entity與dto之間數據拷貝的問題,還有一些建表問題,沒用過hibernate或者用hibernate自動生成表的朋友可能不會有這樣的感受.

Spring data:

由於spring data數據庫映射到實體用的是entity,而前臺顯示用的是dto.因此數據確定須要拷貝. 另一個比較坑爹的地方是entity若是和spring data的session關聯了的話,若是修改了字段,即便不顯示的調用dao.update,在出了事務之後也會自動更新數據庫的(由於是受管實體).因此拷貝是必須的.這樣的話會須要一些時間,另外對象拷貝也蠻麻煩的.特別是還有集合的狀況更是麻煩.(以前公司用cglib的bean copier http://www.cnblogs.com/abcwt112/p/6073103.html)

還有個小坑就是若是查出來的對象有懶加載的集合屬性,那麼固然先後臺交互的時候,好比用jackson將entity轉化成json的時候會自動調用entity的get方法,致使懶加載被觸發,而後hibernate自動調用SQL去查詢數據,然而那個時候事務早已關閉,會報錯,這也是一個坑,之前公司基本上是一個業務域的相關聯對象一次性查出來(也不是不少數據).

另外當建表不是很規範的時候(好比多表關聯沒有使用外鍵關聯,而是共享主鍵,又是單向關聯的時候)spring data jpa的級聯操做可能會產生問題.(http://www.cnblogs.com/abcwt112/p/4849416.html)

 

mybatis:

很簡單..查出什麼數據直接用....

公司仍然有entity和dto.其實我以爲只須要留下dto就足夠了.有2套對象的話若是dao裏的方法的參數不一樣也是須要轉化的.mybatis只是把數據庫查詢的結果映射到了dto上.我以爲沒那麼複雜...不須要2套對象.只有一套dto就足夠了..還簡單些.

 

非主鍵的CRUD操做

表的主鍵在不少時候都是ID自增或者uuid,可是用戶並不會知道,他們知道的多是業務上面的主鍵,好比超市商品的條形碼等等.這種時候咱們操做數據庫可能不是根據id而是根據這種業務上面的惟一標示去操做數據庫.

spring data:

我一直以爲這是Spring data相比於hibernate和jpa最引覺得傲的功能,能夠根據dao的方法名自動映射成sql.

好比findByName會被自動翻譯成select * from xxx where name = :name

updateNameByStateAndLevelIsNotNull會被自動翻譯成update xxx set name = :name where state = :state and level is not null

能夠說Spring data能夠在絕大部分狀況下避免寫SQL.因此操做數據庫比較方便.美中不足的就是若是SQL比較長參數比較多..那麼方法名也會比較長....有時候看起來比較累.

 

mybatis:

讓我從首選spring data變成首選mybatis做爲持久層框架的一個緣由就在這裏.(雖然spring data已經作的很好了)

按照公司的作法咱們須要手寫SQL...那是很坑爹的.絕對沒有Spring data好用.可是eclipse有個mybatis的generator插件.......

他能夠自動幫咱們生成XML..這裏生成的幾個方法很是很是有用....

1     List<TmTransportAddressDto> selectByExample(TmTransportAddressExample example);
2 
3     int updateByExampleSelective(@Param("record") TmTransportAddressDto record, @Param("example") TmTransportAddressExample example);
4 
5     int updateByExample(@Param("record") TmTransportAddressDto record, @Param("example") TmTransportAddressExample example);
6 
7     int countByExample(TmTransportAddressExample example);
8 
9     int deleteByExample(TmTransportAddressExample example);
View Code

就是這幾個example方法.

看一個使用example的小例子:

1             TmTransportAddressDto tmTransportAddressDto = new TmTransportAddressDto();
2             tmTransportAddressDto.setExecutePerson(tmTransportChangeRecord.getDriverNameAfter());
3             tmTransportAddressDto.setExecuteDeviceNo(tmTransportChangeRecord.getPlateNumberAfter());
4             tmTransportAddressDto.setExecuteTelephone(tmTransportChangeRecord.getDriverPhoneAfter());
5             TmTransportAddressExample tmTransportAddressExample = new TmTransportAddressExample();
6             tmTransportAddressExample.createCriteria()
7                     .andExecuteTelephoneEqualTo(tmTransportChangeRecord.getDriverPhoneBefore()).andSnEqualTo(sn);
8             countUpdate += tmTransportAddressDao.updateByExampleSelective(tmTransportAddressDto,
9                     tmTransportAddressExample);

上面這9行代碼至關因而更新tmTransportAddress表的executePerson,executeDeviceNo等4個字段 where 條件是executeTelphone = XXX and sn = xxx.

這種用法比Spring data還要簡單,連dao的方法名都不用寫了(其實仍是要寫的.只是寫在了example裏...generator自動生成了通用的XML SQL片斷)...很是很是好用!

再不少狀況下只要自動生成了xml文件之後基本SQL和額外的dao方法都不須要寫了..由於example至關因而動態拼接SQL的方法.能夠拼接出任意的SQL.

不過我以爲這種用法仍是不太適合頁面上那種動態條件分頁查詢,由於也須要在service裏拼接條件..只是簡化了一些.並無本身在XML裏寫完整的SQL直觀.

 

小結

以上即是我最近2個月學習mybatis的一些感觸.mybatis在不少狀況下確實是比spring data簡單好用(其實就是拼SQL的功能很強大).

後面會再分享一些若是我是架構師會怎麼在項目裏使用mybatis的一些想法

相關文章
相關標籤/搜索