当前位置: 首页 > 工具软件 > iBATIS > 使用案例 >

iBatis详解以及和MyBatis区别

邬阳
2023-12-01

1 ibatis

1.1 ibatis基础

1.1.1 ibatis过渡为mybatis

对于从事Java EE的开发人员来说,iBatis 是一个再熟悉不过的持久层框架了,iBatis 可以算是在所有主流的持久层框架中学习成本最低,最容易上手和掌握的框架。虽说其他持久层框架也号称门槛低,容易上手,但是等到你真正使用时会发现,要想掌握并用好它是一件非常困难的事。
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

iBatisMyBatis,不只是名称上的变化,MyBatis提供了更为强大的功能,同时并没有损失其易用性,相反,在很多地方都借助于JDK的泛型和注解特性进行了简化。iBatis 确实该退休了,因为一个更为出色的继任者经过 10Beta 版本的蜕变已然出现在我们的面前。

1.2 区别

1.2.1 ibatis和mybatis区别

如果接触过一些常用的Java EE框架,应该都知道这些框架需要提供一个全局配置文件,用于指定程序正常运行所需的设置和参数信息。而针对常用的持久层框架而言(HibernateJPAiBatis 等),则通常需要配置两类文件:一类用于指定数据源、事务属性以及其他一些参数配置信息(通常是一个独立的文件,可以称之为全局配置文件);另一类则用于指定数据库表和程序之间的映射信息(可能不止一个文件,称之为映射文件)。MyBatis也不例外,虽然其中的一部分可以通过注解的形式进行,但是这两部分内容本身仍是必不可少的。

根据iBatis的习惯,我们通常把全局配置文件命名为 sqlMapConfig.xml,文件名本身并没有要求,在 MyBatis中,也经常会将该文件命名为 Configuration.xml(读完全文后也许会发现,在iBatis中经常出现的sqlMapMyBatis中被逐渐淡化了,除了此处,还比如iBatis配置文件的根元素为 <sqlMapConfig>,指定映射文件的元素为 <sqlMap>,以及 SqlMapClient 等等,这个变化正说明,iBatis 仅是以 SQL 映射为核心的框架,而在MyBatis中多以MapperSessionConfiguration等其他常用ORM框架中的名字代替,体现的无非是两个方面:首先是为了减少开发者在切换框架所带来的学习成本;其次,MyBatis 充分吸收了其他ORM框架好的实践,MyBatis现在已不仅仅是一个SQL映射框架了)。
mybatis在全局配置文件中可以配置的信息主要包括如下几个方面:

  • properties — 用于提供一系列的键值对组成的属性信息,该属性信息可以用于整个配置文件中。
  • settings — 用于设置MyBatis的运行时方式,比如是否启用延迟加载等。
  • typeAliases — 为Java类型指定别名,可以在XML文件中用别名取代Java类的全限定名。
  • typeHandlers — 在MyBatis通过PreparedStatement为占位符设置值,或者从ResultSet取出值时,特定类型的类型处理器会被执行
  • objectFactoryMyBatis通过ObjectFactory来创建结果对象。可以通过继承DefaultObjectFactory来实现自己的ObjectFactory类。
  • plugins — 用于配置一系列拦截器,用于拦截映射SQL语句的执行。可以通过实现Interceptor接口来实现自己的拦截器。
  • environments — 用于配置数据源信息,包括连接池、事务属性等。
  • mappers — 程序中所有用到的SQL映射文件都在这里列出,这些映射SQL都被MyBatis管理
    上面提及的大多数元素都不是必需的,通常MyBatis会为没有显式设置的元素提供缺省值。一个简单的全局配置文件示例如下:

1.2.1.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的样板代码。其中第一行代码在类路径上加载配置文件,ResourcesMyBatis提供的一个工具类,它用于简化资源文件的加载,它可以访问各种路径的文件,不过最常用的还是示例中这种基于类路径的表示方式

1.2.1.2 sql语句区别

在完成全局配置文件,并通过MyBatis获得SqlSession对象之后,便可以执行数据访问操作了。对于 iBatis/MyBatis 而言,要执行的操作其实就是在映射文件中配置的 SQL 语句。两者的配置基本相同,如下所示:
在映射文件中配置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 终于派上用场了,它使得映射文件与接口绑定变得非常自然。

