Ibatis

来源:互联网 发布:python db2 连接 编辑:程序博客网 时间:2024/04/28 22:31

j2ee的O/R方案真是多,和Hibernate相比,iBatis最大的特点就是小巧,上手很快。看iBatis的文档2小时就会用了,这个O/R Mapping特点就是简单易用。只要有SQL基础,相信你不用教程也能看明白。最新版本2.0(下载 )。

构建ibatis基础代码
ibatis 基础代码包括:


1. ibatis 实例配置
一个典型的配置文件如下(具体配置项目的含义见后):
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-config-2.dtd ">
<sqlMapConfig>
<settings
            cacheModelsEnabled="true"
            enhancementEnabled="true"
            lazyLoadingEnabled="true"
            errorTracingEnabled="true"
            maxRequests="32"
            maxSessions="10"
            maxTransactions="5"
            useStatementNamespaces="false"
/>
<transactionManager type="JDBC">


<dataSource type="SIMPLE">
         <property name="JDBC.Driver"   value="com.p6spy.engine.spy.P6SpyDriver"/>
         <property name="JDBC.ConnectionURL"    value="jdbc:mysql://localhost/sample"/>
         <property name="JDBC.Username"   value="user"/>
         <property name="JDBC.Password"   value="mypass"/>
         <property name="Pool.MaximumActiveConnections"   value="10"/>
         <property name="Pool.MaximumIdleConnections"   value="5"/>
         <property name="Pool.MaximumCheckoutTime"   value="120000"/>
         <property name="Pool.TimeToWait"                  value="500"/>
         <property name="Pool.PingQuery"                  value="select 1 from  ACCOUNT"/>
         <property name="Pool.PingEnabled"             value="false"/>
         <property name="Pool.PingConnectionsOlderThan"     value="1"/>
         <property name="Pool.PingConnectionsNotUsedFor"    value="1"/>
</dataSource>


</transactionManager>
<sqlMap resource="com/ibatis/sample/User.xml"/>
</sqlMapConfig>


2. POJO(Plain Ordinary Java Object)
下面是我们用作示例的一个POJO:
public class User implements Serializable {
         private Integer id;
         private String name;
         private Integer sex;
         private Set addresses = new HashSet();
        /** default constructor */
         public User() {
          }


         public Integer getId() {
                  return this.id;
         }


        public void setId(Integer id) {
                  this.id = id;
         }


        public String getName() {
                  return this.name;
        }


        public void setName(String name) {
                  this.name = name;
        }


        public Integer getSex() {
                  return this.sex;
        }


        public void setSex(Integer sex) {
                  this.sex = sex;
        }
}


3. 映射文件
与Hibernate 不同。因为需要人工编写SQL 代码,ibatis 的映射文件一般采用手动编写(通过Copy/Paste,手工编写映射文件也并没想象中的麻烦)。
针对上面POJO 的映射代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap   PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"  "http://www.ibatis.com/dtd/sql-map-2.dtd ">


      <sqlMap namespace="User">
                   <typeAlias alias="user" type="com.ibatis.sample.User"/>
                   <select id="getUser"    parameterClass="java.lang.String"     resultClass="user">
                    <![CDATA[
                                   select
                                           name,
                                           sex
                                           from t_user
                                           where name = #name#
                    ]]>
                  </select>


                   <update id="updateUser"  parameterClass="user">
                   <![CDATA[
                                  UPDATE t_user
                                               SET
                                               name=#name#,
                                               sex=#sex#
                                               WHERE id = #id#
                    ]]>
                    </update>


                   <insert id="insertUser"   parameterClass="user" >
                                  INSERT INTO t_user (
                                                                name,
                                                                sex)
                                                    VALUES (
                                                                #name#,
                                                                #sex#
                                                                )
                   </insert>


                  <delete id="deleteUser"  parameterClass="java.lang.String">
                                 delete from t_user
                                                    where id = #value#
                  </delete>
         </sqlMap>
