个人从不容资料中摘抄的一些有关ibatis的资料,请大家多提意见!
Ibatis
定义:
相对Hibernate和Apache OJB 等“一站式”ORM解决方案而言,ibatis 是一种“半
自动化”的ORM实现。
以前
ORM的框架(hibernate,ojb)的局限:
1. 系统的部分或全部数据来自现有数据库,处于安全考虑,只对开发团队提供几
条Select SQL(或存储过程)以获取所需数据,具体的表结构不予公开。
2. 开发规范中要求,所有牵涉到业务逻辑部分的数据库操作,必须在数据库层由
存储过程实现(就笔者工作所面向的金融行业而言,工商银行、中国银行、交
通银行,都在开发规范中严格指定)
3. 系统数据处理量巨大,性能要求极为苛刻,这往往意味着我们必须通过经过高
度优化的SQL语句(或存储过程)才能达到系统性能设计指标。
ibatis 的着力点
:
在于POJO 与SQL之间的映射关系。也就是说,ibatis
并不会为程序员在运行期自动生成SQL 执行。具体的SQL 需要程序员编写,然后通过映
射配置文件,将SQL所需的参数,以及返回的结果字段映射到指定POJO。
Ibatis与
Hibernate的区别:
Hibernate提供了全面的数据库封装机制的“全自动化”ORM 实现而言,“全自动”ORM 实现了POJO 和数据库表之间的映射,以及SQL 的自动生成和执行,而ibatis 的着力点,则在于POJO 与SQL之间的映射关系。也就是说,ibatis并不会为程序员在运行期自动生成SQL 执行。具体的SQL 需要程序员编写,然后通过映射配置文件,将SQL所需的参数,以及返回的结果字段映射到指定POJO。
ibatis配置
ibatis
配置文件:
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<!DOCTYPE sqlMapConfig
PUBLIC
"-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-config-2.dtd"
>
<
sqlMapConfig
>
<
settings
⑴
cacheModelsEnabled
=
"true"
enhancementEnabled
=
"true"
lazyLoadingEnabled
=
"true"
errorTracingEnabled
=
"true"
maxRequests
=
"32"
maxSessions
=
"10"
maxTransactions
=
"5"
useStatementNamespaces
=
"false"
/>
<
transactionManager
type
=
"JDBC"
>
⑵
<
dataSource
type
=
"SIMPLE"
>
⑶
<
property
name
=
"JDBC.Driver"
value
=
"com.p6spy.engine.spy.P6SpyDriver"
/>
<
property
name
=
"JDBC.ConnectionURL"
value
=
"jdbc:mysql://localhost/sample"
/>
<
property
name
=
"JDBC.Username"
value
=
"user"
/>
<
property
name
=
"JDBC.Password"
value
=
"mypass"
/>
<
property
name
=
"Pool.MaximumActiveConnections"
value
=
"10"
/>
<
property
name
=
"Pool.MaximumIdleConnections"
value
=
"5"
/>
<
property
name
=
"Pool.MaximumCheckoutTime"
value
=
"120000"
/>
<
property
name
=
"Pool.TimeToWait"
value
=
"500"
/>
<
property
name
=
"Pool.PingQuery"
value
=
"select 1 from
ACCOUNT"
/>
<
property
name
=
"Pool.PingEnabled"
value
=
"false"
/>
<
property
name
=
"Pool.PingConnectionsOlderThan"
value
=
"1"
/>
<
property
name
=
"Pool.PingConnectionsNotUsedFor"
value
=
"1"
/>
</
dataSource
>
</
transactionManager
>
<
sqlMap
resource
=
"com/ibatis/sample/User.xml"
/>
⑷
<
sqlMap
resource
=
"com/ibatis/sample/Address.xml"
/>
</
sqlMapConfig
>
|
⑴
Settings
节点
参数
|
描述
|
cacheModelsEnabled
|
是否启用
SqlMapClient
上的缓存机制。
建议设为
"true"
|
enhancementEnabled
|
是否针对
POJO
启用字节码增强机制以提升
getter/setter
的调用效能,避免使用
Java
Reflect
所带来的性能开销。
同时,这也为
Lazy Loading
带来了极大的性能
提升。
建议设为
"true"
|
errorTracingEnabled
|
是否启用错误日志,在开发期间建议设为
"true"
以方便调试
|
lazyLoadingEnabled
|
是否启用延迟加载机制,建议设为
"true"
|
maxRequests
|
最大并发请求数(
Statement
并发数)
|
maxTransactions
|
最大并发事务数
|
maxSessions
|
最大
Session
数。即当前最大允许的并发
SqlMapClient
数。
maxSessions
设定必须介于
maxTransactions
和
maxRequests
之间,即
maxTransactions<maxSessions=<
maxRequests
|
useStatementNamespaces
|
是否使用
Statement
命名空间。
这里的命名空间指的是映射文件中,
sqlMap
节点
的
namespace
属性,如在上例中针对
t_user
表的映射文件
sqlMap
节点:
<
sqlMap
namespace
=
"User"
>
这里,指定了此
sqlMap
节点下定义的操作均从
属于
"User"
命名空间。
在
useStatementNamespaces=
"true"
的情
况下,
Statement
调用需追加命名空间,如:
sqlMap.update(
"User.updateUser"
,use
r);
否则直接通过
Statement
名称调用即可,如:
sqlMap.update(
"updateUser"
,user);
但请注意此时需要保证所有映射文件中,
Statement
定义无重名。
|
⑵
transactionManager
节点
transactionManager
节点定义了
ibatis
的事务管理器,目前提供了以下几种选择:
Ø
JDBC
通过传统
JDBC Connection.commit/rollback
实现事务支持。
Ø
JTA
使用容器提供的
JTA
服务实现全局事务管理。
Ø
EXTERNAL
外部事务管理,如在
EJB
中使用
ibatis
,通过
EJB
的部署配置即可实现自动的事务管理机制。此时
ibatis
将把所有事务委托给外部容器进行管理。此外,通过
Spring
等轻量级容器实现事务的配置化管理也是一个不错的选择。关于结合容器实现事务管理,参见“高级特性”中的描述。
⑶
dataSource
节点
dataSource
从属于
transactionManager
节点,用于设定
ibatis
运行期使用的
DataSource
属性。
type
属性:
dataSource
节点的
type
属性指定了
dataSource
的实现类型。可选项目:
Ø
SIMPLE
:
SIMPLE
是
ibatis
内置的
dataSource
实现,其中实现了一个简单的数据库连接池机制,对应
ibatis
实现类为
com.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory
。
Ø
DBCP:
基于
Apache DBCP
连接池组件实现的
DataSource
封装,当无容器提
供
DataSource
服务时,建议使用该选项,
对应
ibatis
实现类为
com.ibatis.sqlmap.engine.datasource.DbcpDataSourceFactory
。
Ø
JNDI
:
使用
J2EE
容器提供的
DataSource
实现,
DataSource
将通过指定
的
JNDI Name
从容器中获取。对应
ibatis
实现类为
com.ibatis.sqlmap.engine.datasource.JndiDataSourceFactory
。
dataSource
的子节点说明(
SIMPLE&DBCP
):
参数
|
描述
|
JDBC.Driver
|
JDBC
驱动。如:
com.microsoft.jdbc.sqlserver.SQLServerDriver
|
JDBC.ConnectionURL
|
数据库
URL
。如:
jdbc:microsoft:sqlserver://localhost:1433;databaseName=ibatis
如果用的是
SQLServer JDBC Driver
,需要在
url
后追加
SelectMethod=Cursor
以获得
JDBC
事务的多
Statement
支持。
|
JDBC.Username
|
数据库用户名
|
JDBC.Password
|
数据库用户密码
|
Pool.MaximumActiveConn
ections
|
数据库连接池可维持的最大容量。
|
Pool.MaximumIdleConnec
tions
|
数据库连接池中允许的挂起(
idle
)连接数。
|
以上子节点适用于
SIMPLE
和
DBCP
模式,分别针对
SIMPLE
和
DBCP
模式的
DataSource
私有配置节点如下:
SIMPLE:
Pool.MaximumCheckoutTime
|
数据库联接池中,连接被某个任务所允许占用的最大时间,如果超过这个时间限定,连接将被强制收回。(毫秒)
|
Pool.TimeToWait
|
当线程试图从连接池中获取连接时,连接池中无可用连接可供使用,此时线程将进入等待状态,直到池中出现空闲连接。此参数设定了线程所允许等待的最长时间。(毫秒)
|
Pool.PingQuery
|
数据库连接状态检测语句。某些数据库在连接在某段时间持续处于空闲状态时会将其断开。而连接池管理器将通过此语句检测池中连接是否可用。检测语句应该是一个最简化的无逻辑
SQL
。如“
select 1 from t_user
”,如果执行此语句成功,连接池管理器将认为此连接处于可用状态
|
Pool.PingEnabled
|
是否允许检测连接状态。
|
Pool.PingConnectionsOlderThan
|
对持续连接时间超过设定值(毫秒)的连接进行检
测。
|
Pool.PingConnectionsNotUsedFor
|
对空闲超过设定值(毫秒)的连接进行检测。
|
DBCP:
Pool.MaximumWait
|
当线程试图从连接池中获取连接时,连接池中无可用连接可供使用,此时线程将进入等待状态,直到池中出现空闲连接。此参数设定了线程所允许等待的最长时间。(毫秒)
|
Pool.ValidationQuery
|
数据库连接状态检测语句。某些数据库在连接在某段时间持续处于空闲状态时会将其断开。而连接池管理器将通过此语句检测池中连接是否可用。检测语句应该是一个最简化的无逻辑
SQL
。如“
select 1 from t_user
”,如果执行此语句
成功,连接池管理器将认为此连接处于可用状态。
|
Pool.LogAbandoned
|
当数据库连接被废弃时,是否打印日志。
|
Pool.RemoveAbandonedTimeout
|
数据库连接被废弃的最大超时时间
|
Pool.RemoveAbandoned
|
当连接空闲时间超过
RemoveAbandonedTimeout
时,是否将其废弃。
|
JNDI:
由于大部分配置是在应用服务器中进行,因此
ibatis
中的配置相对简单,下面是分别使用
JDBC
和
JTA
事务管理的
JDNI
配置:
使用
JDBC
事务管理的
JNDI DataSource
配置
<
transactionManager
type
=
"JDBC"
>
<
dataSource
type
=
"JNDI"
>
<
property
name
=
"DataSource"
value
=
"java:comp/env/jdbc/myDataSource"
/>
</
dataSource
>
</
transactionManager
>
|
<
transactionManager
type
=
"JTA"
>
<
property
name
=
"UserTransaction"
value
=
"java:/ctx/con/UserTransaction"
/>
<
dataSource
type
=
"JNDI"
>
<
property
name
=
"DataSource"
value
=
"java:comp/env/jdbc/myDataSource"
/>
</
dataSource
>
</
transactionManager
>
|
⑷ sqlMap节点
sqlMap
节点指定了映射文件的位置,配置中可出现多个
sqlMap
节点,以指定
项目内所包含的所有映射文件。
映射文件
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<!DOCTYPE sqlMap
PUBLIC
"-//iBATIS.com//DTD SQL Map 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-2.dtd"
>
<
sqlMap
namespace
=
"映射文件名称:
User
"
>
<
typeAlias
alias
=
"user"
type
=
"com.ibatis.sample.User"
/>
给对应的类取别名
<
cacheModel
id
=
"userCache"
type
=
"LRU"
>
<
flushInterval
hours
=
"24"
/>
设定缓存有效期
<
flushOnExecute
statement
=
" updateUser"
/>
指定执行特定
Statement
时,将缓存清空。如
updateUser
操作将更新数据库中的用户信息,这将导致缓存中的数据对象与数据库中的实际数据发生偏差,因此必须将缓存清空以避免脏数据的出现。
<
property
name
=
"size"
value
=
"1000"
/>
CacheModel
中最大容纳的数据对象数量
</
cacheModel
>
<
select
id
=
""
parameterClass
=
"java.lang.String"
resultClass
=
"user"
>
<![CDATA[
可以避免
SQL
中与
XML
规范相冲突的字符对
XML
映射文件的合法性造成影响。
SQL
语句
]]>
</
select
>
<
update
id
=
" "
parameterClass
=
"java.lang.String"
>
<![CDATA[
SQL
语句
]]>
</
update
>
<
insert
id
=
" "
parameterClass
=
"java.lang.String"
>
<![CDATA[
SQL
语句
]]>
</
insert
>
<
delete
id
=
""
parameterClass
=
"java.lang.String"
>
<![CDATA[
SQL
语句
]]>
</
delete
>
</
sqlMap
>
|
需要一个JAVABEAN:有getter和setter方法
如何读取配置文件:
public class SQLMapper {
public static SqlMapClient sqlMapper;
static{
String resource = "org/lzp/xml/SqlMapConfig.xml";
指明了配置文件的相对路径
try {
Reader reader = Resources.getResourceAsReader(resource);
//ibatis2.0
/*
XmlSqlMapClientBuilder xmlBuilder =
new
XmlSqlMapClientBuilder();
sqlMapper =
xmlBuilder.buildSqlMap(reader);
*/
//ibatis1.0
sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);
} catch (Exception e) {
e.printStackTrace();
}
}
}
|
SqlMapClient
是
ibatis
运作的核心,所有操作均通过
SqlMapClient
实例完成。例如:
sqlMapper.insert("名称", 参数);
sqlMapper
提供了众多数据操作方法,下面是一些常用方法的示例,具体说明文档请参见
ibatis java doc
,或者
ibatis
官方开发手册。
Statement配置:
Statement
配置包含了数个与
SQL Statement
相关的节点,分别为:
u
statement:
最为通用,它可以替代其余的所有节点。
u
insert
u
delete
u
update
u
select
u
procedure
参数描述:可以是类、基本数据类型和
MAP
进行传值
参数
|
描述
|
parameterClass
|
参数类。指定了参数的完整类名(包括包路径)。
可通过别名避免每次重复书写冗长的类名。
|
resultClass
|
结果类。指定结果类型的完整类名(包括包路径)
可通过别名避免每次重复书写冗长的类名。
|
parameterMap
|
参数映射,需结合
parameterMap
节点对映射关系加以定义。对于存储过程之外的
statement
而言,建议使用
parameterClass
作为参数配置方式,一方面避
免了参数映射配置工作,另一方面其性能表现也更加出色。
|
resultMap
|
结果映射,需结合
resultMap
节点
对映射关系加以定义。
|
cacheModel
|
statement
对应的
Cache
模块。
|
动态映射:
<
select
id
=
"getUsers"
parameterClass
=
"user"
resultClass
=
"user"
>
Select id,name,sex from t_user
<
dynamic
prepend
=
"WHERE"
>
<
isNotEmpty
prepend
=
"AND"
property
=
"name"
>
(name like #name#)
</
isNotEmpty
>
<
isNotEmpty
prepend
=
"AND"
property
=
"address"
>
(address like #address#)
</
isNotEmpty
>
</
dynamic
>
</
select
>
|
Ø 一元判定
: 是针对属性值本身的判定,如属性是否为NULL,是否为空值等。
一元判定节点有:
节点名
|
描述
|
<isPropertyAvailable>
|
参数类中是否提供了此属性
|
<isNotPropertyAvailable>
|
与
<isPropertyAvailable>
相反
|
<isNull>
|
属性值是否为
NULL
|
<isNotNull>
|
与
<isNull>
相反
|
<isEmpty>
|
如果属性为
Collection
或者
String
,其
size
是否
<1
,
如果非以上两种类型,则通过
String.valueOf(
属性值
)
获得其
String
类型的值后,判断其
size
是否
<1
|
<isNotEmpty>
|
与
<isEmpty>
相反。
|
Ø
二元判定
二元判定有两个判定参数,一是属性名,而是判定值,如
<
isGreaterThan
prepend
=
"AND"
property
=
"age"
compareValue
=
"18"
>
(age=#age#)
</
isGreaterThan
>
其中,
property="age"
指定了属性名
”
age
”
,
compareValue=
”
18
”
指明了判定值为
”
18
”
。上面判定节点
isGreaterThan
对应的语义是:如果
age
属性大于
18(compareValue)
,则在
SQL
中加入
(age=#age#)
条件
。
二元判定节点有:
节点名
|
属性值与compareValues的关系
|
<isEqual>
|
相等。
|
<isNotEqual>
|
不等。
|
<isGreaterThan>
|
大于
|
<isGreaterEqual>
|
大于等于
|
<isLessThan>
|
小于
|
<isLessEqual>
|
小于等于
|