1.2.1.3 SqlSession执行区别

使用SqlSession执行映射文件中配置的SQL语句

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

需要注意的是,SqlSession的使用必需遵守上面的格式,即在finally块中将其关闭。以保证资源得到释放,防止出现内存泄露!
以上就是一个简单而完整的MyBatis程序。其中涉及了全局配置文件,映射文件,构建SqlSession对象,执行数据访问操作等四个步骤。下面将针对除构建SqlSession对象之外的三块内容进行分解。
MyBatis全局配置文件的改变
MyBatis全局配置文件的各主要元素基本和iBatis相同,只是在用法和个别名称上做了调整。元素的意义就不再描述,下面主要讲述针对 iBatisMyBatis 配置文件的主要区别之处。

1.2.1.4 属性设置区别

首先,两个版本的 DTD约束不同,MyBatisDTD文件已经包含在发布包下的 mybatis-3.0.x.jar包中。这直接影响到的是,iBatis 配置文件的根元素是 <sqlMapConfig>,而MyBatis使用的是 <configuration>
其次,<settings> 的用法发生了改变,之前的格式为:

  • iBatis中设置属性的方式
<settings props1="value1" props2="value2"… />

要设置的属性直接以键值对的形式作为 <settings>的属性

  • MyBatis中设置属性的方式
 <settings>
    <setting name="props1" value="value1"/>
    <setting name="props2" value="value2"/>
    ……
 </settings>

1.2.1.5 配置事务管理器和数据源区别

  • 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>来进行数据源管理,主要是为了简化在多套数据源配置之间的切换,比如开发和发布使用不同的配置。

1.2.1.6 指定映射文件的方式区别

  • iBatis中指定映射文件的方式
<sqlMap resource=... />
 <sqlMap resource=... />
 <sqlMap resource=... />
  • MyBatis中指定映射文件的方式
<mappers>
    <mapper resource=... />
    <mapper resource=... />
 </mappers>

上面的这些调整,主要出发点其实并不是使得MyBatis功能更为强大,而是使配置更为合理,让开发者更容易阅读和理解。
到目前为止,除了XML形式的全局配置,其实这也不是唯一选择,MyBatis还提供了通过代码来进行配置的方式:

1.2.1.7 代码配置和SQL与方法绑定区别

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);

结合前面的配置文件,很容易理解这段代码的意思,故不再赘述。不过,需要注意的是ConfigurationaddMapper()方法,该方法的参数通常是一个接口,可以在接口里面定义若干方法,在方法上使用注解来指定映射的SQL语句。一个典型的接口定义以及对应的数据访问方法如下:
将映射的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();
 }

1.2.1.8 映射文件区别

MyBatis映射文件的改变
MyBatis针对映射文件进行格式调整的地方很多,但大部分仅仅只是名称上的变化,现代的 IDE 都支持联想功能,可以很方便的获取到当前位置可以有哪些元素、哪些属性等。所以这基本不会给开发者造成什么麻烦。

针对映射文件,首先是一系列的属性名称的改变,这些仅仅是名称的改变,用法和含义并没有发生变化:

  • 和全局配置文件一样,由于DTD约束发生变化,根元素也由iBatis原来的 <sqlMap> 调整为MyBatis<mapper>
  • <select> 等元素的iBatisparameterClass属性改为了MyBatisparameterType 属性。
  • <select>等元素的iBatisresultClasss属性改为了MyBatisresultType 属性。
  • <parameterMap>等元素的 iBatisclass 属性改为了MyBatistype属性。
  • <result> 元素的iBatiscolumnIndex 属性被移除了。
  • 嵌套参数由iBatis#value#改为了MyBatis#{value}
  • <parameter> 等元素的jdbcType 属性取值中,原来的iBatisORACLECURSOR 取值改为了现在的 MyBatisCURSORiBatisNUMBER取值改为了 MyBatisNUMERIC
  • iBatis 配置文件的根元素是 <sqlMapConfig>,而MyBatis使用的是 <configuration>

1.2.1.9 调用存储过程区别

  • iBatis 中调用存储过程的方式
    iBatis/MyBatis 对存储过程的支持一直是值得称道的。之前通过使用<procedure>元素进行存储过程的定义,示例如下:
<procedure id="getValues" parameterMap="getValuesPM">
    { ? = call pkgExample.getValues(p_id => ?) }
 </procedure>
  • MyBatis中调用存储过程的方式
    MyBatis 中,<proccedure>元素已经被移除,通过 <select><insert><update>进行定义:
<select id="getValues" parameterMap="getValuesPM" statementType="CALLABLE"> 
    { ? = call pkgExample.getValues(p_id => ?)} 
 </select>

如上所示,通过statementType属性将该语句标识为存储过程而非普通SQL语句。

代码层面的改变
通过前面的示例可以看出,MyBatis在编码中的最大的改变就是将一个最常用的 APISqlMapClient 改为了SqlSessionFactory。另外,类型处理器接口也由原来的 TypeHandlerCallback 改为了 TypeHandler。最后 DataSourceFactory 也进行了调整,移动到 org.apache.ibatis.datasource 包下,其中的方法也作了微调。总之,代码层面公开的部分改动较少,不会给开发者造成较大的移植成本。

1.3 ibatis语法

1.3.1 iterate循环标签

Iterate:这属性遍历整个集合,并为List集合中的元素重复元素体的内容。
Iterate的属性:

  • prepend - 可被覆盖的SQL语句组成部分,添加在语句的前面(可选)
  • property - 类型为java.util.List的用于遍历的元素(必选)
  • open - 整个遍历内容体开始的字符串,用于定义括号(可选)
  • close -整个遍历内容体结束的字符串,用于定义括号(可选)
  • conjunction - 每次遍历内容之间的字符串,用于定义ANDOR(可选)

遍历类型为java.util.List(或数组)的元素。
例子:

<iterate prepend=”AND” property=”userNameList” open=”(” close=”)” conjunction=”OR”> 
	username=#userNameList[]# 
</iterate>

注意:使用<iterate>时,在List元素名后面包括方括号[]非常重要,方括号[]将对象标记为List, 以防解析器简单地将List输出成String
在生成该条sql语句时,<iterate>标签中的内容是循环生成的,就拿上面的例子来说,生成的sql是:(username=xxx1 or username=xxx2 or username=xxx 3)而不是(username=xxx1 or xxx2 or xxx3)
再举个例子,如下:

id in 
<iterate  prepend="" property="ids"  open="("  close=")"  conjunction="," > 
               #ids[]# 
  </iterate> 

其生成的sql语句是:id in (xx1,xx2,xx3,.....),括号中的(包括括号)是<iterate>标签生成的。
<iterate>标签虽然是遍历整个集合的,但他也不象我们在java中用到的for一样,一次一次的循环生成标签中的内容,而是一次性利用list或数组生成整个可运行的sql语句。 就好比它生成的sql不可能象这样:id in (xx1) id in (xx2) ,id in (xx3),.....

1.3.2 动态sql标签

属性关键字含义
<isEqual>如果参数相等于值则查询条件有效
<isNotEqual>如果参数不等于值则查询条件有效
<isGreaterThan>如果参数大于值则查询条件有效
<isGreaterEqual>如果参数等于值则查询条件有效
<isLessEqual>如果参数小于值则查询条件有效。如下所示:
<isLessEqual prepend = ”AND” property = ”age” compareValue = ”18” >
ADOLESCENT = ‘TRUE’
</isLessEqual>
<isPropertyAvailable>如果参数有使用则查询条件有效
<isNotPropertyAvailable>如果参数没有使用则查询条件有效
<isNull>如果参数为NULL则查询条件有效
<isNotNull>如果参数不为NULL则查询条件有效
<isEmpty>如果参数为空则查询条件有效
<isNotEmpty>如果参数不为空则查询条件有效。参数的数据类型为Collection、String 时参数不为NULL或“”。如下所示:
<isNotEmpty prepend=”AND” property=”firstName” >
FIRST_NAME=#firstName#</isNotEmpty>
<isParameterPresent>如果参数类不为NULL则查询条件有效
<isNotParameterPresent>如果参数对象不存在(空) 有效:
<isNotParameterPresent prepend=”AND”>
EMPLOYEE_TYPE = ‘DEFAULT’
</isNotParameterPresent>

在动态标签中:

  • isequal:作比较用相当于String 里的equal方法,
  • property:指定比较属性的名称,
  • compareValue:表示要比较的参数,
  • prepend:表示追加比较条件
 类似资料: