S xRequests
eStatementName 里的命名空间指的是映射文件中,sqlMap 节点
namespace 属性,如在上例中针对t_user
的映射文件sqlMap 节点:
qlMap namespace ="User">
里,指定了此sqlMap 节点下定义的操作均于"User"命名空间。
useStatementNamespaces="true"的情
下,Statement 调用需追加命lMap.update("User.updateUser",use
;
则直接通过Statement 名称调用即可,如:
update("updateUser",user);
lMap.此时需要保证所有映射文件中,
重名。
ement 定义无transactionManager 节点
ansactionManager 节点定义了ibatis 的事选择:
JDBC
过传统JDBC https://www.doczj.com/doc/0417432175.html,mit/rollback 实现事务支持。
JTA
用容器提供的TERNA EX L
,如在EJB 中使用ibatis ,通过EJB 的部署配置即可实现自
管理的事务管理ib 外,通过Spring 等轻量级容器实现事务的配置化管理。关于结合容器实现dataSource 节点
taSource 从属于transactionManager 节点,用于设定ibatis 运行期使
的DataSource 属性。
pe 属性:dataSource 节点的type 属性指定了dataSource 的实现类型。选项目:
IMPLE :
S MPLE 是ibatis 内置的dataSource 实现,其中实现了一个简单的
据库连接池机制,对应ibatis m.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory。
DBCP:
于Apache DBCP 连接DataSource 服务时,建议使用该选项,对应ibatis 实现类为
m.ibatis.qlmap.engi bcpDa s ne.datasource.D taSou JNDI
使用容器提供的实现,将通过指定
的JN co eFacto
ry da ce 的子节点说明(SIMPLE&DBCP ):
参JD BC 驱动。
如JD 如:如在JD JD JD Po ec 数Po 数允许的挂起(idle )连接数。
以分别针对SIMPLE 和DBCP 模式的
Da SI 参Po me 数,连接被某个任务所允许占用的
最大时间将被强
制Po eToWait 当线程试图从连接池中获取连接时,连接池中无
可直许秒)
Po 某时会将其测检QL 。
如成Po Po de 对持续连J2EE DataSource DataSource Name 从容器中获取。对应ibatis 实现类为
DI m.ibatis.sqlmap.engine.datasource.JndiDataSourc 。
taSour 数描述
JD BC.Driver :org.gjt.mm.mysql.Driver
BC.ConnectionURL 数据库URL 。
bc:mysql://localhost/sample
jd 果用的是SQLServer JDBC Driver ,需要
url 后追加SelectMethod=Cursor 以获得
BC 事务的多Statement 支持。
https://www.doczj.com/doc/0417432175.html,ername 数据库用户名
BC.Password 数据库用户密码
ol.MaximumActiveConn
tions
据库连接池可维持的最大容量。
ol.MaximumIdleConnections
据库连接池中上子节点适用于SIMPLE 和DBCP 模式,taSource 私有配置节点如下:
MPLE:
数描述
ol.MaximumCheckoutTi
据库联接池中,如果超过这个时间限定,连接收回。(毫秒)
ol.Tim 用连接可供使用,此时线程将进入等待状态,
到池中出现空闲连接。此参数设定了线程所允
等待的最长时间。(毫ol.PingQuery 数据库连接状态检测语句。
些数据库在连接在某段时间持续处于空闲状态
断开。而连接池管理器将通过此语句检
池中连接是否可用。
测语句应该是一个最简化的无逻辑S “select 1 from t_user ”,如果执行此语句
功,连接池管理器将认为此连接处于可用状态。
ol.PingEnabled 是否允许检测连接状态。
ol.PingConnectionsOl
rThan
接时间超过设定值(毫秒)的连接进行
检测。
Po tU 对(毫秒)的连接进行检测。
DB 参Po mWait 当线程试图从连接池中获取连接时,连接池中无
可直数设定了线程所允
许等待的Po 某空闲状态
时测检如如果执行此语句
成功,连Po 打印日志。
Po me 数Po 时间超过
Re ndonedTimeout 时,是否将其废
弃JN 置相对简单,下面 是使rce
va
⑷ol.PingConnectionsNo
sedFor
空闲超过设定值CP:
数描述
ol.Maximu 用连接可供使用,此时线程将进入等待状态,
到池中出现空闲连接。此参最长时间。(毫秒)
ol.ValidationQuery 数据库连接状态检测语句。
些数据库在连接在某段时间持续处于会将其断开。而连接池管理器将通过此语句检
池中连接是否可用。
测语句应该是一个最简化的无逻辑SQL 。
“select 1 from t_user ”,接池管理器将认为此连接处于可用状态。
接被废弃时,是否ol.LogAbandoned 当数据库连ol.RemoveAbandonedTi
out
据库连接被废弃的最大超时时间
ol.RemoveAbandoned 当连接空闲moveAba 。
DI 由于大部分配置是在应用服务器中进行,因此ibatis 中的配分别使用JDBC 和JTA 事务管理的JDNI 配置:
用JDBC 事务管理的JNDI DataSou 配置
ransac ataSource type ="JNDI">
roperty name ="DataSource"
lue ="java:comp/env/jdbc/myDataSource"/>
dataSource >
transactionManager >
ransactionManager type ="JTA" >
roperty name ="UserTransaction"
on/UserTransaction"/>
lue ="java:/ctx/c ataSource type ="JNDI">
roperty name ="DataSource"lue ="java:comp/env/jdbc/myDataSource"/>dataSource >
ATIS Developer ’s Guide Version 1.0
. Why not your u ptember 2, 2004 So many open source projects transactionManager >
sqlMap 节点
sq 节点指定了映射文件的位置,配置中可出现多个节点,以指定
项ibatis 基础语义
Xm
Xm 2.0之后版本新引入的组件,用以替代1.x 版Sq Sq ,提供数据操作的基础平台。Sq 可ent r 创建:
St Re re Xm er xmlBuilder =
ne Sq "c 文件在CLASSPATH
中件Sq 文Sq 以例sq Pr pr pr in tProduct ”, product);
sq 例sq In Pr (“sq 例
sq Cu sq ust ”, parameterObject, customer); sq rameterObject, customer); sq 例sq lMap sqlMap 目内所包含的所有映射文件。
lSqlMapClientBuilder lSqlMapClientBuilder 是ibatis 本中的XmlSqlMapBuilder 。其作用是根据配置文件创建SqlMapClient 实例。 lMapClient
是is 的核心组件lMapClient lMapClient ibat 通过XmlSqlMapCli Builde ring resource ="com/ibatis/sample/SqlMapConfig.xml";
ader reader;
ader = Resources.getResourceAsReader(resource);
lSqlMapClientBuild w XmlSqlMapClientBuilder();
p(reader);
lMapClient sqlMap = xmlBuilder.buildSqlMa "指明了配置om/ibatis/sample/SqlMapConfig.xml 的相对路径。通XmlSqlMapClientBuilder 过接受一个Reader 类型的配置文
句柄,根据配置参数,创建SqlMapClient 实例。
lMapClient 提供了众多数据操作方法,下面是一些常用方法的示例,具体说明
档请参见ibatis java doc ,或者ibatis 官方开发手册。
lMapClient 基本操作示例
下示例摘自ibatis 官方开发手册,笔者对其进行了重新排版以获得更好的阅读效果。 1: 数据写入操作(insert, update, delete):
lMap.startTransaction();
oduct product = new Product();
oduct.setId (1);
uct tion (“Shih Tzu ”);
od .setDescrip t rows = sqlMap.insert (“inser https://www.doczj.com/doc/0417432175.html,mitTransaction();
2: 数据查询(select)
lMap.startTransaction();
teger key = new Integer (1);
queryForObject
oduct product = (Product)sqlMap.”getProduct , key);
https://www.doczj.com/doc/0417432175.html,mitTransaction();
3: 在指定对象中存放查询结果(select)lMap.startTransaction();
stomer customer = new Customer();
lMap.queryForObject(“getC lMap.queryForObject(“getAddr ”, pa https://www.doczj.com/doc/0417432175.html,mitTransaction();
4: 执行批量查询(select)
lMap.startTransaction();
Li “”sq 例//on 时,默认为auto_commit 模式
in 例sq Li “getProductList ”, null , 0, 40); sq 例pu ts RowHandler {
pu list) throws
SQ Pr pr (10000);
sq }
}
sq Ro ndler rowHandler = new MyRowHandler();
Li list = sqlMap.queryForList (“getProductList ”, null ,
ro sq IB Se n y 例Pa sqlMap.queryFo ginatedList (“getProductList ”, null , 10);
li li 例t)
sq Ma ForMap (getProductList , null ,
“sq Pr ST-93”);
O 相而言,ibatis 的映射配置更为简洁直接,下面是一
个
https://www.doczj.com/doc/0417432175.html,mitTransaction();
5: 关于AutoCommit
没有预先执行startTransacti t rows = sqlMap.insert (“insertProduct ”, product);
6:查询指定范围内的数据
lMap.startTransaction();
st list = sqlMap.queryForList (https://www.doczj.com/doc/0417432175.html,mitTransaction();
7: 结合RowHandler 进行查询(select)
blic class MyRowHandler implemen blic void handleRow (Object object, List LException {
oduct product = (Product) object;
oduct.setQuantity lMap.update (“updateProduct ”, product);
lMap.startTransaction();
wHa st wHandler);
https://www.doczj.com/doc/0417432175.html,mitTransaction();
ATIS Developer ’s Guide Version 1.0
open source projects. Why not Ope our Doc uments?
ptember 2, 2004 So many 8: 分页查询(select)
ginatedList list =
rPa st.nextPage();
st.previousPage();
9: 基于Map 的批量查 (selec lMap.startTransaction();
“”p map = sqlMap.query productCode ”);
lM comm nsaction ap.itTra ();
oduct p = (Product) map.get(“E R 映射
对Hibernate 等ORM 实现典型的配置文件。
DOCTYPE sqlMap
"-//https://www.doczj.com/doc/0417432175.html,//DTD SQL Map 2.0//EN"
BLIC ttp://www.ib qlMap namespace ="User">
re ca >
]]
UP SE na se WH d = #id#
可两个部分:模块配置和Statement 配置。
模---->
ypeAl as ="u ias ali ser" type ="https://www.doczj.com/doc/0417432175.html,er"/>
acheModel id ="userCache" type ="LRU">
lushInterval hours ="24"/>
lushOnExecute statement =" update roperty name ="size" value ="1000" />
cacheModel >
>
—Statement 配置--e elect id ="getUs r"
rameterClass ="https://www.doczj.com/doc/0417432175.html,ng.sultClass ="user"
cheModel ="userCache"
[CDATA[
lec >
select >
id ="updateUser"
pdate rameterClass DATE t_user
T
me=#name#,
x=#sex#
ERE i update >
sqlMap >
以看到,映射文件主要分为块配置包括: 点:
typeAlias 节定的别名,以避免过长变量值的反复书写,此例中通过
义了本映射文件中typeAlias 节点为类"https://www.doczj.com/doc/0417432175.html,er"定义了一个别名"user",
这他部分,需要引用"https://www.doczj.com/doc/0417432175.html,er"类时,
样在本配置文件的其只 定
这
St
cacheModel 节点
义了本映射文件中使用的Cache 机制:
acheModel id Cache" type ="LRU">
lushInterval hours ="24"/>
lushOnExecute statemen roperty name ="size" cacheModel >
里申明了一个名为"userCache"的cacheModel ,之后可以在atement 申明中对其进行引用:
elect id ="getUser"
rameterClass ="https://www.doczj.com/doc/0417432175.html,ng.String"
re ca >
这表明对通过id 为"getUser"的Select statement 获取的数据,使用
ca 进ca 设定值,则将此CacheModel 的缓存清空。
本 cute :
指ser 操作将更
新缓存中的数据对象与数据库中的实际
数关St St
其最为通用,它可以替代其余的所有节点。除statement 之外
的L 中的同名操作(procedure 对应存储过程)。
使用有操作固然可以达成目标,但缺乏直观性,建议在实际
开选用对应的节点名加以申明。一方面,使得配置文件
更配各in 主st
[r [p rameterMap"]
[r fResultMap"]
[c >
se ertyName#]
or
cheModel ="userCache"
cheModel "userCache"进行缓存。之后如果程序再次用此Statement
行数据查询,即直接从缓存中读取查询结果,而无需再去数据库查询。
cheModel 主要有下面几个配置点:
flushInterval :
定缓存有效期,如果超过此设size :
CacheModel 中最大容纳的数据对象数量。
flushOnExe 定执行特定Statement 时,将缓存清空。如updateU 数据库中的用户信息,这将导致据发生偏差,因此必须将缓存清空以避免脏数据的出现。
于Cache 的深入探讨,请参见“高级特性”中的相关章节。
atement 配置:
了数个与相关的节点,分别为:atement 配置包含SQL Statement atement
st insert
delete
update
select
procedure
中,statement 节点各自对应了SQ 定statement 义所发中根据操作目的,各自加直观,另一方面,也可_____借助DTD 对节点申明进行更有针对性的检查,以避免 置上的失误。
种类型的Statement 配置节点的参数类型基本一致,区别在于数量不同。如
sert 、update 、delete 节点无需返回数据类型定义(总是int )。
要的配置项如下:
atement:
tatement id ="statementName"
lass ="some.c arameterC las esultClass ="https://www.doczj.com/doc/0417432175.html,"]
arameterMap ="nameOfPa esultMap ="nameO acheModel ="nameOfCache"]
lect * from t_user where sex = [?|#prop der by [$simpleDynamic$]
statement >
se
se |#propertyName#]
or
[p s ="https://www.doczj.com/doc/0417432175.html,"]
[p
>
in (n va ([opertyName#])
[p "nameOfParameterMap"]
>
UP SE na se ?|#propertyName#]
WH pertyName#]
De
de t_user
wh 其参lect:
elect id ="statementName"
arameterClass ="https://www.doczj.com/doc/0417432175.html,"]
esultClass ="https://www.doczj.com/doc/0417432175.html,"]
arameterMap ="nameOfParameterMap"]
esultMap ="nameOfResultMap"]
acheModel ="nameOfCache"]
lect * from t_user where sex = [?der by [$simpleDynamic$]
select >
sert:
nsert id ="st arameterClas arameterMap ="nameOfParameterMap"]sert into t_user
e,sex)
am lues
?|#propertyName#],[?|#pr insert >
date :
pdate id ="statementName"
arameterClas p =arameterMa DATE t_user
T
me=[?|#propertyName#],
x=[ERE id = [?|#pro updat lete :
elete id ="statementName"
arameterClass ="https://www.doczj.com/doc/0417432175.html,"]
"nameOfParameterMap"]
arameterMap =lete from ere id = [?|#propertyName#]
delete >
中以“[]”包围的部分为可能出现的配置栏目。
述 数描pa 了参数的完整类名(包括包路径)。
可rameterClass 参数类。指定通过别名避免每次重复书写冗长的类名。
re 结果类。指定结果类型的完整类名(包括包路径)
可sultClass 通过别名避免每次重复书写冗长的类名。
pa 点对映射
关对atement 而言,建议使用
pa 免re 加以定义ca 对,尽量使用parameterClass ,即直接将POJO 作为
sta 的属性作为参数加以
设
UP SE na se WH d = #id#
这https://www.doczj.com/doc/0417432175.html,er 类设定为update statement 的参数,之后,
我opertyName #对POJO 的属性进行引用。如上例
中SE 运行期,应的参如果String 、
In 我
re rameterMap 参数映射,需结合parameterMap 节系加以定义。
于存储过程之外的st rameterClass 作为参数配置方式,一方面避
了参数映射配置工作,另一方面其性能表现也更加出色。
结果映射,sultMap 需结合resultMap 节点对映射关系
。
cheModel statement 对应的Cache 模块。
于参数定义而言tement 的调用参数,这样在SQL 中可以直接将POJO 定,如:
pdate id ="updateUser"
rameterClass DATE t_user
T
me=#name#,
x=#sex#
ERE i update >
里将com.ibati 们即可在SQL 中通过#pr 的:
T name=#name#, sex=#sex# WHERE id=#id#
batis 调用Us i 将通过er 对象的getName 、getSex 和getId 方法获得相
数值,并将其作为SQL 的参数。
parameterClass 中设定的是jdk 的中的简单对象类型,如teger ,ibatis 会直接将其作为SQL 中的参数值。
们也可以将包含了参数数据的Map 对象传递给Statement ,如:
pdate id ="updateUser"
rameterClass ="java.util.Map">
DATE t_user
T
me=#name#,
x=#sex#
ERE id = #id#
update >
里传入取对应的参数值。
样的原理,我们elect id ="getUser"
="java rameterClass sultClass ="java.util.Map">
返字段名为key 保存在Map 对象中返回。
在SE id 对:
wh ]]
值例中,ibatis 会调用setName ,setSex 方法将Select 语句返回的数据赋
予例。
有希的如(假设我们的书库中对应用户名的字段为
xi se xi xi fr wh #id#
ib 行属性映射(即调用POJO 的setName 方法而
不
IBA Version 1.0
Se source projects. Why not Open your Doc uments?
pa 一
jd
lect id,name,sex from t_user
ere id = #id#
>
selec 回的结果将以各SQL 中设定参数名时,可以同时指定参数类型,如:
T name=#name:VARCHAR #,sex=#sex:NUMERIC # WHERE
=#id:NUMERIC #
于返回结果是select 语句,建议也采用resultClass 进行定义,如而言,如果elect id ="getUser"
rameterClass ="https://www.doczj.com/doc/0417432175.html,ng.String"
sultClass ="user">
[CDATA[
lect name,sex from t_us name#
ere name = #>
select >
atis 会自动根据select 语句中的字,如上相应的POJO 实些时候,数据库表中的字段名过于晦涩,而为了使得代码更易于理解,我们
望字段映射到POJO 时,采用比较易读的属性名,此时,我们可以通过Select
as 字句对字段名进行转义,ngming ,对应性别的字段为xingbie ):
lect
ngming as name,
bie sex
ng as om t_user
ere id =atis 会根据转义后的字段名进是setXingming 方法)。TIS Developer ’s Guide ptember 2, 2004 So many open 和rameterMap resultMap 实现了POJO 到数据库字段的映射配置,下面是
个例子:
esultMap id ="get_user_re esult property ="name" column bcType ="VARCHAR" javaType ="https://www.doczj.com/doc/0417432175.html,ng.String"/>
esult property ="sex" column ="xingbie"
bcType ="int esult property ="id" column ="id"
bcType ="int" javaType ="https://www.doczj.com/doc/0417432175.html,ng.Integer"/>
resultMap >
nu />
jd ja nu />
之对其进行引用,如:
{c
pa >
{c sex#)}
一般而parameterClass 和pa 以及存储过程的 IBA ersion 1.0
Se 处由于存储过程相对而言比较封闭(很多情况下需要调用现有 的并as 子句进行字段名转义,无法使其自动与POJO 中映射 关类型ibati 上ib 数据关联
至我们常常遇到关联数 据的情况,如User 对象拥有若干Address 对象,每个Address 对象描述了对应User 的 一应该如何处理?
arameterMap id ="update_user_para" class ="redemption" >
arameter property ="name"
bcType ="VARCHAR"
vaType ="https://www.doczj.com/doc/0417432175.html,ng.String llValue =""
aramet bcType ="int"
.Integer"
vaType ="https://www.doczj.com/doc/0417432175.html,ng llValue =""
parameterMap >
ramet 后我们即可在statement 申明中rocedure id ="getUserList"
sultMap ="get_user_result"
all sp_getUserList()}
procedure >
roc rameterMap ="update_user_para"
all sp_doUserUpdate(#id#,#name#,#procedure >
言,对于insert 、update 、delete 、select 语句,优先采用resultClass 。
较少,而resultMap 则大多用于嵌套查询rameterMap 使用TIS Developer ’s Guide V ptember 2, 2004 So many open source projects. Why not Open your Doc uments?
理,之所以这样,原因是存储过程,其参数命名和返回的数据字段命名往往不符合Java 编程中的命名习惯, 且由于我们难以通过Select SQL 的的属性名相匹配)。此时,使用resultMap 建立字段名和POJO 属性名之间的系就显得非___________常有效。另一方面,由于通过resultMap 指定了字段名和字段,
无需再通过来动态获取字段信息,在一定程度 s JDBC ResultSetMetaData 也提升了性能表现。
atis 高级特性
此,我们讨论的都是针对独立数据的操作。在实际开发中,个联系地址,这种情况下,我们
通过单独的State 实现(通过Statement 工繁ib 联数 据ment 操作固然可以 用于读取用户数据,再手调用另外一个Statement 根据用户ID 返回对应的Address 信息)。不过这样未免失之 琐。下面我们就看看在ibatis 中,如何对关联数据进行操作。
atis 中,提供了Statement 嵌套支持,通过Statement 嵌套,我们即可实现关的操作。
一下们首选读取t_user 表中的所有用户记录,然后获取每个用户对应 的所有配置文
面的例子中,我地址信息。
件如下:
qlMap namespace ="U ypeAlias alias =ypeAlias alias ="address" type =esultMap id ="get-user-result" class ="user">
esult property ="id" column ="id"/>
esult property ="name" column ="name"/>
esult property ="sex" column ="sex"/>
esult property ="addresses" column ="id"
se
//resultMap >
实现了关联
elect id ="getUsers"
rameterClass ="https://www.doczj.com/doc/0417432175.html,ng.String"
sultMap ="get-us [CDATA[
lect id,name,sex from t_user
ere id = #id#
>
select >
Re reader;
re rces.getResourceAsReader(resource);
Xm tBuilder xmlBuilder = new XmlSqlMapClientBuilder(); sq ilder.buildSqlMap(reader);
//Li elect id ="getAddressByUserId"
rameterClass ="int"
sultC [CDATA[
lect address,zipcodefrom t_address
ere user_id = #userid#
>
select >
sqlMap >
应代码:
ring resource ="com/ibatis/sa ader ader = Resou lSqlMapClien lMap = xmlBu sqlMap 系统初始化完毕
Map.queryForList("User.getUsers", "");
st userList = sql