mybatis入門-mapper代理原理

來源:互聯網
上載者:User

標籤:style   dao層   代碼   分享   地址   資源   sql   rtu   href   

  原始dao層開發

    在我們用mybatis開發了第一個小程式後,相信大家對於dao層的開發其實已經有了一個大概的思路了。其他的配置不用變,將原來的test方法,該為dao的方法,將原來的傳回值,直接在dao層進行一下接收就可以了。依然是老一套,先是大架構,然後寫設定檔及UserMapper.xml檔案這一系列的操作。如果不明白的,請參考本人部落格《入門第一個程式》。

    我們需要做的就是,首先建立一個會話工廠(SqlSessionFactory),然後用會話工廠建立會話(SqlSession)。然後通過讀取設定檔得到sql語句,執行,然後返回資料給dao層的對象。具體操作如下

    首先,在原來的基礎上建立一個dao層的介面。

    

    然後寫一個dao層介面的實作類別

 1 public class UserDaoImpl implements UserDao { 2   3 // 需要向dao實作類別中注入SqlSessionFactory 4 // 這裡通過構造方法注入 5 private SqlSessionFactory sqlSessionFactory; 6   7 public UserDaoImpl(SqlSessionFactory sqlSessionFactory) { 8 this.sqlSessionFactory = sqlSessionFactory; 9 }10  11 @Override12 public User findUserById(int id) throws Exception {13 SqlSession sqlSession = sqlSessionFactory.openSession();14  15 User user = sqlSession.selectOne("test.findUserById", id);16  17 // 釋放資源18 sqlSession.close();19  20 return user;21  22 }23  24 @Override25 public void insertUser(User user) throws Exception {26 SqlSession sqlSession = sqlSessionFactory.openSession();27  28 //執行插入操作29 sqlSession.insert("test.insertUser", user);30  31 // 提交事務32 sqlSession.commit();33  34 // 釋放資源35 sqlSession.close();36  37 }38  39 @Override40 public void deleteUser(int id) throws Exception {41 SqlSession sqlSession = sqlSessionFactory.openSession();42  43 //執行插入操作44 sqlSession.delete("test.deleteUser", id);45  46 // 提交事務47 sqlSession.commit();48  49 // 釋放資源50 sqlSession.close();51  52 }53  54 }

然後就是對我們寫的代碼的測試

    這樣開發的話有一些問題:

    1.dao介面的實作類別中存在大量的重複代碼,這些代碼會增加程式員的工作量。

    2.在實作類別中,SqlSession的方法在調用對應檔中的sql語句時將statement的id(其中的"test.findUserById"便是statment的id)寫入程式碼了。

    

    3.調用SqlSession方法時傳入的變數,由於sqlsession方法使用泛型,即使變數類型傳入的不是Dao方法中的參數類型,在編譯的時候也不會報錯,不利於程式的開發。

    

    為瞭解決這些問題,我們通過滿足一些規範就將實體層的實作類別的開發省去,由mybatis架構提供的代理實作類別替我們去動態調用我們的對應檔,然後去執行類中的方法。

  mapper代理方法的原理

    這之前,先聲明一下,使用mapper代理的時候,命名和之前的不太一樣。這裡的介面命名由原來的** 改為**Mapper,比如說原來的User介面,現改為UserMapper。其內容和本質沒有變,只是換了一個命名規範。除了介面外對應檔也是由User.xml改為UserMapper.xml其內容不變。

    mapper代理方法的思路是,程式員接著寫持久層的介面。

    

 

    和對應每個介面的設定檔。

    

   在我們的原來的方法中需要再寫一個介面的實作類別,用來構建會話工廠(SqlSessionFactory)和對應的會話(SqlSession)然後通過會話去讀取對應檔中的sql語句(這裡不準確,不過可以這麼理解)。那麼我麼就可以在這個實體類上做點文章了:

    1.我們可以建立一個代理類,在我們相應的介面被調用的時候,代理類就會建立這個對象,建立會話工廠和會話並不難。

    2.還有就是我們的sqlSession對象調用的方法名稱,這個很好理解,對應的是我們對應檔的標籤。

    3.那麼接下來就是傳入參數和接收傳回值的問題了:

    3.1 傳入參數:我們總共需要傳入兩個參數,一個是對應檔的statement的id的字串,另外一個是執行需要的參數。 比較困難的是,這個字串的產生問題。我們的每個方法到底對應的是哪個對應檔的statement的id。對於這個問題,mybatis給出了我們的解決方案:我們的實體層對象讀到的字串是這樣的:test.insertUser

    可以將這個id分為兩部分,其中的test是我們的對應檔中的namespace的值,這個值讓它和持久層介面的地址一致,這樣就使得代理對象可以通過介面的地址動態產生id的前半部分,也就是test的這一部分;而後半部分則是讓對應檔中的Statement的id和介面的方法一致。

    也就是說,使用者在調用介面的某一個方法的時候,mybatis可以根據介面地址和對應的方法名產生sqlsession對象的方法傳入的字串。這樣就解決了傳入參數中的字串的問題了。

    還有就是第二個問題:我們的傳入具體參數,mybatis規定,傳入參數類型必須和介面的傳入參數類型一致。這樣,我們的傳入參數類型就搞定了。

    3.2傳入參數搞定了以後,傳回值也就搞定了,跟傳入參數的規定一樣,傳回值的類型要求和介面傳回值一致,這樣就可以在代理類中將傳回值傳出了。

    這些搞定了,我們就可以使用代理對象代替我們的實體層具體實作類別了。

    至此,這些問題就差不多都解決了,不過還有一個問題:我們的select方法傳回值問題,代理對象到底是用selectont方法去查詢資料庫呢還是使用selectlist方法呢?這個跟我們的介面(mapper)的傳回值類型有關——如果mapper方法返回單個pojo對象(非集合對象),代理對象內部通過selectOne查詢資料庫;如果mapper方法返回集合對象,代理對象內部通過selectList查詢資料庫。

  mapper代理方法

    原理講完了,使用其實就基本上沒啥要說的了。

    首先我們要建立一個介面。

    

    然後寫對應介面的xml檔案(截取部分,namespace處就不了)。

     

    最後別忘了在SqlMapConfig.xml檔案中載入UserMapper.xml。

    

    測試,這裡有必要說一下,我們的代理對象是通過SqlSession.getMapper(介面位元組碼檔案)擷取的。:

    

    至此,我們的mybatis的實體層的實體層實作類別就可以省略不寫了。不過這樣做的壞處是加強了代碼的耦合性,每個介面和每個對應檔必須對應。不過還是感覺通過遵守一定的規範而使得代碼量大大減少更爽呢。

mybatis入門-mapper代理原理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.