ibitis简介及实例

来源:互联网 发布:优化特色课程 编辑:程序博客网 时间:2024/06/05 06:18


一.ibatis简介

相对Hibernate和Apache OJB等“一站式”ORM解决方案而言,ibatis 是一种“半自动化”的ORM实现。

  所谓“半自动”,可能理解上有点生涩。纵观目前主流的 ORM,无论 Hibernate 还是Apache OJB,都对数据库结构提供了较为完整的封装,提供了从POJO 到数据库表的全套映射机制。程序员往往只需定义好了POJO 到数据库表的映射关系,即可通过 Hibernate或者OJB 提供的方法完成持久层操作。程序员甚至不需要对 SQL 的熟练掌握,Hibernate/OJB会根据制定的存储逻辑,自动生成对应的 SQL 并调用 JDBC 接口加以执行。

大多数情况下(特别是对新项目,新系统的开发而言),这样的机制无往不利,大有一统天下的势头。但是,在一些特定的环境下,这种一站式的解决方案却未必灵光。但是在系统咨询工作过程中,常常遇到以下情况:   

1. 系统的部分或全部数据来自现有数据库,处于安全考虑,只对开发团队提供几条Select SQL(或存储过程)以获取所需数据,具体的表结构不予公开。  

2. 开发规范中要求,所有牵涉到业务逻辑部分的数据库操作,必须在数据库层由存储过程实现  

3. 系统数据处理量巨大,性能要求极为苛刻,这往往意味着我们必须通过经过高度优化的SQL语句(或存储过程)才能达到系统性能设计指标。   

面对这样的需求,再次举起 Hibernate 大刀,却发现刀锋不再锐利,甚至无法使用,奈何?恍惚之际,只好再摸出JDBC 准备拼死一搏……,说得未免有些凄凉,直接使用 JDBC进行数据库操作实际上也是不错的选择,只是拖沓的数据库访问代码,乏味的字段读取操作令人厌烦。

“半自动化”的ibatis,却刚好解决了这个问题。   这里的“半自动化”,是相对Hibernate等提供了全面的数据库封装机制的“全自动化”   ORM 实现而言,“全自动”ORM 实现了 POJO 和数据库表之间的映射,以及 SQL 的自动   生成和执行。而ibatis 的着力点,则在于POJO 与 SQL之间的映射关系。也就是说,ibatis   并不会为程序员在运行期自动生成 SQL 执行。具体的 SQL 需要程序员编写,然后通过映   射配置文件,将SQL所需的参数,以及返回的结果字段映射到指定 POJO。

使用ibatis 提供的ORM机制,对业务逻辑实现人员而言,面对的是纯粹的 Java对象,   这一层与通过 Hibernate 实现 ORM 而言基本一致,而对于具体的数据操作,Hibernate   会自动生成SQL 语句,而ibatis 则要求开发者编写具体的 SQL 语句。相对Hibernate等   “全自动”ORM机制而言,ibatis 以 SQL开发的工作量和数据库移植性上的让步,为系统  设计提供了更大的自由空间。作为“全自动”ORM实现的一种有益补充,ibatis 的出现显   得别具意义。

二.快速入门

1.想要使用ibatis,就需要先导入ibatis-2.3.0.677.jar包,当然少不了数据库驱动jar包classes12.jar。如下图:

      

2.在工程src目录下,建立ibatis.xml文件,这里以dept表为例,连接的是Oracle数据库

参考代码如下:

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEsqlMapConfig  

  PUBLIC "-//ibatis.apache.org//DTDSQL Map Config 2.0//EN"  

  "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<sqlMapConfig>

       <settingscacheModelsEnabled="true"

           enhancementEnabled="true"

           lazyLoadingEnabled="true"

           errorTracingEnabled="true"

           maxRequests="32"

           maxSessions="10"

           maxTransactions="5"

           useStatementNamespaces="false"

       />

       <transactionManagertype="JDBC">

           <dataSourcetype="SIMPLE">

<propertyname="JDBC.Driver"value="oracle.jdbc.driver.OracleDriver"/>

<propertyname="JDBC.ConnectionURL"value="jdbc:oracle:thin:@localhost:1521:orcl"/>

              <propertyname="JDBC.Username"value="scott"/>

              <propertyname="JDBC.Password"value="tiger"/>

              <propertyname="Pool.MaximumActiveConnections"value="10"/>

              <propertyname="Pool.MaximumIdleConnections"value="5"/>

              <propertyname="Pool.MaximumCheckoutTime"value="120000"/>

              <propertyname="Pool.TimeToWait"value="500"/>

              <propertyname="Pool.PingQuery"value="select 1 from dept"/>

              <propertyname="Pool.PingEnabled"value="true"/>

              <propertyname="Pool.PingConnectionsOlderThan"value="1"/>

              <propertyname="Pool.PingconnectionsNotUsedFor"value="1"/>

           </dataSource>

          

       </transactionManager>

       <sqlMapresource="com/siqi/po/dept.ibatis.xml"/>

</sqlMapConfig>

 

注意:对于ibatis.xml文件中,各项配置标签的解释,请参考同目录下的配置注释.txt,里面有详细解释。

 

 

 

3.我们在com.siqi.po包下建立Dept类和dept.ibatis.xml配置文件,

如下图:

 

       参考代码如下:

      

