ibatis对象关系映射

 

简介: iBatis 是一个开源的对象关系映射程序,其工作是将对象映射到 SQL 语句。和其它 O/R Mapping 框架不同,iBatis 开发者需要自己编写和维护 SQL 语句,这给开发带来了很多的灵活性的同时,也带来了很大的复杂度与工作量。在一个数据库中,常见的对象关系有:1 对 1,1 对多,多对多,单表映射,多表映射,单主键,多主键以及对象主键等种种情况。在使用 ibatis 处理数据映射时,需要跟据不同的情况,写出不同的 sql 语句和 sql map 的实现,特别是在复杂关系跟复杂主键时需要编写大量的复杂 sql。本文将详细介绍如何使用 ibatis 来处理数据库中的复杂数据对象关系,根据数据关系的分类,给出具体的实现代码模板与解释。通过本文读者可以了解 ibatis 处理复杂关系时可以使用方式,在具体编写代码过程中只需要套用本文中列出的这些模板,这样可以大大简化开发和加快开发的速度。本文的读者需要对 ibatis 已经有一些基本的使用经验。

ibatis 基本介绍

起源于 2001 年的开放源代码项目 ibatis,是一个基于 Java 的持久层框架。与 Hibernate, Toplink 等持久化框架不同,ibatis 是一个 “半自动化”的 ORM 实现。ibatis 没有对数据库结构提供了较为完整的封装,而是提供了一个从 POJO 到数据库表的全套映射机制。这使得在开发 ibatis 的时候,需要手动的编写 sql 来提过数据库与类对象之间的映射,这在给开发提供了很大的灵活性的同时,大大增加了开发的工作量。Ibatis 主要有以下的这些特性:

1. 简单性

Ibatis 是一个非常简单易用的工具包。这个简单性不仅仅体现在开发库的轻量小巧上,iBATIS 对于 Java 开发者来说也非常简单。因为它除了不用编写那么多代码外与 JDBC 的工作机制非常相像,iBATIS 就是以 XML 的形式来描述的 JDBC 代码。iBATIS 对于数据库管理员以及 SQL 程序员来 说也非常容易理解。iBATIS 配置文件几乎人人都能读懂,只要他有 SQL 编程的经验。

2. 效率与性能

iBATIS 通过一种简单的方式来配置和使用,其性能与 JDBC 相当。通过直接编写 SQL 查询,开发人员可以直接控制 SQL 语句来优化执行效率,甚至可以在其中调用存储过程,为开发人员提供了巨大的 SQL 优化空间。

3. 代码分离

在 iBATIS 中,SQL 语句在很大程度上同应用的源代码是分离 的,SQL 程序员可以按照 SQL 原本的方式来编写它,而不必担心有关 SQL 字符串连接的问题。iBATIS 提供了充分的自由,使得任何人都可以开发、观察并且修改在数据库中执行的 SQL 语句。

4. 可移植性

iBATIS 是可移植的。由于它相对简单的设计,它几乎可以用任何一种语言在任何一个平台上实现。iBATIS 支持 3 种最受欢迎的开发平台:Java、Ruby 和微软 .NET 的 C#。

常见的对象映射与实现

由于在使用 ibatis 进行项目开发中,需要根据数据库的表结构与 Java 类之间的关系写出实现的 SQL 代码,不同的关系会对应不同 SQL 实现。这些 SQL 代码将会和其他 mapping 信息一起放在 ibatis 的 SQL mapping 文件中。下面就对这些每一种映射进行详细分析并给出实现示例。

单表对象绑定与多表对象绑定

在 ibatis 中最简单的关系就是一个对象对单个表的绑定,这也是最简单的类与数据库的映射关系。在没有任何外键关系的时候,在 ibatis 中直接将类的字段对应到表的列即可:


清单 1. 单个对象表绑定的实现
<typeAlias alias="Bank" type="com.example.domain.Bank"/> 
	 <resultMap id="getBankResult" class="Bank"> 
  <result property="id" column="B_ID"/> 
  <result property="name" column="B_NAME"/> 
  </resultMap> 
  
 <select id="getBankById" resultMap="getBankResult" parameterClass="string"/> 
 SELECT `BANKL`.`BANKID` AS `B_ID`, `BANKL`.`NAME` AS `B_NAME` 
 FROM `BANKL` 
 WHERE `BANKID` = #id# 
 </select/>

在某些特殊的对象中,有的时候需要将一个对象映射到多个表中,在这个时候就需要在映射时加入对两张表的选择。因此,需要对上面的简单的 sql 进行一些改动,加入一个两张表的 join 操作,以下是示例:


清单 2. 单个对象多表绑定的实现
<typeAlias alias="Customer" type="com.example.domain.Customer"/> 
  <resultMap id="getCustomerResult" class="Customer"> 
    <result property="id" column="C_ID"/> 
    <result property="name" column="C_NAME"/> 
    <result property="birthday" column="C_BIRTHDAY"/> 
    <result property="gender" column="C_GENDER"/> 
    <result property="identityType" column="C_IDENTITYTYPE"/> 
		 <result property="identityId" column="C_IDENTITYID"/> 
    <result property="consumePoint" column="C_CONSUMEPOINT"/> 
    <result property="lastGetDate" column="C_LASTGETDATE"/> 
		 <result property="lastUseDate" column="C_LASTUSEDATE"/> 
  </resultMap> 
 <select id="getCustomerById" resultMap="getCustomerResult" parameterClass="string"/>  
 SELECT 
 `CUMAS`.`ID` AS `C_ID`, `CUMAS`.`NAME` AS `C_NAME`, `CUMAS`.`BIRTHDAY` AS 
 `C_BIRTHDAY`, `CUMAS`.`GENDER` AS `C_GENDER`, `CUMAS`.`IDTYPE` AS `C_IDENTITYTYPE`, 
 `CUMAS`.`IDNO` AS `C_IDENTITYID`, `CUSPT`.`POINT` AS `C_CONSUMEPOINT`, `CUSPT`.`LASTGET` 
 AS `C_LASTGETDATE`, `CUSPT`.`LASTUSE` AS `C_LASTUSEDATE` 
 FROM `CUMAS`, `CUSPT` WHERE`ID` = #id# AND `CUMAS`.`ID` = `CUSPT`.`CUSID`<select/>

在上面这个例子中,Customer 这个对象被映射到 CUMAS 与 CUSPT 两个表中,每个表中包含了一部分字段,所以在选择的时候需要将两张表 join 起来。在进行删除,修改等操作时,需要注意的是要创建两条语句并在 java code 中对两条语句都进行调用,否则会导致数据不一致的现象发生:


清单 3. 单个对象多表绑定的删除语句
<delete id="deleteCustomer" parameterClass="string"> 
 DELETE FROM `CUMAS` WHERE `ID` = #id#    
  </delete> 
  <delete id="deleteCustomer2" parameterClass="string"> 
 DELETE FROM `CUSPT` WHERE `CUSID` = #id#    
 </delete>

单主键与多主键

在数据库中,一般需要对每条记录定义一个主键,大部分情况下采用一个自增长的 ID 来实现。这个时候有两种实现方法,第一种是用数据库自带的 id 增长功能,如何在 ibatis 中实现这种情况已在 iBatis 帮助文档中有详细说明,这里就不在赘述。第二种方法是采用类似 Toplink 中的实现方式,在 Java 中控制 ID 的增长,这种方法使用一张 sequence 表来存放所有的 id 记录,该表有两个字段,第一个为表名,第二个为当前最新的 id 值,表中的每一行对应一个自增长的 id。与该表对应的为一个 Java 的 Sequence 类与 iBatis 映射文件。在查询每个 sequence 时,通过 sequence name 将当前 id 值取出并设置到对象的 id 中。

在获取新的 sequence 时,需要注意的是对并发的控制,在同一时间只能有一个线程更新 sequence,否则将会导致主键重复。


清单 4. Sequence 的实现
Sequence 的 Java 类public class Sequence{ 
    protected String name; 
    protected String nextId; 
    public String getName() { 
      return name; 
    } 
    public void setName(String name) { 
      this.name = name; 
    } 
    public String getNextId() { 
      return nextId; 
    } 
    public void setNextId(String nextId) { 
      this.nextId = nextId; 
    } 
 }Sequence 的 SQL 映射<sqlMap namespace="Sequence"> 
 <typeAlias alias="Sequence" type="com.example.Sequence"/> 
  <resultMap id="getSequenceResult" class="Sequence"> 
    <result property="name" column="S_NAME"/> 
    <result property="nextId" column="S_NEXTID"/> 
  </resultMap> 
 <select id="getSequenceById" resultMap="getSequenceResult" parameterClass="string" >  
 SELECT 
 `SEQ`.`SEQNAME` AS `S_NAME`, `SEQ`.`SEQVALUE` AS `S_NEXTID` FROM `SEQ` 
 WHERE `SEQNAME` = #name# 
 </select>  
 <update id="updateSequence" parameterClass="Sequence">  
 UPDATE `B2CSEQ` SET `SEQVALUE`=#nextId# WHERE `SEQNAME` = #name# 
 </update> 
 </sqlMap>通过 Sequence 获取 ID 的方法public static synchronized String getNextId(String name) throws SQLException { 
   SqlMapSession sequenceSession=SessionManager.retrieveSession(); 
   ISequence sequence = (ISequence) sequenceSession.queryForObject( 
        "getSequenceById", name); 
   if (sequence == null) { 
    throw new SQLException("Error: A null sequence was returned from the database" + 
      " (could not get next "+ name + " sequence)."); 
   } 
   String id = sequence.getNextId(); 
   sequence.setNextId((new BigDecimal(id).add(new BigDecimal(5))).toString()); 
   sequenceSession.startTransaction(); 
   sequenceSession.update("updateSequence", sequence); 
   sequenceSession.commitTransaction(); 
   sequenceSession.close(); 
   return String.valueOf(sequence.getNextId()); 
  }

常见的类关系与实现

对于类与类之间的引用关系,最常见的是一对一,一对多与多对多。下面就讲述对这三种关系的实现。

一对一映射

在类与类之间关系中,一对一是最简单的一种。在每个类中有一个对其他类的引用,反之亦然。此时只需在 ibatis 的 result map 中建立对对象的引用关系即可:


清单 5. 一对一的引用
<result property="belongedCatalog" column="A_BELONGEDCATALOG" 
 select="getArticleCatalogById"/>

在上面的 mapping 中,A_BELONGEDCATALOG 为查询结果中的一个字段,而 getArticleCatalogById 为一个返回结果为 Catalog 的查询。因此 ibatis 在调用时,将会把 A_BELONGEDCATALOG 作为参数传入 getArticleCatalogById 来生成一个 Catalog 实例的引用 , 并将改引用赋值给 belongedCatalog 属性。

一对多映射

一对多关系与 1 对 1 关系的区别之处在于类中引用的对象为一个列表而非单个对象,因此在 resultmap 中的 mapping 是一样的,唯一的区别在于关联的 select 返回的为一个列表而非单个对象(上例中的 getArticleCatalogById 的返回结果为一个对象,而对于一对多关系此方法将返回一个列表)。因此在这里不再给出实现。

多对多

在实现多对多关系时,每个类都可能包含多个对对方类的引用列表,通常需要建立一张关系表用来存储关系映射,如下所示:


清单 6. 多对多的关系表
CREATE TABLE `ARTICLE_GROUP_RELATION` ( 
 `GROUPID` varchar(10) not null , 
 `ARTICLEID` varchar(10) not null );

在这里 Article 与 Group 两个对象之间存在多对多关系,GROUPID 与 ARTICLEID 字段分别对应与 Group 表与 Article 表的主键。若在 Group 对象中有一个对 Article 列表的引用,首先需要在 Group 的 resultmap 中定义一个 List 的属性。这个属性会映射到一条根据 GroupID 查出 Article 的语句 getArticleByArticleGroupId,该查询需要将上面定义的关系表与 Article 表进行连接,返回结果为一个 Article 的列表 :


清单 7. 多对多的关系映射
<result property="articleList" column="AG_ID" select="getArticleByArticleGroupId"/> 
 <select id="getArticleByArticleGroupId" resultMap="getArticleResult" 
 parameterClass="string"> 
 SELECT 
 `ARTICLE`.`ID` AS `A_ID`, `ARTICLE`.`NAME` AS `A_NAME`, `ARTICLE`.`INDUSTRY` 
 AS `A_ISINDUSTRY`, `ARTICLE`.`UPDATEDATE` AS `A_UPDATEDATE` 
 FROM ` ARTICLE `, ` ARTICLE_GROUP_RELATION ` 
 WHERE `ARTICLE_GROUP_RELATION`.`GROUPID` = #id# AND 
 `ARTICLE_GROUP_RELATION`.`ARTICLEID` = `ARTICLE`.`ID` 
 </select>

需要注意的是,在对应的增加 / 删除 / 修改操作中,也需要调用一个 SQL 语句来更新关系表,否则会导致表中的数据不一致,以删除为例:


清单 8. 多对多的删除语句
<delete id="deleteArticleGroupArticleList" parameterClass="string" > 
 DELETE FROM `ARTICLE_GROUP_RELATION` WHERE `GROUPID` = #id# 
 </delete>

复合关系的分类与实现

上一章介绍了类之间的关系的实现,本章在上一章的基础上,介绍了几种对象主键与继承类关系的实现。

对象主键

对象主键是一种非常特殊的主键实现,此时不是使用一个自动增长的 ID 作为类的主键,而是将类中所引用到的某个对象作为主键。因此,在建表的时候就需要将主键对象表中的主键字段作为该表中的主键字段保存,同样在进行 resultmap 的定义时需要建立一个对与其他对象的引用:

在下面这个例子中,UserCredit 对象中包含一个 createUser 对象并以该对象作为主键,而 User 对象本身包含了两个主键:用户 ID 与注册系统。因此在对 UserCredit 建表时将 USERID 跟 REGISTEREDSYSTEM 作为两个字段存放,对应的在映射时需要将这两个字段一起映射到 user 对象的查询上。对应的字段映射与查询语句如下:


清单 9. 对象主键的关系映射
<result property="createUser" column="userId= USERID , 
 registeredSystem= REGISTEREDSYSTEM" select="getUserById"/> 

 <select id="getUserById" resultMap="getUserResult" 
 parameterClass="java.util.HashMap" >  
 SELECT 
 `SYUSR`.`USERID` AS `U_USERID`, `SYUSR`.`SYSCODE` AS 
 `U_REGISTEREDSYSTEM`, `SYUSR`.`NAME` AS `U_NAME`, 
 `SYUSR`.`SYSNAME` AS `U_DISPNAME`, `SYUSR`.`GENDER` AS `U_GENDER`, 
 `SYUSR`.`MOBILE` AS `U_MOBILE`, `SYUSR`.`EMAIL` AS `U_EMAIL 
 FROM `SYUSR` 
 WHERE 
 `USERID` = #userId# AND `SYSCODE` = #registeredSystem# 
 </select> 
 <select id="getUserCreditByUser" resultMap="getUserCreditResult" 
 parameterClass="java.util.HashMap"> 
 SELECT `NUMBER`, `NUMBERREMAIN`, ` USERID `, `SYSCODE` 
 FROM `CREDIT` 
 WHERE `CREDIT`.` USERID ` = #userId# AND `CREDIT`.`SYSCODE` = #registeredSystem# 
 </select>

需要注意的是,在 getUserById 中接受的参数为一个 HahsMap,这个 HashMap 中存放了两个字段:userId 和 registeredSystem。因此在映射是需要写成 column="userId= USERID , registeredSystem= REGISTEREDSYSTEM"的方式来传入一个 Map 参数。

对于对象主键的查询语句,可以将参数设为一个对象,也可以将参数设为一个 Map,在 Map 中放入 userId 与 registeredSystem,在查询时使用这两个值作为查询条件。类似的在其他增加 / 删除 / 修改操作时也可以传入一个 HashMap 作为参数。

一对多与多对多时的对象主键

在上一小节的基础上,如果某个以对象为主键的类被其他类所引用并建立了一对多或者多对多的关系,此时在 mapping 时需要把前一章中使用的关联的 id 改成对象的主键。下面是一对多的示例,首先在 resultmap 中定义属性映射,然后定义了对应的查询方法。


清单 10. 一对多对象主键的关系映射
<result property="groupList" column="userId= USERID , 
 registeredSystem= REGISTEREDSYSTEM" select=" getAttrListByUser "/> 
 <select id="getAttrListByUser" resultMap="getAttrResult" 
 parameterClass="java.util.HashMap"> 
 SELECT `ATTRIBUTENAME`, `ATTRIBUTEVALUE`, ` USERID `, `SYSCODE` 
 FROM `ATTRIBUTE` 
 WHERE `ATTRIBUTE`.`USERID` = #userId# AND 
 `ATTRIBUTE`.`SYSCODE` = #registeredSystem# 
 </select>

将上面的对象主键与前面提到的多对多关系结合起来,可以得到最复杂的多对多的对象主键的实现。首先在关系表中需要加入对于对象主键的定义。假设 Article 对象为多主键对象,在 Article 中有一个 GroupList 的属性,Article 与 Group 有多对多的关系,以下为表的定义与 resultmap 的实现:


清单 11. 一对多对象主键的关系映射
CREATE TABLE `ARTICLE_GROUP_RELATION` ( 
 `GROUPID` varchar(10) not null , 
 `ARTICLETITLE` varchar(10) not null, 
 `ARTICLEUSER` varchar(10) not null ); 
 <result property="groupList" column=" articleTitle=TITLE, 
 articleUser=USERID" select="getGroupByArticle"/> 

 <select id="getGroupByArticle" resultMap="getGroupResult" 
 parameterClass="java.util.HashMap"> 
 SELECT 
 `GROUP`.`NAME` AS `G_NAME`, `GROUP`.`ID` AS `G_ID` 
 FROM ` GROUP `, ` ARTICLE_GROUP_RELATION ` 
 WHERE `ARTICLE_GROUP_RELATION`.`GROUPID` = GROUP.`ID` AND 
 `ARTICLE_GROUP_RELATION`.`ARTICLETITLE` = #articleTitle# AND 
 `ARTICLE_GROUP_RELATION`.`ARTICLEUSER` = #articleUser# 
 </select> 
 <delete id="deleteArticleGroupArticleList" parameterClass="java.util.HashMap" > 
 DELETE FROM `ARTICLE_GROUP_RELATION` 
 WHERE `GROUPID` = #groupId# AND 
 `ARTICLE_GROUP_RELATION`.`ARTICLETITLE` = #articleTitle# AND 
 `ARTICLE_GROUP_RELATION`.`ARTICLEUSER` = #articleUser# 
 </delete>

上面的 getGroupByArticle 为一条根据 Article 查出 Group 的语句,该查询需要将关系表与 Groupe 表 join,返回结果为一个 Group 的列表。同样需要注意的是,在对应的增加 / 删除 / 修改操作中,也需要调用一个 SQL 语句来更新关系表,上面是删除的例子。

类的继承的特殊处理

类的继承关系是一种非常常见的类关系,在一般的应用中都会涉及。一般会将一些公有的属性与方法放在一个父类中,然后不同的子类继承父类。在进行数据库的映射时,对于继承关系可以有两种处理方法。第一种是对于父类并不单独建表与之对应,而是分别对每个子类分别建表与做映射,所有父类的属性都在子类中保存有一份。这种方法的好处是在进行映射时非常简单,与一般类的处理相同,坏处是是并利用类的继承的特点,子类的表中会有大量重复的属性。第二种方法是对于父类建立一张表与之对应,对于每一个子类也单独建立一张表与之对应,但是在子类当中并不保存父类的属性,父类的属性只保存在父类的表当中。对于所有的父类与子类,都采用一套相同的 id,这就是说如果子类的表中有一行 ID 值为 10 的数据,在父类表中也会有一行 ID 值为 10 的数据。这两行数据分别存放子类与父类中的属性值。为了区分具体的值是属于哪个子类,在父类中需要定义一个特殊字段 CLASSKEY,这个字段的值表示该行是属于哪个字段。这种方法也是在很多 O/R mapping 工具中常用的方法,下面将详细讲述这种方法的实现。在下面的这里实现示例中有三个类:Customer(客户),ComanyCustomer(公司客户), PersonCustomer(个人客户)。 Customer 为一个父类,ComanyCustomer 与 PersonCustomer 继承了 Customer。在数据库中对应的有三张表 CUSTOMER, COMPANYCUSTOMER 和 PERSONCUSTOMER。 在下面的实现中,“COM”为 ComanyCustome 类所对应的 Class Keyr,“PERSON”为 PersonCustomer 对应的 Class Key。在进行查询的时候需要将子表与父表相 join,在进行增加 / 删除 / 修改操作的时候,也需要同时更改父类表与子类表,如增加中需要同时调用下面的两条增加语句。


清单 12. 继承关系的实现
<select id="getCompanyCustomerByID" resultMap="getCompanyCustomerResult" 
 parameterClass="string"> 
 SELECT 
 `CUSTOMER`.`NAME` AS `C_NAME`, `COMPANYCUSTOMER`.`ID` 
 AS `C_ID`, `COMPANYCUSTOMER`.`LICENSE` AS `C_ LICENSE` 
 FROM `COMPANYCUSTOMER`, `CUSTOMER` 
 WHERE `COMPANYCUSTOMER`.`ID` = `CUSTOMER`.`ID` AND 
 `CUSTOMER`.`CLASSKEY` = ‘ COM ’ AND 
 `COMPANYCUSTOMER`.`ID` = #id# 
 </select> 

 <insert id="insertCustomer" parameterClass="Customer">  
 INSERT INTO `CUSTOMER` 
 (`CUSTOMER`.`ID`, `CUSTOMER`.`CLASSKEY`, `CUSTOMER`.` NAME `) 
 VALUES ( #id#,  #classKey#,#name#)      
 </insert> 
 <insert id="insertComanyCustomer" parameterClass="ComanyCustomer">  
 INSERT INTO `COMPANYCUSTOMER` 
 (`COMPANYCUSTOMER`.`ID`, `COMPANYCUSTOMER`.` NAME `) 
 VALUES ( #id#,  #license#)      
 </insert> 
 <select id="getClassKeyByID" resultClass="string” parameterClass="string"> 
 SELECT 
 `CUSTOMER`.` CLASSKEY` AS `C_ CLASSKEY` 
 FROM `CUSTOMER` 
 WHERE `CUSTOMER`.`ID` = #id# 
 </select>

继承关系比其他关系复杂的实现是在 java 类也需要做一些特殊的处理,在引用 Customer 类的时候,可以直接引用父类或子类。引用父类时可能指向的是一个 ComanyCustomer 的实例,也可能是一个 PersonalCustomer 的实例。然而在仅仅知道 id 的时候无法判断是哪一个具体的子类,在这个时候,就需要根据 ClassKey 来判读具体是哪一个实例了。首先需要有一个方法获取 ClassKey,然后根据 ClassKey 来调用获取具体子类的语句。


清单 13. 继承关系的 Java 实现
public Customer getCustomerById(String id) 
 { 
 String classKey=(String) sqlSession.queryForObject("getClassKeyByID", id); 
 if(“COM”.equals(classKey)) 
     return (Customer) sqlSession.queryForObject("getCompanyCustomerByID", id); 
   else 
   if(“PERSON”.equals(classKey)) 
     return (Customer) sqlSession.queryForObject("getPersonCustomerByID", id); 
 }

总结

本文介绍了关于 iBatis 开发中常用的映射的实现,由于 iBatis 的所有语句必须靠开发人员生成,上面描述的种种对象关系和给出的实现实例将对开发 iBatis 的应用具有非常大的指导意义。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本书是讲述iBATIS框架的权威著作。书中既详实地介绍了iBATIS的设计理念和基础知识,也讨论了动态SQL、高速缓存、DAD框架等高级主题,还讲解了iBATIS在实际开发中的应用。书的最后给出了一个设计优雅、层次清晰的示例程序JGameStore,该示例涵盖全书的大部分知识点,可以作为iBATIS学习和Web开发的经典案例,非常值得深入研究。 本书既可为广大的开发人员(不仅仅是Web应用程序开发人员)提供指导,也可为架构师的项目决策提供参考。项目经理、数据库管理员、质量保证员与测试员以及系统分析师也能从本书中受益。 目录: 第一部分 介绍 第1章 iBATIS的理念 2 1.1 一个结合了所有优秀思想的混合型解决方案 2 1.1.1 探索iBATIS的根源 3 1.1.2 理解iBATIS的优势 7 1.2 iBATIS适合应用在何处 10 1.2.1 业务对象模型 11 1.2.2 表现层 11 1.2.3 业务逻辑层 12 1.2.4 持久层 13 1.2.5 关系数据库 15 1.3 使用不同类型的数据库 17 1.3.1 应用程序数据库 17 1.3.2 企业数据库 18 1.3.3 私有数据库 19 1.3.4 遗留数据库 20 1.4 iBATIS如何解决数据库的常见问题 20 1.4.1 所有权与控制 20 1.4.2 被多个分散的系统访问 21 1.4.3 复杂的键和关系 21 1.4.4 数据模型的去规范化或过度规范化 22 1.4.5 瘦数据模型 23 1.5 小结 24 第2章 iBATIS是什么 26 2.1 映射SQL语句 27 2.2 iBATIS如何工作 29 2.2.1 iBATIS之于小型、简单系统 30 2.2.2 iBATIS之于大型、企业级系统 31 2.3 为何使用iBATIS 31 2.3.1 简单性 32 2.3.2 生产效率 32 2.3.3 性能 32 2.3.4 关注点分离 33 2.3.5 明确分工 33 2.3.6 可移植性:Java、.NET及其他 33 2.3.7 开源和诚实 33 2.4 何时不该使用iBATIS 34 2.4.1 当永远拥有完全控制权时 34 2.4.2 当应用程序需要完全动态的SQL时 34 2.4.3 当没有使用关系数据库时 35 2.4.4 当iBATIS不起作用时 35 2.5 5分钟内用iBATIS创建应用程序 35 2.5.1 安装数据库 36 2.5.2 编写代码 36 2.5.3 配置iBATIS(预览) 37 2.5.4 构建应用程序 38 2.5.5 运行应用程序 39 2.6 iBATIS未来的发展方向 40 2.6.1 Apache软件基金会 40 2.6.2 更简单、更小且依赖性更少 40 2.6.3 更多的扩展点和插件 41 2.6.4 支持更多的平台和语言 41 2.7 小结 41 第二部分 iBATIS基础知识 第3章 安装和配置iBATIS 44 3.1 获得一份iBATIS发布 45 3.1.1 二进制发布 45 3.1.2 从源代码构建 45 3.2 发布中包含的内容 47 3.3 依赖性 48 3.3.1 针对延迟加载的字节码增强 48 3.3.2 Jakarta Commons数据库连接池 49 3.3.3 分布式高速缓存 49 3.4 将iBATIS添加到应用程序中 49 3.4.1 在独立应用程序中使用iBATIS 50 3.4.2 在Web应用程序中使用iBATIS 50 3.5 iBATIS和JDBC 51 3.5.1 释放JDBC资源 51 3.5.2 SQL注入 51 3.5.3 降低复杂度 52 3.6 配置iBATIS(续) 53 3.6.1 SQL Map配置文件 54 3.6.2 properties元素 55 3.6.3 settings元素 56 3.6.4 typeAlias元素 58 3.6.5 transactionManager元素 60 3.6.6 typeHandler元素 61 3.6.7 sqlMap元素 61 3.7 小结 62 第4章 使用已映射语句 63 4.1 从基础开始 63 4.1.1 创建JavaBean 64 4.1.2 SqlMap API 66 4.1.3 已映射语句的类型 67 4.2 使用select已映射语句 70 4.2.1 使用内联参数(用#做占位符) 70 4.2.2 使用内联参数(用$做占位符) 71 4.2.3 SQL注入简介 72 4.2.4 自动结果映射 73 4.2.5 联结相关数据 74 4.3 映射参数 75 4.3.1 外部参数映射 75 4.3.2 再论内联参数映射 76 4.3.3 基本类型参数 78 4.3.4 JavaBean参数和Map参数 78 4.4 使用内联结果映射和显式结果映射 78 4.4.1 基本类型结果 79 4.4.2 JavaBean结果和Map结果 81 4.5 小结 81 第5章 执行非查询语句 82 5.1 更新数据的基本方法 82 5.1.1 用于非查询SQL语句的SqlMap API 82 5.1.2 非查询已映射语句 83 5.2 插入数据 84 5.2.1 使用内联参数映射 84 5.2.2 使用外部参数映射 85 5.2.3 自动生成的键 86 5.3 更新和删除数据 88 5.3.1 处理并发更新 88 5.3.2 更新或删除子记录 89 5.4 运行批量更新 90 5.5 使用存储过程 91 5.5.1 优缺点分析 92 5.5.2 IN、OUT和INOUT参数 93 5.6 小结 95 第6章 使用高级查询技术 96 6.1 在iBATIS中使用XML 96 6.1.1 XML参数 96 6.1.2 XML结果 98 6.2 用已映射语句关联对象 101 6.2.1 复杂集合 101 6.2.2 延迟加载 104 6.2.3 避免N+1查询问题 105 6.3 继承 107 6.4 其他用途 109 6.4.1 使用语句类型和DDL 109 6.4.2 处理超大型数据集 109 6.5 小结 115 第7章 事务 116 7.1 事务是什么 116 7.1.1 一个简单的银行转账示例 116 7.1.2 理解事务的特性 118 7.2 自动事务 120 7.3 局部事务 121 7.4 全局事务 122 7.4.1 使用主动或被动事务 123 7.4.2 开始、提交以及结束事务 124 7.4.3 我是否需要全局事务 124 7.5 定制事务 125 7.6 事务划界 126 7.6.1 将事务在表现层划界 128 7.6.2 将事务在持久层划界 128 7.6.3 将事务在业务逻辑层划界 128 7.7 小结 129 第8章 使用动态SQL 130 8.1 处理动态WHERE子句条件 130 8.2 熟悉动态标签 132 8.2.1 dynamic标签 134 8.2.2 二元标签 135 8.2.3 一元标签 136 8.2.4 参数标签 137 8.2.5 iterate标签 138 8.3 一个简单而完整的示例 139 8.3.1 定义如何检索和显示数据 140 8.3.2 确定将涉及哪些数据库结构 140 8.3.3 以静态格式编写SQL 141 8.3.4 将动态SQL标签应用到静态SQL上 141 8.4 高级动态SQL技术 142 8.4.1 定义结果数据 142 8.4.2 定义所需的输入 143 8.4.3 以静态格式编写SQL 144 8.4.4 将动态SQL标签应用到静态SQL上 145 8.5 动态SQL的其他替代方案 147 8.5.1 使用Java代码 147 8.5.2 使用存储过程 150 8.5.3 同iBATIS相比较 152 8.6 动态SQL的未来 152 8.6.1 简化的条件标签 152 8.6.2 表达式语言 153 8.7 小结 153 第三部分 真实世界中的iBATIS 第9章 使用高速缓存提高性能 156 9.1 一个简单的iBATIS高速缓存示例 156 9.2 iBATIS高速缓存的理念 157 9.3 理解高速缓存模型 158 9.3.1 type属性 158 9.3.2 readOnly属性 159 9.3.3 serialize属性 159 9.3.4 联合使用readOnly属性和serialize属性 159 9.4 如何使用高速缓存模型中的标签 160 9.4.1 高速缓存的清除 160 9.4.2 设置高速缓存模型实现的特性 163 9.5 高速缓存模型的类型 163 9.5.1 MEMORY 163 9.5.2 LRU 164 9.5.3 FIFO 165 9.5.4 OSCACHE 166 9.5.5 你自己的高速缓存模型 166 9.6 确定高速缓存策略 166 9.6.1 高速缓存只读的长效数据 167 9.6.2 高速缓存可读写数据 169 9.6.3 高速缓存旧的静态数据 170 9.7 小结 172 第10章 iBATIS数据访问对象 173 10.1 隐藏实现细节 173 10.1.1 为何要分离 174 10.1.2 一个简单示例 175 10.2 配置DAO 177 10.2.1 properties元素 177 10.2.2 context元素 178 10.2.3 transactionManager元素 178 10.2.4 DAO元素 182 10.3 配置技巧 183 10.3.1 多个服务器 183 10.3.2 多种数据库方言 184 10.3.3 运行时配置更改 185 10.4 基于SQL Map的DAO实现示例 185 10.4.1 配置iBATIS DAO 186 10.4.2 创建DaoManager实例 187 10.4.3 定义事务管理器 187 10.4.4 加载映射 188 10.4.5 DAO实现编码 191 10.5 小结 193 第11章 DAO使用进阶 194 11.1 不是基于SQLMap的DAO实现 194 11.1.1 Hibernate版本的DAO实现 194 11.1.2 JDBC版本的DAO实现 199 11.2 为其他数据源使用DAO模式 203 11.2.1 示例:为LDAP使用DAO 203 11.2.2 示例:为Web服务使用DAO 208 11.3 使用Spring DAO 209 11.3.1 编写代码 209 11.3.2 为什么使用Spring代替iBATIS 211 11.4 创建自己的DAO层 211 11.4.1 从实现中分离出接口 212 11.4.2 创建一个工厂以解耦 212 11.5 小结 214 第12章 扩展iBATIS 215 12.1 理解可插拔组件的设计 215 12.2 使用自定义类型处理器 217 12.2.1 实现自定义类型处理器 217 12.2.2 创建TypeHandlerCallback 218 12.2.3 注册TypeHandlerCallback以供使用 221 12.3 使用CacheController 222 12.3.1 创建CacheController 223 12.3.2 CacheController的放入、获取以及清除操作 223 12.3.3 注册CacheController以供使用 224 12.4 配置iBATIS不支持的DataSource 224 12.5 定制事务管理 225 12.5.1 理解TransactionConfig接口 226 12.5.2 理解Transaction接口 227 12.6 小结 228 第四部分 iBATIS使用秘诀 第13章 iBATIS最佳实践 230 13.1 iBATIS中的单元测试 230 13.1.1 对映射层进行单元测试 231 13.1.2 对DAO进行单元测试 233 13.1.3 对DAO的消费层进行单元测试 235 13.2 管理iBATIS配置文件 237 13.2.1 将其保存在类路径上 237 13.2.2 集中放置文件 238 13.2.3 主要按返回类型来组织映射文件 239 13.3 命名规范 239 13.3.1 语句的命名 239 13.3.2 参数映射的命名 239 13.3.3 结果映射的命名 240 13.3.4 XML文件的命名 240 13.4 Bean、map还是XML 240 13.4.1 JavaBean 241 13.4.2 Map 241 13.4.3 XML 241 13.4.4 基本类型 241 13.5 小结 241 第14章 综合案例研究 243 14.1 设计理念 243 14.1.1 账户 243 14.1.2 目录 244 14.1.3 购物车 244 14.1.4 订单 244 14.2 选择具体的实现技术 244 14.2.1 表现层 244 14.2.2 服务层 244 14.2.3 持久层 245 14.3 调整Struts:使用BeanAction 245 14.3.1 BaseBean 246 14.3.2 BeanAction 246 14.3.3 ActionContext 246 14.4 JGameStore工程结构 247 14.4.1 src文件夹 247 14.4.2 test文件夹 248 14.4.3 web文件夹 248 14.4.4 build文件夹 248 14.4.5 devlib文件夹 248 14.4.6 lib文件夹 249 14.5 配置web.xml文件 249 14.6 设置表现层 251 14.6.1 第一步 251 14.6.2 使用表现层bean 253 14.7 编写服务层代码 257 14.7.1 配置dao.xml文件 258 14.7.2 事务划界 259 14.8 编写DAO 260 14.8.1 SQLMap配置 260 14.8.2 SQLMap文件 261 14.8.3 接口和实现 262 14.9 小结 263 附录A iBATIS.NET快速入门 264 A.1 比较iBATISiBATIS.NET 264 A.1.1 为何Java开发人员应该关心iBATIS.NET 264 A.1.2 为何.NET开发人员应该关心iBATIS.NET 265 A.1.3 主要区别是什么 265 A.1.4 相似之处又在哪里 265 A.2 使用iBATIS.NET 265 A.2.1 DLL和依赖性 265 A.2.2 XML配置文件 266 A.2.3 配置API 267 A.2.4 SQL映射文件 267 A.3 到哪里去查找更多的信息 269
iBATIS(现在已更名为MyBatis)是一个开源的持久化框架,用于将数据库操作与应用程序中的对象进行映射。它提供了一种简单而灵活的方式来执行数据库操作,而无需编写复杂的SQL语句。 iBATIS的主要目标是将数据库操作与应用程序解耦,使开发人员能够专注于业务逻辑而不必过多关注数据库细节。它采用了一种称为"对象关系映射"(Object-Relational Mapping,ORM)的技术,将数据库表和Java对象之间的映射定义在XML配置文件中。 使用iBATIS,开发人员可以通过简单的配置文件来定义SQL语句,并将SQL语句与Java对象进行映射。这样,开发人员可以使用面向对象的方式来进行数据库操作,而不必直接编写SQL语句。 以下是iBATIS的一些主要特点: 1. 简单易用:iBATIS提供了简单而直观的API,使得开发人员能够轻松地执行各种数据库操作。通过使用XML配置文件,可以将SQL语句与Java对象进行映射,从而实现数据库操作的简化。 2. 灵活性:iBATIS允许开发人员编写自定义的SQL语句,以满足各种复杂的数据库操作需求。它支持动态SQL,使得可以根据不同的条件来构建SQL语句,从而提供更大的灵活性。 3. 良好的性能:iBATIS通过使用预编译的SQL语句和缓存机制来提高数据库操作的性能。它可以缓存已执行的SQL语句和查询结果,以减少数据库访问的次数,从而提高应用程序的性能。 4. 易于调试:iBATIS提供了详细的日志功能,可以记录所有执行的SQL语句和参数,方便开发人员进行调试和排查问题。 iBATIS(MyBatis)在Java应用程序中被广泛使用,特别适用于需要对数据库进行精确控制和优化的项目。它提供了一种轻量级而灵活的方式来处理数据库操作,简化了开发人员与数据库之间的交互过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值