iBATIS系统学习笔记二

目录:
学习笔记零 - 起源
学习笔记一 - 概念与入门
学习笔记三 - 高级技巧与进阶
学习笔记四 - 技巧与实践


iBATIS基础知识

安装和配置iBATIS

内容
- 获取iBATIS
- iBATIS和JDBC
- iBATIS配置基础

1 iBATIS的依赖性

iBATIS的一些特效需要依赖包才能使用。

1.1针对延迟加载的字节码增强

字节码增强是一种可以根据你所定义的配置活其他规则在运行时修改代码的技术。
iBATIS允许将某些SQL查询和其他一些SQL查询关联起来。这点很像O/RM工具,iBATIS的优势在于更加灵活,能够达到多个数据库查询的效果。
如果你有1000个客户,每个客户都有1000个订单,同时每个订单都有25个订单项,那么合并后将需要25,000,000个对象,显然这个订单项的数据太大了,根本不可能同时把它们全部加载到内存中。
我们可以重新配置SQL映射以便加载那些关联列表。这样一来,当用户查看客户列表时,只有这1000个客户对象会保存在内容中,加载其他列表所需的信息始终可用,但是直到实际需要这些数据时菜真正加载。也就是说,订单信息不是一开始就被加载,只有等到用户单击某个客户查看订单时才加载。同理,当用户单击某个订单时,选中的25个订单才会加载。
只需要更改配置,不需要修改代码的情况下,就能完成这个修改。

1.2 Jakarta Commons数据库连接池

iBATIS是一个用于简化应用程序与数据库交互的工具,所以很明显应用程序必须连接到某个数据库。按需创建新的连接是非常耗时的,因此iBATIS不使用这个方法,而是使用一个连接池,连接池始终处于连接状态并且可以为应用程序的所有用户共享。
很多软件开发商所提供的驱动程序都有支持链接池化版本,但是存在一个问题,即这些连接池的特性和配置同它们的实现一样各不相同。
而Jakarta Commons Database Connection Pool(DBCP)项目正是用于解决以上问题,他是一个包装器(wrapper),可以使我们轻松地使用任意的JDBC驱动程序作为连接池的一部分。

1.3 分布式高速缓存

iBATIS提供了一个使用OpenSymphony cache(OSCache)的告诉缓存实现方案。OSCache可被配置为夸多服务器集群以提供可伸缩性和错误恢复支持。


2 将iBATIS添加到应用程序中

首先需要将iBATIS的配置文件加入应用程序的编译时和运行时的类路径中。

2.1 加入小程序中

java -cp ibatis-sqlmap-2.jar: ibatis-common-2.jar:. MyMainClass

2.2 在Web应用程序中使用iBATIS

放入lib中。
这些显然不够现在的需求,待补充


3 iBATIS和JDBC

Sun公司的JDBC API是Java编程语言中的数据库连接标准。在没有使用iBATIS的情况下,使用JDBC需要注意以下几点

3.1 释放JDBC资源

3.2 SQL注入

使用JDBC的PreparedStatement能有效的防止SQL注入攻击。
在使用iBATIS的时候,当使用显式SQL字符串来替换语法的语句具有这样风险,比如:

SELECT * FROM $TABLE_NAME$ WHERE $ COLUMN_NAME$ = #value#

3.3 降低复杂度

使用JDBC时那些繁琐的步骤可以通过iBATIS去除


4 配置iBATIS

iBATIS的配置概念图
概念配置

SqlMapConfig位于最上方,我们在此文件定义那些全局配置选项以及对各个独立SqlMap文件的引用。
SqlMap文件则用于定义那些已映射语句,这些已映射语句结合应用程序提供的输入来完成数据库的交互。

4.1 SQL Map配置文件

即SqlMapConfig.xml文件,是iBATIS配置的核心。所以东西都是通过此文件中的配置提供给框架。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
    <properties resource="db.properties" />
    <!-- 全局配置选项 -->
    <settings
     useStatementNamespaces="false"
     cacheModelsEnabled="true"
     enhancementEnabled="true" 
     lazyLoadingEnabled="true" 
     maxRequests="32" 
     maxSessions="10" 
     maxTransactions="5"/>

    <!-- 事务管理器 -->
    <transactionManager type="JDBC" >
        <dataSource type="SIMPLE">
            <property name="JDBC.Driver" value="${driver}"/>
            <property name="JDBC.ConnectionURL" value="${url}"/>
            <property name="JDBC.Username" value="${user}"/>
            <property name="JDBC.Password" value="${pword}"/>
        </dataSource>
    </transactionManager>

    <!-- 对各个Sql Map文件的引用 -->
    <sqlMap resource="org/apache/mapper2/ii15/SqlMap.xml" />
