对于从事 Java EE 的开发人员来讲,iBatis 是一个再熟悉不过的持久层框架了,在 Hibernate、JPA 这样的一站式对象 / 关系映射(O/R Mapping)解决方案盛行以前,iBaits 基本是持久层框架的不二选择。即便在持久层框架层出不穷的今天,iBatis 凭借着易学易用、轻巧灵活等特色,也仍然拥有一席之地。尤为对于擅长 SQL 的开发人员来讲,iBatis 对 SQL 和存储过程的直接支持可以让他们在得到 iBatis 封装优点的同时而不丧失 SQL 调优的手段,这是 Hibernate/JPA 所没法比拟的。具体而言,使用 iBatis 框架的主要优点主要体如今以下几个方面:html
首先,iBatis 封装了绝大多数的 JDBC 样板代码,使得开发者只需关注 SQL 自己,而不须要花费精力去处理例如注册驱动,建立 Connection,以及确保关闭 Connection 这样繁杂的代码。面试
其次,iBatis 能够算是在全部主流的持久层框架中学习成本最低,最容易上手和掌握的框架。虽然说其余持久层框架也号称门槛低,容易上手,可是等到你真正使用时会发现,要想掌握并用好它是一件很是困难的事。在工做中我须要常常参与面试,我曾听到过不少位应聘者描述,他们所在的项目在技术选型时选择 Hibernate,后来发现难以驾驭,不得不将代码用 JDBC 或者 iBatis 改写。sql
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。数据库
从 iBatis 到 MyBatis,不仅是名称上的变化,MyBatis 提供了更为强大的功能,同时并无损失其易用性,相反,在不少地方都借助于 JDK 的泛型和注解特性进行了简化。iBatis 确实该退休了,由于一个更为出色的继任者通过 10 个 Beta 版本的蜕变已然出如今咱们的面前。apache
本文将主要针对 MyBatis 和 iBatis 的变化之处进行讨论,以便于读者顺利从 iBatis 向 MyBatis 过渡。mybatis
回页首app
若是读者接触过一些经常使用的 Java EE 框架,应该都知道这些框架须要提供一个全局配置文件,用于指定程序正常运行所需的设置和参数信息。而针对经常使用的持久层框架而言(Hibernate、JPA、iBatis 等),则一般须要配置两类文件:一类用于指定数据源、事务属性以及其余一些参数配置信息(一般是一个独立的文件,能够称之为全局配置文件);另外一类则用于指定数据库表和程序之间的映射信息(可能不止一个文件,咱们称之为映射文件)。MyBatis 也不例外,虽然其中的一部分能够经过注解的形式进行,可是这两部份内容自己还是必不可少的。ide
根据 iBatis 的习惯,咱们一般把全局配置文件命名为 sqlMapConfig.xml,文件名自己并无要求,在 MyBatis 中,也常常会将该文件命名为 Configuration.xml (读彻底文后读者也许会发现,在 iBatis 中常常出现的 “sqlMap” 在 MyBatis 中被逐渐淡化了,除了此处,还好比 iBatis 配置文件的根元素为 <sqlMapConfig>,指定映射文件的元素为 <sqlMap>,以及 SqlMapClient 等等,这个变化正说明,iBatis 仅是以 SQL 映射为核心的框架,而在 MyBatis 中多以 Mapper、Session、Configuration 等其余经常使用 ORM 框架中的名字代替,体现的无非是两个方面:首先是为了减小开发者在切换框架所带来的学习成本;其次,MyBatis 充分吸取了其余 ORM 框架好的实践,MyBatis 如今已不只仅是一个 SQL 映射框架了)。在全局配置文件中能够配置的信息主要包括以下几个方面:工具
上面说起的大多数元素都不是必需的,一般 MyBatis 会为没有显式设置的元素提供缺省值。一个简单的全局配置文件示例以下:
<?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 提供的一个工具类,它用于简化资源文件的加载,它能够访问各类路径的文件,不过最经常使用的仍是示例中这种基于类路径的表示方式。若是读者对 Hibernate 有所了解,必定会发现 MyBatis 不管是使用风格仍是类名都和 Hibernate 很是相像,笔者曾今屡次在国内外 Java 社区看到有人说 MyBatis 在向 Hibernate/JPA 靠拢。暂且不论这是否属实,持久化技术在通过一番蓬勃的竞争和发展,最终在社区造成统一的认识并被普遍接受,这对开发者而言未必不是一件好事,MyBatis 在这一点上只是向事实上的标准靠近了一步。
在完成全局配置文件,并经过 MyBatis 得到 SqlSession 对象以后,即可以执行数据访问操做了。对于 iBatis/MyBatis 而言,要执行的操做其实就是在映射文件中配置的 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 的方式以下:
try { UserInfo userinfo = (UserInfo) sqlSession.selectOne ("mybatis.demo.UserInfoMapper.getUser", 2); System.out.println(userinfo); } finally { sqlSession.close(); } |
须要注意的是,SqlSession 的使用必需遵照上面的格式,即在 finally 块中将其关闭。以保证资源获得释放,防止出现内存泄露!
以上就是一个简单而完整的 MyBatis 程序。其中涉及了全局配置文件,映射文件,构建 SqlSession 对象,执行数据访问操做等四个步骤。下面将针对除构建 SqlSession 对象以外的三块内容进行分解。
MyBatis 全局配置文件的各主要元素基本和 iBatis 相同,只是在用法和个别名称上作了调整。元素的意义就再也不描述,下面主要讲述针对 iBatis 和 MyBatis 配置文件的主要区别之处。
首先,两个版本的 DTD 约束不一样,MyBatis 的 DTD 文件已经包含在发布包下的 mybatis-3.0.x.jar 包中。这直接影响到的是,iBatis 配置文件的根元素是 <sqlMapConfig>,而 MyBatis 使用的是 <configuration>。
其次,<settings> 的用法发生了改变,以前的格式为:
<settings props1="value1" props2="value2"… /> |
要设置的属性直接以键值对的形式做为 <settings> 的属性。而在 MyBatis 中调整为略显复杂但却更有条理的方式:
<settings> <setting name="props1" value="value1"/> <setting name="props2" value="value2"/> …… </settings> |
另外,以前配置事务管理器和数据源的方式以下:
<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> 来进行数据源管理,主要是为了简化在多套数据源配置之间的切换,好比开发和发布使用不一样的配置。
最后,在 iBatis 中指定映射文件的方式以下:
<sqlMap resource=... /> <sqlMap resource=... /> <sqlMap resource=... /> |
在 MyBatis 中调整为以下方式:
<mappers> <mapper resource=... /> <mapper resource=... /> </mappers> |
上面的这些调整,主要出发点其实并非使得 MyBatis 功能更为强大,而是使配置更为合理,让开发者更容易阅读和理解。
到目前为止,咱们主要讨论了 XML 形式的全局配置,其实这也不是惟一选择,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 语句。一个典型的接口定义以及对应的数据访问方法以下:
// 映射 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 针对映射文件进行格式调整的地方不少,但大部分仅仅只是名称上的变化,现代的 IDE 都支持联想功能,能够很方便的获取到当前位置能够有哪些元素、哪些属性等。因此这基本不会给开发者形成什么麻烦。
针对映射文件,首先是一系列的属性名称的改变,这些仅仅是名称的改变,用法和含义并无发生变化:
iBatis/MyBatis 对存储过程的支持一直是值得称道的。以前经过使用 <procedure> 元素进行存储过程的定义,示例以下:
<procedure id="getValues" parameterMap="getValuesPM"> { ? = call pkgExample.getValues(p_id => ?) } </procedure> |
在 MyBatis 中,<proccedure> 元素已经被移除,经过 <select>、<insert> 和 <update> 进行定义:
<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 文档。
原文出自:http://www.ibm.com/developerworks/cn/opensource/os-cn-mybatis/index.html
转载请注明出处.珍惜他人的劳动成果.