iBatis是一个采用ORM机制基于SQL的持久层开源框架
ibatis同hibernate一样,都是与数据库打交道的框架,只不过同hibernate不同的是ibatis是半自动化的,而hibernate是全自动的,这样的设计给了我们程序员更大的灵活空间,我们可以自己手动书写sql语句。
ibatis主要包括这么几个部分
一是sqlMapConfig.xml配置文件,
二是pojo用来与数据库打交道的持久层对象,也是我们通过ibatis要操作的对象。
三是sqlMap.xml配置文件用来自己手动填写sql语句,然后再sqlMapConfig.xml文件中添加这个资源的位置。最后在dao中把参数(也就是pojo)传到该配置文件中。
1..sqlMapConfig.xml配置文件详解:
<?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" <!--是否启用缓存机制-->
lazyLoadingEnabled="true" <!--是否启用延迟加载机制-->
enhancementEnabled="true" <!--是否启用字节码增强机制-->
errorTracingEnabled="true" <!--是否启用错误处理机制-->
maxRequests="32" <!--最大并发请求数-->
maxSessions="10" <!--最大Session数-->
maxTransactions="5" <!--最大并发事务数-->
useStatementNamespaces="true"/> <!--是否启用名称空间-->
<transactionManager type="JDBC"> <!--定义了ibatis的事务管理器有3中(JDBC,JTA,EXTERNAL)-->
<dataSource type="SIMPLE"> <!--type属性指定了数据源的链接类型,也有3种类型(SIMPLE,DBCP,JNDI)-->
<property name="JDBC.Driver" value="com.mysql.jdbc.Driver"/>
<property name="JDBC.ConnectionURL" value="jdbc:mysql://localhost/test"/>
<property name="JDBC.Username" value="root"/>
<property name="JDBC.Password" value="wyq"/>
<property name="Pool.MaximumActiveConnections" value="10" /> <!--连接池维持的最大容量-->
<property name="Pool.MaximumIdleConnections" value="5"/> <!--连接池允许挂起的最大连接-->
<property name="Pool.MaximumCheckoutTime" value="120000"/> <!--连接被某个任务所允许占用的最大时间-->
<property name="TimeToWait" value="500"/> <!--线程允许等待的最大时间-->
</dataSource>
</transactionManager>
<sqlMap resource="com/wyq/map/userMap.xml"/>
</sqlMapConfig>
JNDI的配置大部分都在应用服务器中进行,所以在ibatis中的配置相对简单
(1)jdbc事务控制的JNDI配置
<transctionManager type="JDBC">
<dataSource type="JNDI">
<property name="DataSource" value="java:comp/env/jdbc/myDataSource"/>
</dataSource>
</transctionManager>
(2)JTA事务控制的JNDI配置
<transctionManager type="JTA">
<property name="UserTransaction" value="java:/ctx/con/UserTransaction"/>
<dataSource type="JNDI">
<property name="DataSource" value="java:comp/env/jdbc/myDataSource"/>
</dataSource>
</transctionManager>
sqmMap节点指定了映射文件的位置。
测试ibatis类的具体写法
ibatis映射文件的书写:
<?xml version="1.0" encoding="UTF-8"?> |
<statement id="statementName"
[parameterClass="some.class.Name"] //表示输入的参数类型为Class
[resultClass="some.class.Name"] //表示输出的参数类型为Class
[parameterMap="nameOfParameterMap"] //表示输入的参数类型为Map
[resultMap="nameOfResultMap"] //表示输出的参数类型为Class
[cacheModel="nameOfCache"]
>
select * from t_user where sex = [?|#propertyName#] order by [$simpleDynamic$]
</statement>
1、对于参数定义,尽量使用parameterClass,即直接将pojo作为statement的调用参数,如果输入的参数是java.util.map,那么map中的键值将作为输入参数,普通基本类型就是直接输入。
2、对于返回结果而言,尽量也使用resultClass,直接将字段名与pojo相对应。
3、而parameterMap与resultMap实现了pojo到数据库字段的映射配置,parameterMap 使用较少,而resultMap 则大多用于嵌套查询以及存储过程的。
<resultMap id="get_user_result" class="user">
<result property="name" column="xingming"
jdbcType="VARCHAR" javaType="java.lang.String"/>
<result property="sex" column="xingbie"
jdbcType="int" javaType="java.lang.Integer"/>
<result property="id" column="id"
jdbcType="int" javaType="java.lang.Integer"/>
</resultMap>
<parameterMap id="update_user_para" class="redemption" >
<parameter property="name" jdbcType="VARCHAR" javaType="java.lang.String" nullValue="" />
<parameter property="sex" jdbcType="int" javaType="java.lang.Integer" nullValue="" />
</parameterMap>
<procedure id="getUserList" resultMap="get_user_result" >
{call sp_getUserList()}
</procedure>
<procedure id="doUserUpdate"
parameterMap="update_user_para"
>
{call sp_doUserUpdate(#id#,#name#,#sex#)}
</procedure>
ibatis高级特性,处理表与表之间的关联。ibatis中,提供了Statement嵌套支持,通过Statement嵌套,我们可以实现关联数据的操作。
1、一对多关联:
<sqlMap namespace="User">
<typeAlias alias="user" type="com.ibatis.sample.User"/>
<typeAlias alias="address" type="com.ibatis.sample.Address"/>
<resultMap id="get-user-result" class="user">
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<result property="addresses" column="id"
select="User.getAddressByUserId"/>
</resultMap>
<select id="getUsers"
parameterClass="java.lang.String"
resultMap="get-user-result">
<![CDATA[
select id,name, sex from t_user where id = #id#
]]>
</select>
<select id="getAddressByUserId" parameterClass="int" resultClass="address">
<![CDATA[
select address, zipcode from t_address where user_id = #userid#
]]>
</select>
</sqlMap>
多表关联查询大量数据时建议采用存储过程来处理,来避免系统问题
2、一对一表关联:
<resultMap id="get-user-result" class="user">
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<result property="address" column="t_address.address"/>
<result property="zipCode" column="t_address.zipcode"/>
</resultMap>
<select id="getUsers"
parameterClass="java.lang.String"
resultMap="get-user-result">
<![CDATA[
select* from t_user,t_address where t_user.id=t_address.user_id
]]>
</select>
在进行表关联的时候一定要注意:关联的2个pojo之间的联系,还有就是配置文件之间的关联。
动态映射:查询结果根据查询条件的变化而变化
<select id="getUsers"
parameterClass="user"
resultMap="get-user-result">
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>
一元判断:
节点名 描述
<isPropertyAvailable> 参数类中是否提供了此属性
<isNotPropertyAvailable> 与<isPropertyAvailable>相反
<isNull> 属性值是否为NULL
<isNotNull> 与<isNull>相反
<isEmpty> 如果属性为Collection或者String,其size是否<1,
如果非以上两种类型,则通过
String.valueOf(属性值)
获得其String类型的值后,判断其size是否<1
<isNotEmpty> 与<isEmpty>相反。
二元判断:
节点名 属性值与compareValues的关系
<isEqual> 相等。
<isNotEqual> 不等。
<isGreaterThan> 大于
<isGreaterEqual> 大于等于
<isLessThan> 小于
<isLessEqual> 小于等于