iBatis 到 MyBatis區別

簡介: 本文主要講述了 iBatis 2.x 和 MyBatis 3.0.x 的區別,以及從 iBatis 向 MyBatis 移植時須要注意的地方。經過對本文的學習,讀者基本可以瞭解 MyBatis 有哪些方面的改進,並可以順利使用 MyBatis 進行開發。本文更適合有 iBatis 基礎的開發人員閱讀。java


從 iBatis 到 MyBatis,你準備好了嗎?面試

對於從事 Java EE 的開發人員來講,iBatis 是一個再熟悉不過的持久層框架了,在 Hibernate、JPA 這樣的一站式對象 / 關係映射(O/R Mapping)解決方案盛行以前,iBaits 基本是持久層框架的不二選擇。即便在持久層框架層出不窮的今天,iBatis 憑藉着易學易用、輕巧靈活等特色,也仍然擁有一席之地。尤爲對於擅長 SQL 的開發人員來講,iBatis 對 SQL 和存儲過程的直接支持可以讓他們在得到 iBatis 封裝優點的同時而不喪失 SQL 調優的手段,這是 Hibernate/JPA 所沒法比擬的。具體而言,使用 iBatis 框架的主要優點主要體如今以下幾個方面:sql

首先,iBatis 封裝了絕大多數的 JDBC 樣板代碼,使得開發者只需關注 SQL 自己,而不須要花費精力去處理例如註冊驅動,建立 Connection,以及確保關閉 Connection 這樣繁雜的代碼。數據庫

其次,iBatis 能夠算是在全部主流的持久層框架中學習成本最低,最容易上手和掌握的框架。雖然說其餘持久層框架也號稱門檻低,容易上手,可是等到你真正使用時會發現,要想掌握並用好它是一件很是困難的事。在工做中我須要常常參與面試,我曾聽到過不少位應聘者描述,他們所在的項目在技術選型時選擇 Hibernate,後來發現難以駕馭,不得不將代碼用 JDBC 或者 iBatis 改寫。apache

iBatis 自從在 Apache 軟件基金會網站上發佈至今,和他的明星兄弟們(Http Server,Tomcat,Struts,Maven,Ant 等等)一塊兒接受者萬千 Java 開發者的敬仰。然而在今年六月中旬,幾乎是發佈 3.0 版本的同時,iBatis 主頁上的一則 「Apache iBATIS has been retired」 的聲明在社區引發了一陣不小的波瀾。在 Apache 寄居六年以後,iBatis 將代碼託管到 Google Code。在聲明中給出的主要理由是,和 Apache 相比,Google Code 更有利於開發者的協同工做,也更能適應快速發佈。於此同時,iBatis 改名爲 MyBatis。mybatis

從 iBatis 到 MyBatis,不僅是名稱上的變化,MyBatis 提供了更爲強大的功能,同時並無損失其易用性,相反,在不少地方都藉助於 JDK 的泛型和註解特性進行了簡化。iBatis 確實該退休了,由於一個更爲出色的繼任者通過 10 個 Beta 版本的蛻變已然出如今咱們的面前。app

本文將主要針對 MyBatis 和 iBatis 的變化之處進行討論,以便於讀者順利從 iBatis 向 MyBatis 過渡。框架

由一個 MyBatis 示例開始ide

若是讀者接觸過一些經常使用的 Java EE 框架,應該都知道這些框架須要提供一個全局配置文件,用於指定程序正常運行所需的設置和參數信息。而針對經常使用的持久層框架而言(Hibernate、JPA、iBatis 等),則一般須要配置兩類文件:一類用於指定數據源、事務屬性以及其餘一些參數配置信息(一般是一個獨立的文件,能夠稱之爲全局配置文件);另外一類則用於指定數據庫表和程序之間的映射信息(可能不止一個文件,咱們稱之爲映射文件)。MyBatis 也不例外,雖然其中的一部分能夠經過註解的形式進行,可是這兩部份內容自己還是必不可少的。工具