</sqlMapConfig>

4.2 properties元素

<properties>元素允许在主配置文件之外提供一个名/值对列表,从而使得主配置文件更加通用。
可以使用两种方式来指定所用的属性文件,每种方式对应 <properties>元素的一个属性。分别为:
1. resource — 类路径上的一个资源(或文件)。
2. url — 同意资源定位符(uniform resource locator)。

resource属性是由类加载器来读取,Java文档也会以这种方式访问数据时引用这些资源。
url属性是用java.net.URL类来处理,这个属性的取值可以使该类能理解并用于加载数据的任何有效的URL

4.3 settings元素

<settings>元素就好像是装满了配置选项的摸彩袋,可以通过为 <settings>元素添加若干属性来设置这些可选项。iBATIS有许多配置项可以用,并且每个配置项对这个SQL Map实例来说都是全局的。
1. lazyLoadingEnabled — 延迟加载,只加载必要信息而推迟加载其他未明确请求的数据的技术。lazyLoadingEnabled 配置项用于指定当存在相关联的已映射语句时,是否使用延迟加载。有效值是true或false,默认值是true。
2. cacheModelsEnabled — 数据告诉缓存是一种用于提高程序性能的技术,它基于近期使用过的数据往往很快又会被用到这样一种假设,将近期使用过的数据保存在内存中。cacheModelsEnabled 配置项用于指定是否想让iBATIS使用该技术。有效值也是ture和false并且默认值为true。为了充分利用高速缓存技术,还必须为已映射语句配置高速缓存模型。
3. enhancementEnabled — enhancementEnabled配置项用于指定是否使用cglib中那些已优化的类来提高延迟加载的性能,有效值为true或false,默认值为true。(属于增强型框架,除非确实需要,劲量避免使用。)
4. useStatementNamespaces — useStatementNamespaces 配置项用于告诉iBATIS,在引用已映射语句时,是否需要使用限定名。默认false。举例说明,如果有一个名为Account 的SQL映射,它包含名为insert、update、delete以及getAll的已映射语句,当已启用此配置项时,就必须用Account.insert这个名字来调用这条已映射语句。(这样就通过命名空间,不会造成名字冲突)
5. maxRequests、maxSessions、maxTransactions — 这三种以及被废弃,默认即可用,如果一定要进行修改,需要确保maxRequests大于maxSessions,maxSessions大于maxTransactions,并保证比例相同。另需要注意,这个3个配置项没有一个会对连接池中的连接数或应用程序服务器负责管理的那些资源产生实际影响。

4.4 typeAlias元素

元素允许定义别名:

<typeAlias alias = "Account" type = "org.apache.ibatis.jgamestor.domin.Account" />

经过配置后,可以直接使用Account这样的别名来给出iBATIS需要的数据。
iBATIS框架定义了许多别名:
1. 事物管理器别名 — JDBC, JTA, EXTERNAL
2. 数据类型 — string,byte,long,short,int,integer,double,float,boolean,date,decimal,object,map,hashmap,list,arraylist,collection,iterator
3. 数据源工厂类型 — SIMPE, DBCP, JNDI
4. 告诉缓存控制器类型 — FIFO, LRU, MEMORY, OSCACHE
5. XML结果类型 — Dom, domCollection, Xml, XmlCollection
别名可以省去大量的时间简化类名的输入。

4.5 transactionManager元素

iBATIS提供了若干内建事务管理器实现:

名字 描述
JDBC 用于提供简单的基于JDBC的事物管理,大多数情况下,使用这个事物管理器就足够了
JTA 用于在你的应用程序中提供基于容器的事物管理
EXTERNAL 用于提供非事物管理,并假定管理事物的是应用程序,而不是iBATIS

对于事务管理器,另一个可用的设置就是commitRequired属性,该属性默认为false,主要用于那些要求在释放某个连接之前必须commit或者rollback的情况。