从上面的映射文件可以看出,通过<insert>、<delete>、<update>、<select>四个节点,我们分别定义了针对TUser 对象的增删改查操作。在这四个节点中,我们指定了对应的SQL 语句,以update节点为例:
……
                 <update id="updateUser" ⑴
                              parameterClass="user"> ⑵
                     <![CDATA[ ⑶
                                UPDATE t_user ⑷
                                               SET (
                                                      name=#name#, ⑸
                                                      sex=#sex# ⑹
                                                      )
                                               WHERE id = #id# ⑺
                     ]]>
                  </update>
……

⑴ ID
指定了操作ID,之后我们可以在代码中通过指定操作id 来执行此节点所定义的操作,如:
sqlMap.update("updateUser",user);
ID设定使得在一个配置文件中定义两个同名节点成为可能(两个update节点,以不同id区分)

⑵ parameterClass
指定了操作所需的参数类型, 此例中update 操作以com.ibatis.sample.User 类型的对象作为参数,目标是将提供的User
实例更新到数据库。
parameterClass="user"中,user为“com.ibatis.sample.User”类的别名,别名可通过typeAlias节点指定,如示例配置文件中的:

<typeAlias alias="user" type="com.ibatis.sample.User"/>

⑶ <![CDATA[……]]>
通过<![CDATA[……]]>节点,可以避免SQL 中与XML 规范相冲突的字符对XML映射文件的合法性造成影响。

⑷ 执行更新操作的SQL,这里的SQL 即实际数据库支持的SQL 语句,将由ibatis填入参数后交给数据库执行。

⑸ SQL中所需的用户名参数,“#name#”在运行期会由传入的user对象的name属性填充。

⑹ SQL 中所需的用户性别参数“#sex#”,将在运行期由传入的user 对象的sex属性填充。

⑺ SQL中所需的条件参数“#id#”,将在运行期由传入的user对象的id属性填充。

对于这个示例,ibatis在运行期会读取id 为“updateUser”的update节点的SQL定义,并调用指定的user对象的对应getter方法获取属性值,并用此属性值,对SQL中的参数进行填充后提交数据库执行。
此例对应的应用级代码如下,其中演示了ibatis SQLMap的基本使用方法:
         String resource ="com/ibatis/sample/SqlMapConfig.xml";
         Reader reader;

                    reader = Resources.getResourceAsReader(resource);
         XmlSqlMapClientBuilder xmlBuilder = new XmlSqlMapClientBuilder();
         SqlMapClient sqlMap = xmlBuilder.buildSqlMap(reader);
                  //sqlMap系统初始化完毕,开始执行update操作
               try{
                        sqlMap.startTransaction();


                        User user = new User();
                        user.setId(new Integer(1));
                        user.setName("Erica");
                        user.setSex(new Integer(1));


                        sqlMap.update("updateUser",user);
                        sqlMap.commitTransaction();
         } finally{
                        sqlMap.endTransaction();
                  }
其中,SqlMapClient是ibatis运作的核心,所有操作均通过SqlMapClient实例完成。
可以看出,对于应用层而言,程序员面对的是传统意义上的数据对象,而非JDBC中烦杂的ResultSet,这使得上层逻辑开发人员的工作量大大减轻,同时代码更加清晰简洁。
数据库操作在映射文件中加以定义,从而将数据存储逻辑从上层逻辑代码中独立出来。
而底层数据操作的SQL可配置化,使得我们可以控制最终的数据操作方式,通过SQL的优化获得最佳的数据库执行效能,这在依赖SQL自动生成的“全自动”ORM机制中是所难以实现的。