根據 iBatis 的習慣,咱們一般把全局配置文件命名爲 sqlMapConfig.xml,文件名自己並無要求,在 MyBatis 中,也常常會將該文件命名爲 Configuration.xml (讀徹底文後讀者也許會發現,在 iBatis 中常常出現的 「sqlMap」 在 MyBatis 中被逐漸淡化了,除了此處,還好比 iBatis 配置文件的根元素爲 <sqlMapConfig>,指定映射文件的元素爲 <sqlMap>,以及 SqlMapClient 等等,這個變化正說明,iBatis 僅是以 SQL 映射爲核心的框架,而在 MyBatis 中多以 Mapper、Session、Configuration 等其餘經常使用 ORM 框架中的名字代替,體現的無非是兩個方面:首先是爲了減小開發者在切換框架所帶來的學習成本;其次,MyBatis 充分吸取了其餘 ORM 框架好的實踐,MyBatis 如今已不只僅是一個 SQL 映射框架了)。在全局配置文件中能夠配置的信息主要包括以下幾個方面:

  • properties --- 用於提供一系列的鍵值對組成的屬性信息,該屬性信息能夠用於整個配置文件中。

  • settings --- 用於設置 MyBatis 的運行時方式,好比是否啓用延遲加載等。

  • typeAliases --- 爲 Java 類型指定別名,能夠在 XML 文件中用別名取代 Java 類的全限定名。

  • typeHandlers --- 在 MyBatis 經過 PreparedStatement 爲佔位符設置值,或者從 ResultSet 取出值時,特定類型的類型處理器會被執行。

  • objectFactory --- MyBatis 經過 ObjectFactory 來建立結果對象。能夠經過繼承 DefaultObjectFactory 來實現本身的 ObjectFactory 類。

  • plugins --- 用於配置一系列攔截器,用於攔截映射 SQL 語句的執行。能夠經過實現 Interceptor 接口來實現本身的攔截器。

  • environments --- 用於配置數據源信息,包括鏈接池、事務屬性等。

  • mappers --- 程序中全部用到的 SQL 映射文件都在這裏列出,這些映射 SQL 都被 MyBatis 管理。

上面說起的大多數元素都不是必需的,一般 MyBatis 會爲沒有顯式設置的元素提供缺省值。一個簡單的全局配置文件示例以下:


清單 1. 簡單的全局配置文件示例

<?xml version="1.0" encoding="UTF-8" ?>
 <!--iBatis 和 MyBatis 的全局配置文件使用不一樣的 DTD 約束,在將應用由
 iBatis 升級至 MyBatis 時須要注意(二者的映射文件 DTD 約束也不相同)-->
 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
 <configuration>
 <!-- 配置數據源相關的信息 -->
 <environments default="demo">
 <environment id="demo">
 <transactionManager type="JDBC"/>
 <dataSource type="POOLED">
 <property name="driver" value= … />
 <property name="url" value= … />
 <property name="username" value="root"/>
 <property name="password" value="root"/>
 </dataSource>
 </environment>
 </environments>
 <!-- 列出映射文件 -->
 <mappers>
 <mapper resource="footmark/mybatis/demo/UserInfoMapper.xml"/>
 </mappers>
 </configuration>


有了這些信息,MyBatis 便可以和數據庫創建鏈接,並應用給定的鏈接池信息和事務屬性。MyBatis 封裝了這些操做,最終暴露一個 SqlSessionFactory 實例供開發者使用,從名字能夠看出來,這是一個建立 SqlSession 的工廠類,經過 SqlSession 實例,開發者可以直接進行業務邏輯的操做,而不須要重複編寫 JDBC 相關的樣板代碼。根據全局配置文件生成 SqlSession 的代碼以下:

Reader reader = Resources.getResourceAsReader("Configuration.xml");
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = sqlSessionFactory.openSession();

在完成全局配置文件,並經過 MyBatis 得到 SqlSession 對象以後,即可以執行數據訪問操做了。對於 iBatis/MyBatis 而言,要執行的操做其實就是在映射文件中配置的 SQL 語句。二者的配置基本相同,以下所示:能夠把上面的三行代碼看作是 MyBatis 建立 SqlSession 的樣板代碼。其中第一行代碼在類路徑上加載配置文件,Resources 是 MyBatis 提供的一個工具類,它用於簡化資源文件的加載,它能夠訪問各類路徑的文件,不過最經常使用的仍是示例中這種基於類路徑的表示方式。若是讀者對 Hibernate 有所瞭解,必定會發現 MyBatis 不管是使用風格仍是類名都和 Hibernate 很是相像,筆者曾今屢次在國內外 Java 社區看到有人說 MyBatis 在向 Hibernate/JPA 靠攏。暫且不論這是否屬實,持久化技術在通過一番蓬勃的競爭和發展,最終在社區造成統一的認識並被普遍接受,這對開發者而言未必不是一件好事,MyBatis 在這一點上只是向事實上的標準靠近了一步。


清單 2. 在映射文件中配置 SQL 語句

<?xml version="1.0" encoding="UTF-8" ?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="mybatis.demo.UserInfoMapper">
 <select id="selectUser" parameterType="int"
 resultType="mybatis.demo.UserInfo">
 select * from UserInfo where userid =#{userid}
 </select>
 </mapper>

在 iBatis 中,namespace 不是必需的,且它的存在沒有實際的意義。在 MyBatis 中,namespace 終於派上用場了,它使得映射文件與接口綁定變得很是天然。關於接口綁定,後面會有篇幅專門描述。使用 SqlSession 執行 SQL 的方式以下:


清單 3. 使用 SqlSession 執行映射文件中配置的 SQL 語句

try
{
UserInfo userinfo = (UserInfo) sqlSession.selectOne
("mybatis.demo.UserInfoMapper.getUser", 2);
System.out.println(userinfo);
} finally
{
sqlSession.close();
}

須要注意的是,SqlSession 的使用必需遵照上面的格式,即在 finally 塊中將其關閉。以保證資源獲得釋放,防止出現內存泄露!

以上就是一個簡單而完整的 MyBatis 程序。其中涉及了全局配置文件,映射文件,構建 SqlSession 對象,執行數據訪問操做等四個步驟。下面將針對除構建 SqlSession 對象以外的三塊內容進行分解。

MyBatis 全局配置文件的改變

MyBatis 全局配置文件的各主要元素基本和 iBatis 相同,只是在用法和個別名稱上作了調整。元素的意義就再也不描述,下面主要講述針對 iBatis 和 MyBatis 配置文件的主要區別之處。

首先,兩個版本的 DTD 約束不一樣,MyBatis 的 DTD 文件已經包含在發佈包下的 mybatis-3.0.x.jar 包中。這直接影響到的是,iBatis 配置文件的根元素是 <sqlMapConfig>,而 MyBatis 使用的是 <configuration>。

其次,<settings> 的用法發生了改變,以前的格式爲:


清單 4. 在 iBatis 中設置屬性的方式

 <settings props1="value1" props2="value2"… /> 


要設置的屬性直接以鍵值對的形式做爲 <settings> 的屬性。而在 MyBatis 中調整爲略顯複雜但卻更有條理的方式:


清單 5. 在 MyBatis 中設置屬性的方式

 <settings>  <setting name="props1" value="value1"/>  <setting name="props2" value="value2"/> …… </settings> 


另外,以前配置事務管理器和數據源的方式以下:


清單 6. 在 iBatis 中配置事務管理器和數據源的方式

 <transactionManager type="JDBC" >  <dataSource type="SIMPLE">  <property name="JDBC.Driver" value="${driver}"/>  <!-- 其餘數據源信息省略 -->  </dataSource>  </transactionManager> 


在 MyBatis 中調整爲以下的方式:


清單 7. 在 MyBatis 中配置事務管理器和數據源的方式

 <environments default="demo">  <environment id="demo">  <transactionManager type="JDBC"/>  <dataSource type="POOLED">  <property name="JDBC.Driver" value="${driver}"/>  <!-- 其餘數據源信息省略 -->  </dataSource>  </environment>  </environments> 


經過 <environments> 來進行數據源管理,主要是爲了簡化在多套數據源配置之間的切換,好比開發和發佈使用不一樣的配置。

最後,在 iBatis 中指定映射文件的方式以下:


清單 8. 在 iBatis 中指定映射文件的方式

 <sqlMap resource=... />  <sqlMap resource=... />  <sqlMap resource=... /> 


在 MyBatis 中調整爲以下方式:


清單 9. 在 MyBatis 中指定映射文件的方式

 <mappers>  <mapper resource=... />  <mapper resource=... />  </mappers> 


上面的這些調整,主要出發點其實並非使得 MyBatis 功能更爲強大,而是使配置更爲合理,讓開發者更容易閱讀和理解。

到目前爲止,咱們主要討論了 XML 形式的全局配置,其實這也不是惟一選擇,MyBatis 還提供了經過代碼來進行配置的方式:


清單 10. 在 MyBatis 中使用代碼進行配置

 DataSource ds = …… // 獲取一個 DataSource  TransactionFactory txFactory = new JdbcTransactionFactory();  Environment env = new Environment("demo", txFactory, ds);  Configuration cfg = new Configuration(env);  cfg.addMapper(UserInfoMapper.class);  SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(cfg); 


結合前面的配置文件,很容易理解這段代碼的意思,故再也不贅述。不過,須要注意的是 Configuration 的 addMapper() 方法,該方法的參數一般是一個接口,能夠在接口裏面定義若干方法,在方法上使用註解來指定映射的 SQL 語句。一個典型的接口定義以及對應的數據訪問方法以下:


清單 11. 將映射的 SQL 語句與接口中的方法綁定

 // 映射 SQL 綁定接口 public interface UserInfoMapper  {  @Select("select * from userinfo where userid = #{userid}")  public UserInfo getUserInfo(int userid);  }  // 接口綁定對應的數據訪問方法 try  {  //UserInfo userinfo = (UserInfo) sqlSession.selectOne  ("mybatis.demo.UserInfoMapper.selectUser", 2);  UserInfoMapper userinfoMapper =  sqlSession.getMapper(UserInfoMapper.class);  UserInfo userinfo = userinfoMapper.getUserInfo(1);  System.out.println(userinfo);  } finally  {  sqlSession.close();  } 


MyBatis 映射文件的改變

MyBatis 針對映射文件進行格式調整的地方不少,但大部分僅僅只是名稱上的變化,現代的 IDE 都支持聯想功能,能夠很方便的獲取到當前位置能夠有哪些元素、哪些屬性等。因此這基本不會給開發者形成什麼麻煩。

針對映射文件,首先是一系列的屬性名稱的改變,這些僅僅是名稱的改變,用法和含義並無發生變化:

  • 和全局配置文件同樣,因爲 DTD 約束髮生變化,根元素也由原來的 <sqlMap> 調整爲 <mapper>。

  • <select> 等元素的 parameterClass 屬性改成了 parameterType 屬性。

  • <select> 等元素的 resultClasss 屬性改成了 resultType 屬性。

  • <parameterMap> 等元素的 class 屬性改成了 type 屬性。

  • <result> 元素的 columnIndex 屬性被移除了。

  • 嵌套參數由 #value# 改成了 #{value}。

  • <parameter> 等元素的 jdbcType 屬性取值中,原來的 "ORACLECURSOR" 取值改成了如今的 "CURSOR","NUMBER" 取值改成了 "NUMERIC"。

iBatis/MyBatis 對存儲過程的支持一直是值得稱道的。以前經過使用 <procedure> 元素進行存儲過程的定義,示例以下:


清單 12. iBatis 中調用存儲過程的方式

 <procedure id="getValues" parameterMap="getValuesPM">     { ? = call pkgExample.getValues(p_id => ?) }  </procedure> 


在 MyBatis 中,<proccedure> 元素已經被移除,經過 <select>、<insert> 和 <update> 進行定義:


清單 13. MyBatis 中調用存儲過程的方式

 <select id="getValues" parameterMap="getValuesPM" statementType="CALLABLE">     { ? = call pkgExample.getValues(p_id => ?)}  </select> 


如上所示,經過 statementType 屬性將該語句標識爲存儲過程而非普通 SQL 語句。

代碼層面的改變

經過前面的示例能夠看出,MyBatis 在編碼中的最大的改變就是將一個最經常使用的 API 由 SqlMapClient 改成了 SqlSessionFactory。另外,類型處理器接口也由原來的 TypeHandlerCallback 改成了 TypeHandler。最後 DataSourceFactory 也進行了調整,移動到 org.apache.ibatis.datasource 包下,其中的方法也做了微調。總之,代碼層面公開的部分改動較少,不會給開發者形成較大的移植成本。

總結

本文主要描述了從 iBatis 向 MyBatis 移植過程當中可能遇到的問題,大部分的變化已經體如今上文中,若是但願從頭開始學習 MyBatis,則建議從頭開始閱讀官方的 user guide 文檔。

相關文章
相關標籤/搜索