对于某些操作(选择或者存储过程调用),通常并不需要事物,因此一般将其忽略。某些数据库驱动程序(例如Sybase)不会轻易释放连接,直至该连接的每个已启动事物都已提交或回退。在这些情况下,就可以使用commitRequired属性来强制释放连接,即使在那些通常需要在一个事物中释放却没有释放的情况。
1. <property>元素 — 每个事物管理器都可以有不同的配置项。因此iBATIS框架允许使用此标签元素来指定任意数目的名值对以提供给相应的事务管理器实现类
2. <dataSource>元素 — 在Java中,使用连接池的标准方法就是通过javax.sql.DataSource对象。事务管理器的 元素有一个类型属性,用来告诉iBATIS它应该为其数据源工厂实例化并使用哪个类。实际上元素并不是用来定义DataSource,而是用来定义DataSourceFactory实现类,然后iBATIS将用这个实现类来创建实际的DataSource。

iBATIS具有3中数据源工厂的实现类,简单描述如下:

名字 描述
SIMPLE 简单的数据源工厂,用于配置内置有简单连接池的数据源,使用iBATIS框架与JDBC实现
DBCP DBCP数据源工厂使用Jakarta Commons数据库连接池实现
JNDI JNDI数据源工厂用于允许iBATIS共享通过JNDI定位的基于容器的数据源

4.6 typeHandler元素

iBATIS使用类型处理器将数据从数据库特定的数据类型转换为应用程序中的数据类型。类型树立起本质上就是一个翻译器,它将数据库返回的结果集合中的列“翻译”为相应的Java Bean中的字段。
例如数据库没有布尔数据类型,因此在数据库往往使用单个字符Y或N来表示真假。为处理这种情况,需要创建两个类:一个自定义类型处理器和一个类型处理器回调类。
大部分情况下(原文甚至用了99%)都不需要编写自定义类型处理器,如果需要的话,可以通过元素并告诉iBATIS它需要在两个类型jdbcTypejavaType之间转换哪些元素。此外,还需要回调类来管理类型处理器。

4.7 SqlMap元素

元素也是使用resource属性或者url属性,来设置sqlMap的位置。


使用已映射语句

内容
- JavaBean
- iBATIS API
- 已映射语句
- 使用参数映射和结果映射


1 从基础开始

iBATIS并不是一个O/RM工具,他只是一种查询映射工具。

1.1 创建JavaBean

bean的构成
本质上而言,JavaBean规范就是一组规则,用于定义java开发可使用的组件。规范可以看做框架开发人员和应用开发人员的一个中间层公共语言。
iBATIS对于应用javaBean的唯一规则是对于特性命名。在JavaBean中,特性名由一对方法定义,这对方法即规范中所谓的存取方法(accessor method)比如以下value的特性创建的存取方法:

public void setValue(ValueType new value);
public ValueType getValue();

这一对存取方法定义了以小写v开头的名为value的简单特性。
boolean类型的特性允许获取方法是用isProperty,如果是包装类型Boolean则必须使用get。

特性名 获取方法 设置方法
xcoordinate/Double getXcoordinate() setXcoordinate(Double v)
xCoordinate/Double getxCoordinate() setxCoordinate(Double v)
XCoordinate/Double getXCoordinate() setXCoordinate(Double v)
Xcoordinate/Double Not allowed Not allowed
student/Boolean getStudent() setStudent(Boolean b)
student/boolean getStudent()
isStudent()
setStudent(boolean b)

已索引特性,即代表值数组的特性:

public void setOrderItem(OrderItem[] newArray);
public OrderItem[] getOrderItem();
public void setOrderItem(int index, OrderItem oi);
public OrderItem getOrderItem(int index);

显然,两个重载方法的区别不明显
这里推荐2个iBATIS的bean写法:

public void setOrderItemArray(OrderItem[] newArray);
public OrderItem[] getOrderItemArray();
public void setOrderItem(int index, OrderItem oi);
public OrderItem getOrderItem(int index);
public BeanType setProperty(PropType newValue){
    this.property = newValue;
    return this;
};
myBean.setProperty(x).setSomeProperty(y);

bean导航

可以通过点记法 引用特性:

Java代码 点记法
anOrder.getAccount(),getUsername() anOrder.account.username
anOrder.getOrderItem().get(0).getProductId anOrder.orderItem[0].producId
anObject.getID() anObject.ID
anObject.getxCoordinae() anObject.xCoordinate

使用Java的Introspector类来获取javabean索引特性:

 public void listPropertyNames(Class c)
            throws IntrospectionException {
        PropertyDescriptor[] pd;
        pd = Introspector.getBeanInfo(c).getPropertyDescriptors();
        for(int i=0; i< pd.length; i++) {
            System.out.println(pd[i].getName()
                    + " (" + pd[i].getPropertyType().getName() + ")");
        }
    }

>> output:
>class (java.lang.Class)
>classname (java.lang.String)
>count (java.lang.Integer)
>psd (java.lang.String)
>sgn (int)

