ibatis基础配置:
<sqlMapConfig>
<properties resource="db.properties"/>
<settings
useStatementNamespaces="false"
cacheModelEnabled="true"
enhancementEnabled="true"
lazyLoadEnabled="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>
<sqlMap resources="org/apache/mapper2/ii15/SqlMap.xml"/>
</sqlMapConfig>
第4章:使用已映射语句
Object queryForObject(String id, Object parameter);
Object queryForObject(String id, Object parameter, Object result);
如果数据库返回了不止一行就会抛出异常
List queryForList(String id, Object parameter);
List queryForList(String id, Object parameter, int skip, int max);
Map queryForMap(String id, Object parameter, String key)
Map queryForMap(String id, Object parameter, String key, String value)
返回一行或多行数据,key、value为bean的某个属性
已映射语句的类型和相关XML元素
<select>、<insert>、<update>、<delete>、<sql>、<include>、<procedure>、<statement>
<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="getOrderShippedAfter" resultClass="map"> sql include*******************************************
<include refid="select-order"/>
<include refid="where-shipped-after-value"/>
</select>
<select id="getOrderCountShippedAfter" resultClass="int">
<include refid="select-count"/>
<include refid="where-shipped-after-value"/>
</select>
参数映射:内联参数、
结果映射:
参数映射
使用内联参数(用#做占位符)
<select id="getByIdValue" resultClass="Account">
select
accountId, userName from Account where accountId = #value#
</select>
account = (Account)sqlMap.queryForObject("cds.getByIdValue", new Integer(1));
使用内联参数所带来的疑问:如何在where子句中使用like?
1、在所传入的参数中使用SQL通配符。
2、要搜索内容的文本必须是能够被参数化的SQL表达式的一部分;如:'%'||#value#||'%'。
3、改为使用替代语法(用$做占位符)。
使用内联参数(用$做占位符)
它可以用来把值直接插入到SQL语句之中(在该SQL语句被转变为参数化语句之前);
但使用这种方式时要非常小心,因为它可能使你暴漏给SQL注入,另外过度使用还可能造成性能问题;
<select id="getByLikeCity" resultClass="Account">
select * from Account where city like '%$value$%'
</select>
结果映射
自动结果映射
可以有3种方式来使用这个特征:单列选择(as value)、固定多列选择和动态多列选择。
动态多列:<dynamic>
如果你既没有提供结果映射,也没有提供结果类,ibatis将执行你的语句但是却不返回任何东西
如果所选择的列在数据库中存在,但是不存在于你要映射的bean中,你将不会得到任何错误或警告,但是也得不到任何数据;
如果映射中存在某列,但数据库中不存在,将会报异常
如果只想从某个查询中获取单列,就可以使用别名value作为一种快捷方式来完成此目的,
这样就可以不需要定义复杂的结果映射了。
<select id="getAllAccountIdValues" resultClass="int">
select accountId as value from Account
</select>
联结相关数据
多表联结
映射参数:内联参数(##、$vlaue$)
外部参数映射
参数映射的属性:property、javaType、jdbcType、nullValue、mode、typeHandler。 typeHandler***************************************************************
结果映射属性:property、column、columnIndex、javaType、jdbcType、nullValue、select;
nullvalue:设定一个参数时,nullValue属性可以根据特性类型被设置为任何有效的值;
用来指定外发的空值替换:数据库写入时,如果在待写入的javabean属性或map键值对中检测到该替换值,就将空值写入到数据库,
从数据库读出一个空值时,则将相应的javabean字段或map键值对的值设为该替换值。
<select id="getOrderShippeAfter" returnClass="java.util.HashMap">
select * from order where shipDate > #value:DATE#
</select>
<select id="getOrderShippeAfter" returnClass="java.util.HashMap">
select * from order where shipDate > #value,jdbcType=DATE#
</select>
内联结果映射、显式结果映射
内联结果映射非常容易使用,并且在绝大多数的情况下都能很顺利地完成工作;
显式结果映射则可以提供更好的性能、更严格的配置,以及更加精确的行为;
显式结果映射属性:property、column、columnIndex、javaType、jdbcType、nullValue、select;
当你的数据库中包含允许为空的列时,数据库类型(jdbcType)通常是必需设置的,即向DB中显式地插入null;
在xml中"<"做好使用<,<![CDATA[...]]>也可以,但是同时使用动态sql和CDATA时要特别小心,
因为CDATA中的动态sql标签将不会被解析。
java基本类型:boolean、byte、char、short、int、long、float、double;
java1.4环境下,只能传递基本类型的包装类型参数,但java5可以传递基本类型参数,因为java5会自动装箱。结果类型也是一样的。
ibatis不允许你直接获得基本类型的结果,但是它允许你获得基本类型的包装结果:
<select id="getOrderCountByAccount"
resultClass="java.lang.Integer">
select count(*) as value from order where accountId = #value#
</select>
Integer count = (Integer)sqlMap.queryForObject("Account.getOrderCountByAccount");
<select id="getPrimitiveById"
resultMap="primitiveResultMapExample">
select count(*) as orderCount from order where accountId = #accountId#
</select>
<resultMap id="primitiveResultMapExample"
class="PrimitiveResult">
<result property="orderCount" column="orderCount"/>
</resultMap>
public class PrimitiveResult{
private int orderCount;
public int getOrderCount(){}
public void setOrderCount(){}
}
********************************************************************
第5章:执行非查询语句
用于非查询SQL语句的SqlMap API
Object insert(String id, Object parameterObject)throws SQLException;
int update(String id, Object parameterObject)throws SQLException;
int delete(String id, Object parameterObject)throws SQLException;
用于更新数据的已映射语句类型:insert、update、delete、procedure、sql、include;
insert:id、parameterClass、parameterMap
delete:id、parameterClass、parameterMap
update:id、parameterClass、parameterMap
procedure:id、parameterClass、parameterMap、resultClass、resultMap、xmlResultName
sql:id
include:refid
插入数据:
使用内联参数映射:
<insert id="insertWithInlineInfo">
insert into account(accountId, username, password, memberSince, firsetName, lastName)
values(#accountId:NUMBER#, #username:VARCHAR#, #password:VARCHAR#, ...)
</insert>
sqlMapClient.insert("Account.insertWithInlineInfo", account);
使用外部参数映射
<parameterMap id="fullParameterMapExample" class="Account">
<parameter property="accountId" jdbcType="NUMBER">
<parameter property="username" jdbcType="VARCHAR">
</parameterMap>
<insert id="insertWithExternalInfo"
parameterMap="fullParameterMapExample">
insert into account(accountId, username, password)
values(?,?,?,?,?,?,...)
</insert>
自动生成的键
如果你将数据库设计为使用自动生成的主键,就可以使用ibatis的<selectKey>元素
(该元素是<insert>元素的一个专用子元素)来获取这些自动生成的主键的值并将其
保存在对象中。完成这项工作可以有两种方式,具体选择何种方式由你所使用的具体
的主键生成技术来确定。
第一种方式是,当你把记录插入到数据库中并且数据库为该记录自动生成了主键值之后,
就立即抓取该键值。须注意多线程并行执行时的问题。
第二种方式是,在插入记录之前就获取键值。通常是最安全的方式。
<insert id="insert">
<selectKey keyProperty="accountId" resultClass="int">
select nextVal('account_accountid_seq')
</selectKey>
insert into account(accountId, username, password)values(#accountId#, #username#, #password#)
</inser>
Integer returnValue = (Integer)sqlMap.insert("account.insert", account);
返回值returnValue即为主键,其实执行完insert语句,account对象的主键已经不为空了
更新和删除数据:
ibatis目前还没有实现的一个功能是:为记录提供某种形式的锁,以对相同数据的并发修改进行管理。
不过你仍可以使用若干技术来处理并发更新,例如使用时间戳或者为数据库表中的每条记录加一个版本号。
更新或删除子记录:
由于ibatis框架从根本上说就是一个SQL映射工具,因此它在更新数据库时并不管理对象间的这些关系。所有,你必须在应用程序的数据层而不是在
ibatis中处理对象关系。
运行批量更新:
使用批处理语句的一个重要技巧是:将这些批处理语句打包成一个事务。如果没有这么做,那么每条语句都会开始一个新的事务,这样一来随着批处理语句
规模的增长,性能将会受到严重的影响;
sqlMapClient.startBatch();
sqlMapClient.executeBatch();
sqlMapClient.startTransaction();
sqlMapClient.commitTransaction();
sqlMapClient.endTransaction();
public void saveOrder(SqlMapClient sqlMapClient, Order order)throws SQLException{
sqlMapClient.startTransaction();
try{
if(order.getOrderId == null){
sqlMapClient.insert("Order.insert", order);
}else{
sqlMapClient.update("Order.update", order);
}
sqlMapClient.startBatch();
sqlMapClient.delete("Order.deleteDetails", order);
for(int i=0; i<order.getOrderItems().size; i++){
OrderItem oi = (OrderItem)order.getOrderItems().get(i);
oi.setOrderId(order.getOrderId()); //error
sqlMapClient.insert("OrderItem.insert", oi);
}
sqlMapClient.executeBatch();
sqlMapClient.commitTransaction();
}finally{
sqlMapClient.endTransaction();
}
}
当使用批处理语句时,直到调用executeBatch()方法执行这批批处理语句,数据库生成键才会被产生。
简单地说,这意味着如果你使用selectKey语句来更新所插入对象的系统生成键,那么它们将为所生成
的键返回空值,因此事情并不会像你预期的那样,所以如果可以,用存储过程代替批处理。
使用存储过程:
**************************************************************************************
第6章:使用高级查询技术
使用xml;
用已映射语句关联对象; resultMap》result》select*****************************************************
假设你有一个数据库,其中Account记录和Order记录存在关联,而Order记录又关联OrderItem记录,建立起这些关联关系之后,请求Account记录时,
就会同时获得所有关联的Order对象以及OrderItem对象。如下sql映射以完成这项任务:会产生N+1问题
AccountInfo(OrderInfo(OrderItem))
AccountInfo(accountId)
OrderInfo(orderId, accountId)
OrderItem(orderItemId, orderId)
<sqlMap namespace="Ch6">
<resultMap id="ResultAccountInfoMap" class="org.apache.mapper2.examples.bean.AccountInfo">
<result property="account.accountId" column="accountId"/>
<result property="orderList" select="Ch6.getOrderInfoList" column="accountId"/>
</resultMap>
<resultMap id="ResultOrderInfoMap" class="org.apache.mapper2.examples.bean.OrderInfo">
<result property="order.orderId" column="orderId"/>
<result property="orderItemList" select="Ch6.getOrderItemList" column="orderId"/>
</resultMap>
<resultMap id="ResultOrderItemMap" class="org.apache.mapper2.examples.bean.OrderItem">
<result property="orderId" column="orderId"/>
<result property="orderItemId" column="orderItemId"/>
</resultMap>
<select id="getAccountInfoList" resultMap="ResultAccountInfoMap">
select accountId from Account
</select>
<select id="getOrderInfoList" resultMap="ResultOrderInfoMap">
select orderId from orders where accountId=#value#
</select>
<select id="getOrderItemList" resultMap="ResultOrderItemMap">
select orderId, orderItemId from orderItem where orderid = #value#
</select>
</slqMap>
数据库I/O 问题
数据库I/O可以很好地度量你的数据库的使用情况,同时也是影响数据库性能的主要瓶颈之一。
N+1查询 问题
如果执行一个查询语句并获取N条父记录,那么为了获得所有这些父记录的子记录,你就必需再
执行N个查询。
这些问题的解决方案
解决N+1问题,可以通过一条sql把所有记录加载到内存,到必然导致数据库I/O问题。数据库I/O问题,N+1问题,必有其一。
通过延迟加载解决数据库I/O问题,通过ibatis提供的groupBy属性,或RowHandler的自定义组件解决N+1问题。
其实质是通过连接的形式,将几条sql整合成一条sql。
延迟加载:解决数据库I/O问题
SqlMapConfig.xml
lazyLoadingEnabled=true;
延迟加载cglib增强版:enhancementEnabled=true
<resultMap id="ResultAccountInfoNMap" class="AccountInfo" groupBy="account.accountId"> resultMap》result》resultMap*****************************************************
<result property="account.accountId" column="accountId"/>
<result property="orderList" resultMap="ch6.ResultOrderInfoNMap"/>
</resultMap>
<resultMap id="ResultOrderInfoNMap" class="OrderInfo" groupBy="order.orderId">
<result property="order.orderId" column="orderId"/>
<result property="orderItemList" resultMap="ch6.ResultOrderItemNMap"/>
</resultMap>
<resultMap id="resultOrderItemNMap" class="OrderItem">
<result preoperty="orderId" column="orderId"/>
<result property="orderItemId" column="orderItemId"/>
</resultMap>
<select id="getAccountInfoListN" resultMap="resultAccountInfoNMap">
select account.accountId as accountId,
orders.orderid as orderId,
orderitem.orderitemid as orderItemId
from account join orders on account.accountId = orders.accountId
join orderitem on orders.orderId = orderitem.orderId
ordery by accountId, orderId, orderItemId
</select>
继承 resultMap》discriminator》subMap************************************
ibatis通过使用一个特殊的被称为鉴别器(discriminator)的结果映射来支持继承体系。
使用鉴别器你就可以根据数据库中某列的值来确定要实例化的类的类型。
它和switch的工作原理很相似;
<resultMap id="document" class="testdomin.Document">
<result property="id" column="DOCUMENT_ID"/>
<result property="title" column="TITLE"/>
<result property="type" column="TYPE"/>
<discriminator column="TYPE" javaType="String">
<subMap value="Book" resultMap="book"/>
<subMap value="Newspaper" resultMap="news"/>
</discriminator>
</resultMap>
如果TYPE列取值为Book,那么就使用名为book的结果映射;否则,如果TYPE取值为Newspaper,那么就使用名为news的结果映射。
<resultMap id="book" class="testdomain.Book" extends="document">
<result property="pages" column="DOCUMENT_PAGENUMBER"/>
</resultMap>
ibatis框架的设计意图就是要灵活,当无法使用其他类型的已映射语句时,也许就可以使用<statement>已映射语句。
虽然ibatis并没有正式支持DDL,但是数据库可能会允许你通过ibatis的<statement>类型来执行DDL语句。
<statement id="dropTable">
DROP TABLE Account CASCADE
</statement>
sqlMap.update("Account.dropTable", null);
处理超大型数据集 处理大数据集**************************************
RowHandler接口是一个非常简单的接口,它允许你在某个已映射语句的结果集的处理中插入自己的动作。
public interface RowHandler{
void handleRow(Object valueObject);
}
**************************************************************************************
第7章:事务 transactionManager***********************************************
<transactionManager type="jdbc">
<dataSource type="simple">
<property .../>
</dataSource>
</transactionManager>
sqlMapClient.startTransaction
sqlMapClient.commitTransaction
sqlMapClient.endTransaction
ibatis支持的4种范围的事务:
1、自动事务:只涉及一条语句,这种事务不需要显式地划定事务边界,每一条sql都是一个独立的事务;
2、局部事务:只涉及一个数据库,需显式调用;
3、全局事务:涉及多语句和不止一个数据库;
4、定制事务:由用户管理事务,获取connection,事务完全控制权;
有两种法人给sqlMapClient传递一个connection:
1、sqlMapClient.setUserConnection(dataSource.getConnection());
2、session = sqlMapClient.openSession(dataSource.getConnection());
事务的特性:
原子性:或者全部成功,或者全部失败;
一致性:所有的约束都得到满足;
持久性:数据存到数据库中,数据的持久化;
隔离性:各事务间不会相互冲突;
隔离级别:
读未提交数据;
读已提交数据;
可重复读(保证数据在事务提交前不会被其他用户修改);
串行化(最高级别的隔离,所有事务都串行化执行);
自动事务
局部事务
全局事务:对性能影响较大,须慎重使用
主动事务、被动事务
定制事务
理想情况下,事务根本就不应该由开发人员来启动。换句话说,应该让容器来启动事务。因此,你应该声明式地配置应用程序。
ibatis为其支持的各种范围的事务使用了一个统一的编程模型,因此即使容器支持事务划分,你可以也应该在
代码中始终使用 startTransaction()、commitTransaction()和endTransaction()。
ibatis所以使用这种方式的原因在于它使得你的持久化代码可以不依赖于任何容器,这样即使在没有容器的环境
下,代码也可以表现出相对一致的行为。其实当事务管理器的类型被配置为EXTERNAL时,ibatis会将事务的管理
权完全交给外部的容器。
将事务在业务逻辑层划界
**************************************************************************************
第8章:使用动态的SQL(dynamic、property、prepend、removeFirstPrepend、open、close、compareValue、compareProperty)
(isEqual、isNotEqual、isGreaterThan、isGreaterEqual、isLessThan、isLessEqual)
(isNull、isNotNull、isEmpty、isNotEmpty)
处理动态WHERE子语句条件
<select id="getChildCategories" parameterClass="Category" resultClass="Category">
select * from category
<dynamic prepend="where">
<isNull property="parentCategoryId">
parentCategoryId is null
</isNull>
<isNotNull property="parentCategoryId">
parentCategoryId=#parentCategoryId#
</isNotNull>
</dynamic>
</select>
所有的动态标签都有prepend、open和close这3个属性。
open和close属性在每个标签中的功能都是一样的。它们无条件地将其属性值放在标签的结果内容的开始处或者结束处。
<dynamic>标签之外,prepend属性在所有其他标签中的功能也都是一样的。<dynamic>标签在内容体的结果SQL非空时,
总是将其prepend属性值添加为该结果SQL的前缀。没什么方式可以阻止<dynamic>标签将该值加为前缀。
其他标签的prepend:第一个产生内容的标签的prepend属性将会被忽略,其他将不会;
<dynamic prepend="where">
<isNotEmpty property="y">
y=#y#
</isNotEmpty>
<isNotNull property="x" removeFirstPrepend="true" prepend="and" open="(" close=")">
<isNotEmpty property="x.a" prepend="or">
a=#x.a#
</isNotEmpty>
<isNotEmpty property="x.b" prepend="or">
a=#x.b#
</isNotEmpty>
<isNotEmpty property="x.c" prepend="or">
a=#x.c#
</isNotEmpty>
</isNotNull>
</dynamic>
<dynamic>标签具有隐式删除(或者说忽略)其第一个产生内容的子标签上的prepend功能。
由于父标签设置了removeFirstPrepend属性,第一个产生内容的<isNotEmpty>子标签将不会把它的prepend
值OR加为前缀。
removeFirstPrepend:这个功能在所有标签中都得到了支持,<dynamic>标签隐式地支持此功能。而其他标签
则通过此属性显式地支持此功能。
<dynamic>是最顶层标签,这意味着它不能被嵌套。
二元标签用于将参数特性的某个值同另外一个值或者参数特性做比较。如果比较结果为true,那么结果SQL
中就包含其内容体。
二元动态标签:<isEqual>、<isNotEqual>、<isGreaterThan>、<isGreaterEqual>、<isLessThan>、<isLessEqual>
二元标签的属性:property(必需)、prepend(可选)、Open(可选)、close(可选)、removeFirstPrepend(可选)
compareProperty(如果没有指定compareValue,则它是必需的)、
compareValue(如果没有指定compareProperty,则它是必需的)
一元标签用于直接考察参数对象中某个bean特性的状态,而不需要与其他值进行比较,如果参数对象的状态结果
为真,那么结果SQL中就会包含其内容体。所有的一元标签都共享property属性。
一元标签:<isPropertyAvailable>、<isNotPropertyAvailable>、<isNull>、<isNotNull>、<isEmpty>、<isNotEmpty>、
一元标签属性:property(必需)、prepend(可选)、Open(可选)、close(可选)、removeFirstPrepend(可选)
参数标签:考虑到ibatis允许定义没有参数的已映射语句。参数标签就是用来检查某个特定参数是否被传递给了已映射语句。
参数标签:<isParameterPresent>、<isNotParameterPresent>
参数标签的属性:prepend(可选的)、open(可选)、close(可选)、removeFirstPrepend(可选)
<iterate>标签
<iterate>标签以一个集合或数组类型的特性作为其property属性值,ibatis通过遍历这个集合(数组)来从一组值
中重复产生某种SQL小片段。这些小片段以conjunction属性值作为分隔符连接起来,从而形成一个有意义的SQL语句片段,
open属性值将作为所呈现的值列表的前缀,close属性值将作为所呈现的值列表的后缀,最终动态形成一个完整合法的SQL。
<iterate>标签属性:property(必需)、prepend(可选)、Open(可选)、close(可选)、conjunction(可选)
removeFirstPropend(可选)
<select id="getProducts" parameterClass="Product" resultClass="Product">
select * from products
<dynamic prepend="where productType in">
<iterate property="productTypes" open="(" close=")" conjunction=",">
#productTypes[]#
</iterate>
</dynamic>
</select>
高级动态SQL技术
**************************************************************************************
第9章:使用高速缓存提高性能
ibatis的强健且简单的高速缓存机制是完全基于配置的,因此避免了直接管理高速缓存的负担。
<cacheModel id="categoryCache" type="MEMORY">
<flushOnExecute statement="cds.insert01"/>
<flushOnExecute statement="cds.update01"/>
<flushOnExecute statement="cds.delete01"/>
<property name="reference-type" value="WEAK"/>
</cacheModel>
<select id="getCategory" parameterClass="Category" resultClass="Category" cacheModel="categoryCche">
select * from categroy where categoryId = #categoryId#
</select>
MEMORY:ibatis内置的一种高速缓存方式,可以把查询结果直接存储在内存中。
<flushOnExecute>:用于指定当某个特定高速缓存被访问时,其存储结果将被清楚。
<property>:就是用于完成这些专用特性的设置的。name指定该高速缓存模型将要设置的特性的名称,
value指定该预定义特性的值。
与其它高速缓存不同,ibatis只专注于数据访问层的高速缓存实现和高速缓存策略。只针对数据访问层,
使得框架通过配置文件来管理高速缓存,而配置文件的管理是非常容易的。
cacheModel的属性:
id
Type
readOnly:为true,并不能保证从高速缓存中检出的对象内容不被改变,
只是告诉ibatis高速缓存,不会修改对象的值,所有可以从高速缓存中得到对象的引用。
通常与serialize联合使用。
serialize:指示高速缓存对应以何种方式返回,当为true时,深复制缓存的对象,意味着从缓存中检出的对象仅仅拥有相同的值,并非指向同一个实例。
readOnly = true/serialize = false;
readOnly = false/serialize = true;
Type:内置的各种高速缓存模型类型:
MEMORY(weak、soft、strong):简单地将高速缓存数据保存在内存中,直至垃圾收集器移除它。
weak:不会阻止垃圾收集器收集,保护内存容量;
soft:会阻止垃圾收集器收集,除非内存容量不足;
strong:不理会内存约束,高速缓存的对象一直存在,除非达到指定的时间间隔;
FIFO(size):高速缓存的数据量是固定的,使用先进先出算法来移除高速缓存中的数据。
LRU(size):高速缓存的数据量是固定的,使用最近最少使用来移除高速缓存中的数据。
OSCACHE:使用opensymphony高速缓存,是一个缓存框架,需要依赖第三方jar。
上述缓存模型都实现cacheController接口;
清除标签,用于定义从高速缓存中清理数据的规则:
flushOnExcete:执行某个sql动作时。
flushInterval(hours、minutes、seconds、milliseconds):定时执行清除。
**************************************************************************************
第10章:ibatis数据访问对象
<daoConfig>
<context id="sqlMap">
<transactionManager></transactionManager>
<dao interface="AccountDAO"
implementnation="AccountDAOImpl"/>
</context>
</daoConfig>
Reader reader = Resources.getResourceAsReader("dao.xml");
DaoManager daoManager = DaoManagerBuilder.buildDaoManager(reader);
public class AccountDAOImpl extends SqlMapTemplate implements AccountDAO{
public AccountDAOImpl(DaoManager daoManager){
super(daoManager);
}
public List query(AccountDTO accountDTO){
this.queryForList("sqlquery", accountDTO);
}
}
**************************************************************************************
第11章:DAO使用进阶 sqlMapClientDaoSupport
**************************************************************************************
第12章:扩展ibatis
ibatis的几个扩展点:
TypeHandlerCallback、cacheController、DataSourceFactory、TransactionConfig
TypeHandlerCallback
类型转换器:类似Hibernate中CustomEditor
注册:<typeHandler callback="com.domain.package.YesNoTypeHandlerCallback" javaType="boolean" jdbcType="VARCHAR"/>
public interface TypeHandlerCallback{
public void setParameter(ParameterSetter setter, Object parameter)throws SQLException;
public Object getResult(ResultGetter getter)throws SQLException;
public Object valueOf(String s);//空值的处理
}
CacheController
LruCacheController:最近最少使用的高速缓存会追踪最近访问的高速缓存项。
FifoCacheController:先进先出高速缓存;
MemoryCacheController:内存高速缓存由java内存模型和垃圾收集器来决定高速缓存项应该在何时被移除;
OSCacheController:OpenSymphony高速缓存是一个被称为OSCache的非常先进的第三方高速缓存解决方案的适配器,
OSCache支持许多自己的高速缓存模型以及像分布高速缓存这样的高级的特性;
<cacheModel id="personCache" type="com.test.MapCacheController">
<flushInterval hours="24"/>
<flushOnExecute statement="updatePerson"/>
<flushOnExecute statement="insertPerson"/>
<flushOnExecute statement="deletePerson"/>
</cacheModel>
public interface CacheController{
public void configure(Properties props);
public void pubObject(CacheModel cacheModel, Object key, Object object);
public Object getObject(CacheModel cacheModel, Object key);
public Object removeObject(CacheModel cacheModel, Object key);
public void flush(CacheModel cacheModel);
}
public calss MapCacheController{
private Map cache = new HashMap();
public void configure(Properties props){
....
}
public void putObject(CacheModel cacheModel, Object key, Object object){
cache.put(key, object);
}
public Object getObject(CacheModel cacheModel, Object key){
return cache.get(key);
}
public Object removeObject(CacheModel cacheModel, Object key){
return cache.remove(key);
}
public void flush(CacheModel cacheModel){
cache.clear();
}
}
第13章:ibatis实践