publicclass Dept {

    privateintdeptno;

    private Stringdname;

    private Stringloc;

    publicint getDeptno() {

       returndeptno;

    }

    publicvoid setDeptno(int deptno) {

       this.deptno = deptno;

    }

    public String getDname() {

       returndname;

    }

    publicvoid setDname(String dname) {

       this.dname = dname;

    }

    public String getLoc() {

       returnloc;

    }

    publicvoid setLoc(String loc) {

       this.loc = loc;

    }

}

 

 

dept.ibatis.xml文件,参考代码如下:

       <?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEsqlMap PUBLIC "-//ibatis.apache.org//DTDSQL Map 2.0//EN" 

    "http://ibatis.apache.org/dtd/sql-map-2.dtd">

   

   <sqlMapnamespace="Dept">

  

    <typeAliasalias="dept"type="com.siqi.po.Dept"/>

   

       <selectid="getDeptById"

       parameterClass="dept"

       resultClass="dept">

       <![CDATA[

           select dname,loc from dept where deptno=#deptno#

       ]]>

       </select>

      

       <selectid="getDept"

       parameterClass="dept"

       resultClass="dept"

       >

       <![CDATA[

           select deptno,dname,loc from dept

       ]]>

       </select>

      

       <updateid="updateDept"

       parameterClass="dept">

       <![CDATA[

           update dept set dname=#dname#,loc=#loc# wheredeptno=#deptno#

       ]]>

       </update>

      

       <insertid="insertDept"

       parameterClass="dept">

           <![CDATA[

              insert into dept values(#deptno#,#dname#,#loc#)

           ]]>

       </insert>

      

       <deleteid="deleteDept"

       parameterClass="dept">

       <![CDATA[

           delete from dept where deptno=#deptno#

       ]]>

       </delete>

</sqlMap>

 

 

注意:

       id:

指定了操作ID,之后我们可以在代码中通过指定操作id来执行节点所定义的操作,可以定义两个同名节点,但id必须不同。它就相当于我们以前的方法名。

举例:

              sqlMap.delete( “deleteDept”,dept);

       parameterClass:

       指定了操作所需的参数类型,上面配置文件中 真正的参数类型应该为:com.siqi.po.Dept

因为,我们在前面设置了<typeAlias alias="dept" type="com.siqi.po.Dept"/>

所以,dept 就为com.siqi.po.Dept的别名。所以在参数类型位置可以直接写dept

       <![CDATA[…]>

       通过此节点,可以避免SQL中与XML规范相冲突的字符对XML映射文件的合法性造成影响。

       可执行操作的SQL语句

       这里的SQL语句即实际数据库支持的SQL语句,将由iBatis填入参数后交给数据库执行。

       SQL中所需要的参数:

       参数都以 “ #...# ”标注。

三.测试

下面我们写一个测试类,来简单测试下,经过上述配置,ibatis能否使用

publicclass Test {

    publicstaticvoid main(String[] args) {

 

       Reader reader=null;

       try {

           reader=Resources.getResourceAsReader("ibatis.xml");

       } catch (IOException e) {

           //TODO Auto-generatedcatch block

           e.printStackTrace();

       }

    SqlMapClientsqlMap=SqlMapClientBuilder.buildSqlMapClient(reader);

       try {

           sqlMap.startTransaction();

           Dept d=new Dept();

           d.setDeptno(80);

           d.setDname("hello");

           d.setLoc("world");

           sqlMap.insert("insertDept",d);增加方法

           //sqlMap.delete("deleteDept",d);删除方法

           //sqlMap.update("updateDept",d);修改方法

          

List<Dept> list=s.queryForList("getDept",d); //查询方法, //查询方法比较特殊。

 

           for(Dept dept:list){

            System.out.println(dept.getDeptno()+”,”+dept.getDname()+”,”+dept.getLoc());

           }

           s.commitTransaction();

           s.endTransaction();

       } catch (Exception e) {

           //TODO Auto-generatedcatch block

           e.printStackTrace();

       }

   

    }

}

 

经过上面测试,我们成功啦~!

增加一条数据:

我们再修改编号为88的loc为“jinan“。

代码如下:

效果如下:

 

我们再来删除部门编号为88的部门

代码如下:

 

四.拓展

      (1)分页查询

              queryForList() 方法,有传入四个参数的,再利用自定义标签就可以实现分页查询

举例:

       queryForList(“getDept”,d,(当前页-1)*每页大小,每页大小)

代码如下,定义currentPage:当前页,pageSize:每页大小,totalCount为记录总条数.

 

 

实现的效果为:

 

       (2)模糊查询

              SQL语句为:select* from dept where dname like '%'||#dname#||'%'

配置文件中代码如下:

      

调用方法时,

      

这样就可以查出所有部门名称中带“A“的部门

       Ps:囧,貌似都带A   ⊙﹏⊙b汗

 

(3)一对多查询.这里我们以dept和emp表为例

1.首先在po里加上Emp类

2.在dept.ibatis.xml中增加以下配置

执行步骤如上,师弟,师妹们一定要注意配置id和resultMap时,起的名字单词要对应一致

 

别忘记在Dept中加上 emp的集合。而且由于版本问题, iBatis2.0仅对java.util.Listjava.util.Collection类型进行支持。

3.进行测试

这里我们以部门编号为30的部门为例

上述代码无BUG