1.2 SqlMap API

SqlMapClient 的接口具备的方法超过30个,在此简单介绍:

  1. queryForObject()
    queryForObject() 的方法是用于从数据库取出一条记录,并把它放入到一个java对象中。他具备2种签名:
 Object queryForObject(String id, Object parameter) throws SQLException;
Object queryForObject(String id, Object parameter, Object result) throws SQLException;

第二种签名接受一个将被用作返回值的对象 — 运行已映射语句之后,该方法并不会创建一个新的对象,而是会修改这个特性。如果请求的对象不能轻创建那就使用这个方式
需要注意的是,如果返回不止一行,那么这个方法就会抛出异常。

2.queryForList()
queryForList() 从数据库中获取一行或多行。

List queryForList(String id, Object parameter) throws SQLException;
List queryForList(String id, Object parameter, int skip, int max)
throws SQLException;

第二个版本返回其中一部分,他将跳到skip参数指定的位置上,并返回从查询结果开始的max行。比如有8条满足结果的数据,当skip = 5 ,max = 5时,则只会返回最后三条数据(不包括第五条)。

3.queryForMap()
queryForMap() 是从数据库中返回一行或多行组成的Java Map。

Map queryForMap(String id, Object parameter, String key) throws SQLException; Map queryForMap(String id, Object parameter, String key, String value)
throws SQLException;

第一个方法返回一组java对象,其中这些对象的键值由key参数所指定的特性来表示,值为返回对象。
第二个方法返回的对象时value参数所标识的对象的特性
这里有些难以理解,举例说明:
JavaBean:

public class UserAccount {
   
    int userId;
    String userName;
    String password;
    String groupName;
    //Set and get
}

SqlMap:

<sqlMap>
    <select id="getAll" resultClass="UserAccount">
        SELECT * FROM USER_ACCOUNT
    </select>
</sqlMap>

运行代码:

Map accountMap = sqlMapClient.queryForMap("getAll", null, "userId");
System.out.println(accountMap);
accountMap = sqlMapClient.queryForMap(
         "getAll",
         null,
         "userId",
         "userName");
System.out.println(accountMap);

output:
>>{
  1=com.alan.myvaadin.pojo.UserAccount@11ddcde, 2=com.alan.myvaadin.pojo.UserAccount@18fb1f7, 3=com.alan.myvaadin.pojo.UserAccount@ed0338, 4=com.alan.myvaadin.pojo.UserAccount@6e70c7, 5=com.alan.myvaadin.pojo.UserAccount@ae506e, 6=com.alan.myvaadin.pojo.UserAccount@228a02, 7=com.alan.myvaadin.pojo.UserAccount@192b996, 8=com.alan.myvaadin.pojo.UserAccount@1d63e39, 9=com.alan.myvaadin.pojo.UserAccount@8f4fb3, 10=com.alan.myvaadin.pojo.UserAccount@b988a6}
{
  1=ALAN, 2=MILU, 3=MIKE, 4=JESSIE, 5=BOOK, 6=TONY, 7=LARRY, 8=FANCY, 9=ALLEN, 10=DADY}

1.3 已映射语句的类型

已映射语句的类型和相关XML元素:

语句 属性 子元素 用途
<select> id
parameterClass
resuletClass
parameterMap
resultMap
cacheModel
所有动态元素 用于选择数据
<insert> id
parameterClass
parameterMap
所有动态元素
selectKey
用于插入数据
<update>/<delete> id
parameterClass
parameterMap
所有动态元素 用于更新/删除
<procedure> id
parameterClass
resuletClass
parameterMap
resultMap
xmlResultName
所有动态元素 用于调用存储过程
<statement> id
parameterClass
resuletClass
parameterMap
resultMap
xmlResultName
所有动态元素 可用来代表所有语句类型,
几乎可以用来执行所有的操作
<sql> id 所有动态元素 非已映射语句,可用来创建用于已映射语句的组件
<include> refid 用于将使用<sql>类型所创建的组件插入到已映射语句中。

<sql>元素和<include>元素,用来创建已映射语句的元素。联合使用这两个元素能够创建可插入到已映射语句中的组件。

<sql>元素用于创建一个文本片段,这些片段又可以组合起来以创建完整的SQL语句。例如:

<sql id="select-order">
    select * from order
</sql>
<sql id="select-count">
    select count(*) as value from order
</sql>
<sql id="where-shipped-after-value">
    <![CDATA[
    where shipDate > #value:DATE#
    ]]>
</sql>
<select id=
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值