ibatis配置
结合上面示例中的ibatis配置文件。下面是对配置文件中各节点的说明:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig  PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"  "http://www.ibatis.com/dtd/sql-map-config-2.dtd ">
      <sqlMapConfig>
              <settings ⑴
                              cacheModelsEnabled="true"
                              enhancementEnabled="true"
                              lazyLoadingEnabled="true"
                              errorTracingEnabled="true"
                              maxRequests="32"
                              maxSessions="10"
                              maxTransactions="5"
                              useStatementNamespaces="false"
              />


              <transactionManager type="JDBC"> ⑵
               <dataSource type="SIMPLE"> ⑶
                              <property name="JDBC.Driver"    value="com.p6spy.engine.spy.P6SpyDriver"/>
                              <property name="JDBC.ConnectionURL"   value="jdbc:mysql://localhost/sample"/>
                              <property name="JDBC.Username"   value="user"/>
                              <property name="JDBC.Password"   value="mypass"/>
                              <property name="Pool.MaximumActiveConnections"    value="10"/>
                              <property name="Pool.MaximumIdleConnections"    value="5"/>
                              <property name="Pool.MaximumCheckoutTime"    value="120000"/>
                              <property name="Pool.TimeToWait"   value="500"/>
                              <property name="Pool.PingQuery"    value="select 1 from  ACCOUNT"/>
                              <property name="Pool.PingEnabled"   value="false"/>

                              <property name="Pool.PingConnectionsOlderThan"   value="1"/>
                              <property name="Pool.PingConnectionsNotUsedFor"   value="1"/>
               </dataSource>
           </transactionManager>


         <sqlMap resource="com/ibatis/sample/User.xml"/> ⑷
         <sqlMap resource="com/ibatis/sample/Address.xml"/>
        </sqlMapConfig>

⑴ Settings 节点
参数 描述
 cacheModelsEnabled 是否启用SqlMapClient上的缓存机制。建议设为"true"   enhancementEnabled 是否针对POJO启用字节码增强机制以提升   getter/setter的调用效能,避免使用JavaReflect所带来的性能开销。同时,这也为Lazy Loading带来了极大的性能提升。建议设为"true"


errorTracingEnabled 是否启用错误日志,在开发期间建议设为"true" 以方便调试
lazyLoadingEnabled 是否启用延迟加载机制,建议设为"true"


maxRequests 最大并发请求数(Statement并发数) maxTransactions 最大并发事务数
maxSessions 最大Session 数。即当前最大允许的并发 SqlMapClient数。


maxSessions设定必须介于  maxTransactions和maxRequests之间,即
maxTransactions<maxSessions=<  maxRequests


useStatementNamespaces 是否使用Statement命名空间。这里的命名空间指的是映射文件中,sqlMap节点
的namespace属性,如在上例中针对t_user表的映射文件sqlMap节点:
<sqlMap namespace="User">
       这里,指定了此sqlMap节点下定义的操作均从属于"User"命名空间。在useStatementNamespaces="true"的情
况下,Statement调用需追加命名空间,如:
             sqlMap.update("User.updateUser",user);
否则直接通过Statement名称调用即可,如:
             sqlMap.update("updateUser",user);
但请注意此时需要保证所有映射文件中,Statement定义无重名。

⑵ transactionManager节点
transactionManager 节点定义了ibatis 的事务管理器,目前提供了以下几种选择:
Ø JDBC
通过传统JDBC Connection.commit/rollback实现事务支持。
Ø JTA
使用容器提供的JTA服务实现全局事务管理。
Ø EXTERNAL
外部事务管理,如在EJB中使用ibatis,通过EJB的部署配置即可实现自动的事务管理机制。此时ibatis 将把所有事务委托给外部容器进行管理。此外,通过Spring 等轻量级容器实现事务的配置化管理也是一个不错的选择。关于结合容器实现事务管理,参见“高级特性”中的描述。

⑶ dataSource节点
dataSource从属于transactionManager节点,用于设定ibatis运行期使用的DataSource属性。
type属性: dataSource节点的type属性指定了dataSource的实现类型。
可选项目:
Ø SIMPLE:
SIMPLE是ibatis内置的dataSource实现,其中实现了一个简单的数据库连接池机制, 对应ibatis 实现类为
com.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory。
Ø DBCP:
基于Apache DBCP 连接池组件实现的DataSource 封装,当无容器提供DataSource 服务时,建议使用该选项,对应ibatis 实现类为
com.ibatis.sqlmap.engine.datasource.DbcpDataSourceFactory。
Ø JNDI:
使用J2EE 容器提供的DataSource 实现,DataSource 将通过指定的JNDI Name 从容器中获取。对应ibatis 实现类为
com.ibatis.sqlmap.engine.datasource.JndiDataSourceFactory。
dataSource的子节点说明(SIMPLE&DBCP):

参数 描述
JDBC.Driver JDBC 驱动。
如:org.gjt.mm.mysql.Driver   JDBC.ConnectionURL 数据库URL。
如:jdbc:mysql://localhost/sample
如果用的是SQLServer JDBC Driver,需要 在url后追加SelectMethod=Cursor以获得
JDBC事务的多Statement支持。 JDBC.Username 数据库用户名  JDBC.Password 数据库用户密码
Pool.MaximumActiveConnections
数据库连接池可维持的最大容量。
Pool.MaximumIdleConnections
数据库连接池中允许的挂起(idle)连接数。以上子节点适用于SIMPLE 和DBCP 模式,分别针对SIMPLE 和DBCP 模式的
DataSource私有配置节点如下:
SIMPLE:
参数 描述
           Pool.MaximumCheckoutTime
数据库联接池中,连接被某个任务所允许占用的最大时间,如果超过这个时间限定,连接将被强制收回。(毫秒)
Pool.TimeToWait 当线程试图从连接池中获取连接时,连接池中无可用连接可供使用,此时线程将进入等待状态,直到池中出现空闲连接。此参数设定了线程所允许等待的最长时间。(毫秒)
Pool.PingQuery 数据库连接状态检测语句。某些数据库在连接在某段时间持续处于空闲状态时会将其断开。而连接池管理器将通过此语句检测池中连接是否可用。检测语句应该是一个最简化的无逻辑SQL。如“select 1 from t_user”,如果执行此语句成功,连接池管理器将认为此连接处于可用状态。
Pool.PingEnabled 是否允许检测连接状态。
Pool.PingConnectionsOlderThan
对持续连接时间超过设定值(毫秒)的连接进行检测。

Pool.PingConnectionsNotUsedFor
对空闲超过设定值(毫秒)的连接进行检测。
DBCP:
参数 描述
Pool.MaximumWait 当线程试图从连接池中获取连接时,连接池中无可用连接可供使用,此时线程将进入等待状态,直到池中出现空闲连接。此参数设定了线程所允许等待的最长时间。(毫秒)
Pool.ValidationQuery 数据库连接状态检测语句。某些数据库在连接在某段时间持续处于空闲状态时会将其断开。而连接池管理器将通过此语句检测池中连接是否可用。
检测语句应该是一个最简化的无逻辑SQL。如“select 1 from t_user”,如果执行此语句成功,连接池管理器将认为此连接处于可用状态。
Pool.LogAbandoned 当数据库连接被废弃时,是否打印日志。
Pool.RemoveAbandonedTimeout
数据库连接被废弃的最大超时时间
Pool.RemoveAbandoned 当连接空闲时间超过RemoveAbandonedTimeout时,是否将其废弃。


JNDI由于大部分配置是在应用服务器中进行,因此ibatis中的配置相对简单,下面是分别使用JDBC和JTA事务管理的JDNI配置:使用JDBC事务管理的JNDI DataSource配置
        <transactionManager type="JDBC" >
                     <dataSource type="JNDI">
                               <property name="DataSource"    value="java:comp/env/jdbc/myDataSource"/>
                     </dataSource>
       </transactionManager>


       <transactionManager type="JTA" >
                     <property name="UserTransaction"   value="java:/ctx/con/UserTransaction"/>
                     <dataSource type="JNDI">
                               <property name="DataSource"   value="java:comp/env/jdbc/myDataSource"/>
                    </dataSource>
        </transactionManager>

⑷ sqlMap节点
sqlMap 节点指定了映射文件的位置,配置中可出现多个sqlMap 节点,以指定项目内所包含的所有映射文件。