天天看點

Mybatis筆記三:iBatis與MyBatis差別

轉載:http://www.tuicool.com/articles/auaAru

iBatis 架構的主要優勢:

1、iBatis 封裝了絕大多數的 JDBC 樣闆代碼,使得開發者隻需關注 SQL 本身,而不需要花費精力去處理例如注冊驅動,建立 Connection,以及確定關閉 Connection 這樣繁雜的代碼。

2、從 iBatis 到 MyBatis,不隻是名稱上的變化,MyBatis 提供了更為強大的功能,同時并沒有損失其易用性,相反,在很多地方都借助于 JDK 的泛型和注解特性進行了簡化

常用的 Java EE 架構,應該都知道這些架構需要提供一個全局配置檔案,用于指定程式正常運作所需的設定和參數資訊。而針對常用的持久層架構而言(Hibernate、JPA、iBatis 等),則通常需要配置兩類檔案:

一類用于指定資料源、事務屬性以及其他一些參數配置資訊(通常是一個獨立的檔案,可以稱之為全局配置檔案);

另一類則用于指定資料庫表和程式之間的映射資訊(可能不止一個檔案,我們稱之為映射檔案)。

MyBatis 也不例外,雖然其中的一部分可以通過注解的形式進行,但是這兩部分内容本身仍是必不可少的

MyBatis 全局配置檔案中可以配置的資訊主要包括如下幾個方面:

    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 會為沒有顯式設定的元素提供預設值。

 iBatis 2.x 和 MyBatis 3.0.x 的差別

1、 全局配置檔案命名

iBatis 通常把為 sqlMapConfig.xml,檔案名本身并沒有要求,在 MyBatis 中經常會将該檔案命名為 Configuration.xml

2、 全局配置檔案

<?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 的樣闆代碼。

其中第一行代碼在類路徑上加載配置檔案,Resources 是 MyBatis 提供的一個工具類,它用于簡化資源檔案的加載,它可以通路各種路徑的檔案,不過最常用的還是示例中這種基于類路徑的表示方式

在完成全局配置檔案,并通過 MyBatis 獲得 SqlSession 對象之後,便可以執行資料通路操作了

— 設定屬性的差別

iBatis :<settings props1=”value1″ props2=”value2″… />

MyBatis :<settings> <setting name=”props1″ value=”value1″/> <setting name=”props2″ value=”value2″/> …… </settings>

—配置事務管理器和資料源的差別

iBatis :

<transactionManager type=”JDBC” >

<dataSource type=”SIMPLE”>

<property name=”JDBC.Driver” value=”${driver}”/>

</dataSource>

</transactionManager>

MyBatis :

<environments default=”demo”>

<environment id=”demo”>

<transactionManager type=”JDBC”/>

<dataSource type=”POOLED”>

<property name=”JDBC.Driver” value=”${driver}”/>

</dataSource>

</environment>

</environments>

通過 <environments> 來進行資料源管理,主要是為了簡化在多套資料源配置之間的切換,比如開發和釋出使用不同的配置。

3、 在映射檔案中配置 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 終于派上用場了,它使得映射檔案與接口綁定變得非常自然

—指定映射檔案的方式的差別

iBatis:<sqlMap resource=… /> <sqlMap resource=… /> <sqlMap resource=… />

MyBatis :<mappers> <mapper resource=… /> <mapper resource=… /> </mappers>

4、 使用 SqlSession 執行映射檔案中配置的 SQL 語句

try {

UserInfo userinfo = (UserInfo) sqlSession.selectOne (“mybatis.demo.UserInfoMapper.getUser”, 2);

System.out.println(userinfo);

} finally {

sqlSession.close();

}

需要注意的是,SqlSession 的使用必需遵守上面的格式,即在 finally 塊中将其關閉。以保證資源得到釋放,防止出現記憶體洩露!

5、 在 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 語句。一個典型的接口定義以及對應的資料通路方法如下:

6、 将映射的 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();

}

7、 MyBatis 映射檔案的改變 (僅僅是名稱的改變,用法和含義并沒有發生變化)

    和全局配置檔案一樣,由于 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> 元素進行存儲過程的定義,示例如下:

— 存儲過程的差別

iBatis:

<procedure id=”getValues” parameterMap=”getValuesPM”>

{ ? = call pkgExample.getValues(p_id => ?) }

</procedure>

MyBatis :

<select id=”getValues” parameterMap=”getValuesPM” statementType=”CALLABLE”>

{ ? = call pkgExample.getValues(p_id => ?)}

</select>

通過 statementType 屬性将該語句辨別為存儲過程而非普通 SQL 語句

 8、代碼層面的改變

MyBatis 在編碼中的最大的改變就是将一個最常用的 API 由 SqlMapClient 改為了 SqlSessionFactory。

另外,類型處理器接口也由原來的 TypeHandlerCallback 改為了 TypeHandler。

最後 DataSourceFactory 也進行了調整,移動到 org.apache.ibatis.datasource 包下,其中的方法也作了微調。總之,代碼層面公開的部分改動較少,不會給開發者造成較大的移植成本