ibatis 相关
(1)
在数据库持久层的框架中,大家一定听过Hibernate的大名了吧,经典的SSH框架就有它的一份哦!可是我今天要说的却是另外一个持久层的框架,它就是iBatis。与Hibrenate相比,它的主要优势就是简单、小巧、轻量级,但是它的功能却丝毫不亚于Hibernate,下面让我们来看看iBatis在项目中的应用吧!
iBatis确实很简单,它的工作原理就是通过SQLMap映射文件将sql语句和java对象对应起来(如:在利用对象属性的getter从属性中获取值,查询结果后,将各值用setter方法放到对象中).在iBatis中,sql语句是我们手工编写好的,这一点与Hibernate不同,Hibernate是通过映射java对象和数据库表字段来自动生成的sql语句。
(2)
ibatis中的namespace与resultMap
<sqlMapnamespace="admin">在运用时如下:
this.getSqlMapClient().update(“admin.update”,entity);
分析:
ibatis配置文件中的useStatementNamespaces:是否使用Statement命名空间。这里的命名空间指的是映射文件中,sqlMap节点的namespace属性,如:<sqlMapnamespace="User">。这里,指定了此sqlMap节点下定义的操作均从属于"User"命名空间。
在useStatementNamespaces="true"的情况下,Statement调用需追加命名空间,如:sqlMap.update("User.updateUser",user);否则直接通过Statement名称调用即可,如:sqlMap.update("updateUser",user);
好处:
在实际应用中,利用namespace可以防止两个同名的方法而引起冲突。如有两个updateUser,可以通过AupdateUser/B.updateUser来区分。
另一种方法:
但有一种更方便的方法,可以在不采用namspace的情况下,解决上面的问题:即直接在方法的前面直接命名为AupdateUser/B.updateUser。调用时,直接调用AupdateUser/B.updateUser即可。如下:
<sqlMap>
<typeAliastype="com.admin.entity.Admin"alias="Admin"/>
<selectid="Admin.findUserByLoginName"parameterclass="java.lang.String"
resultMap="AdminResult">
select*fromT_ADMINISTRATORSwherelonginName=#value#
andstatus!=4
</select>
调用时,getSqlMapClientTemplate.queryForList(“Admin.findUserByLoginName”,”test”);即可。
请注意:
此时需要保证所有映射文件中,Statement定义无重名。
第二:
resultMap:结果映射,需结合resultMap节点对映射关系加以定义。
<sqlMap>
<typeAliastype="com.admin.entity.Admin"alias="Admin"/>
<resultMapid="AdminResult"class="Admin">
<resultcolumn="staff_id"property="id"/>
<resultcolumn="loginName"property="loginName"/>
<resultcolumn="password"property="password"/>
<resultcolumn="staff_name"property="username"/>
<resultcolumn="status"property="status"/>
<resultcolumn="phone"property="phone"/>
<resultcolumn="email"property="email"/>
</resultMap>
<selectid="Admin.findUserByLoginName"parameterclass="java.lang.String"
resultMap="AdminResult">
select*fromT_ADMINISTRATORSwherelonginName=#value#
andstatus!=4
</select>
</sqlMap>
(3)关于ibatis中输入/输出各种类型的参数分析
在ibatis,输入的参数对象常以parameterClass来定义,输出的结果集常以resultMap来定义。(resultMap:方便JAVABEAN属性及字段的映射,调用JAVABEAN的setter进行设置值。通常我们不采用resultClass属性进行映射,因为它不具备映射数据库表字段的持久化特性。)
在ibateis中,parameterClass的类型大都是:string,int/对象/hashmap
resultclass/resultMap的类型大都是:对象/hashmap
当parameterClass为string,int时,可用#value#表示或直接用传入的值名表示。
当parameterClass/resultMap的类型是对象时,用#属性#表示。程序会调用JAVABEAN的getter方法,进行获取属性值。
当parameterClass/resultMap的类型是hashmap(Map是key-value结构的)时,那程序会直接通过key来分析取参数。
具体请见以下两部分:
ibatis各种参数数据集
原型参数
<selectid="select1"parameterclass="java.lang.String"resultclass="AppLog">
select
IDasid,
TYPEastype,
DESCRasdescr
fromAPP_LOG
whereID=#id#
</select>
sqlMapper.queryForObject("select0",id);
--参数名与传入值名称一样。--应该也可用参数#value#表示
Map类参数
<selectid="select2"parameterclass="java.util.HashMap"resultclass="AppLog">
select
IDasid,
TYPEastype,
DESCRasdescr
fromAPP_LOG
whereID=#ids#
</select>
map.put("ids",id);
AppLoglog=(AppLog)sqlMapper.queryForObject("select0",map);
--通过key来获取值
对象参数
<selectid="select3"parameterclass="AppLog"resultclass="AppLog">
select
IDasid,
TYPEastype,
DESCRasdescr
fromAPP_LOG
whereID=#id#
</select>
AppLogp=newAppLog();
p.setId(id);
AppLoglog=(AppLog)sqlMapper.queryForObject("select3",p);
动态字段、表
<selectid="selectd"resultclass="java.util.HashMap"parameterclass="java.util.HashMap"
remapResults="true">
select$fieldList$
from$table$
whereID=#id#
</select>
Mapp=newHashMap();
p.put("id",id);
p.put("table","APP_LOG");
p.put("fieldList","ID,TYPE,DESCR");
Mapmap=(Map)sqlMapper.queryForObject("selectd",p);
Stringid1=(String)map.get("ID");
Stringtype=(String)map.get("TYPE");
Stringdescr=(String)map.get("DESCR");
注意:#与$区别:
1.#是把传入的数据当作字符串,如#field#传入的是id,则sql语句生成是这样,orderby"id",这当然会报错..
2.$传入的数据直接生成在sql里,如#field#传入的是id,则sql语句生成是这样,orderbyid,这就对了.
$方式一般用于传入数据库对象.例如传入表名.
#方式一般用于传入插入/更新的值或查询/删除的where条件
ibatis各种返回数据集
别名映射->实体类+resultClass
<selectid="selectAll"resultclass="AppLog">
select
IDasid,
TYPEastype,
DESCRasdescr
fromAPP_LOG
whereID=#id#
</select>
Listlist=sqlMapper.queryForList("selectAll");
for(inti=0;i<list.size();i){
AppLoglog=(AppLog)list.get(i);
//addyourcodehere;
}
注意:
为什么定义了resultclass="AppLog",而queryForList出来的是list?
这里的resultclass="AppLog",是指查询出来的每条记录的格式是AppLog。
当我们queryForList时,系统会将各条记录(即各个AppLog放到list中)传回给我们。当我们queryForObject时,就只传回一个AppLog。
别名映射->Map类+resultClass--》把每条记录放于map中,字段名为key,值为value.
<selectid="selectAll"resultclass="java.util.HashMap">
select
IDasid,
TYPEastype,
DESCRasdescr
fromAPP_LOG
whereID=#id#
</select>
Listlist=sqlMapper.queryForList("selectAll");
for(inti=0;i<list.size();i){
Mapmap=(Map)list.get(i);
Stringid=(String)map.get("id");
Stringtype=(String)map.get("type");
Stringdescr=(String)map.get("descr");
//addyourcodehere;
}
无映射
<selectid="selectAll3"resultclass="java.util.HashMap">
select*fromAPP_LOG
</select>
Listlist=sqlMapper.queryForList("selectAll3");
for(inti=0;i<list.size();i){
Mapmap=(Map)list.get(i);
Stringid=(String)map.get("ID");
Stringtype=(String)map.get("TYPE");
Stringdescr=(String)map.get("DESCR");
}
显式映射->实体类:resultMap
<resultMapid="AppLogResult"class="AppLog">
<resultproperty="id"column="ID"/>
<resultproperty="type"column="Type"/>
<resultproperty="descr"column="DESCR"/>
</resultMap>
<selectid="selectAll"resultMap="AppLogResult">
select*fromAPP_LOG
</select>
Listlist=sqlMapper.queryForList("selectAll");
for(inti=0;i<list.size();i){
AppLoglog=(AppLog)list.get(i);
//addyourcodehere;
}
显式映射->Map类:resultMap--》把每条记录放于map中,字段名为key,值为value.
<resultMapid="map-result"class="java.util.HashMap">
<resultproperty="id"column="ID"/>
<resultproperty="type"column="Type"/>
<resultproperty="descr"column="DESCR"/>
</resultMap>
<selectid="selectAll2"resultMap="map-result">
select*fromAPP_LOG
</select>
Listlist=sqlMapper.queryForList("selectAll2");
for(inti=0;i<list.size();i){
Mapmap=(Map)list.get(i);
Stringid=(String)map.get("id");
Stringtype=(String)map.get("type");
Stringdescr=(String)map.get("descr");
}
又如:
map.put("appIds",Ids);
executor.update("Device.OpenClientApp",map);
下面的property属性及循环变量,都是对应map的key名。
-----证明,ibatis对于hashmap,都是通过key来获取值的。所以,所有参数须用key来表示!!!
如下:
<updateid="Device.OpenClientApp"parameterclass="java.util.HashMap">
updateT_Device_App_R_InfosetOpr='1'whereApp_IDin
<iterateconjunction=","open="("close=")"property="appIds">
#appIds[]#
</iterate>
</update>
例子:
<statementid=”statementName”parameterClass=”examples.domain.Product”>
insertintoPRODUCTvalues(#id#,#description#,#price#,#classify.id#)
</statement>
蓝色部分#classify.id#翻译过来实际是product.getClassify().getId(),classify是Product对象的一个子对象。
(4)关于参数的三种设置方法及ParameterMap用法
前提:有一个user的javabean.
一,自动参数映射:
<insertid="insertUser7"parameterclass="user">
<![CDATA[
INSERTINTOt_user(ID,NAME,PASS)VALUES(#id#,#name#,#pass#)
]]>
</insert>
二,内联参数映射:
<insertid="insertUser8"parameterclass="user">
<![CDATA[
INSERTINTOt_user(ID,NAME,PASS)VALUES(#id:INT#,#name:VARCHAR#,#pass:VARCHAR#)
]]>
</insert>
备注:好像将属性对应的数据类型故意写错,程序也可正常执行,没报错.
三,外联参数映射:
以上二种方式都用paramClass,但此处用parameterMap.
<parameterMapid="parameterMap"class="user">
<parameterproperty="id"jdbcType="INTEGER"/>
<parameterproperty="name"jdbcType="VARCHAR"/>
<parameterproperty="pass"jdbcType="VARCHAR"/>
</parameterMap>
<insertid="insertUser9"parameterMap="parameterMap">
<![CDATA[
INSERTINTOt_user(ID,NAME,PASS)VALUES(?,?,?)
]]>
</insert>
若此处的对象不是javabean,而是一个hashMap.用法也一样,只是id,name,pass不是javabean的属性,而是hashMap的key.
String[]ids;
...........
map.put("devId",ids[0]);
map.put("appId",ids[1]);
<!--自动参数映射方式-->
<insertid="DAPermit.addAppDevMapping"parameterclass="java.util.HashMap">
insertintoT_Device_App_R_Info(Device_ID,App_ID,Opr)values(#devId#,#appId#,'2');
</insert>
<!--
内联方式:
<insertid="DAPermit.addAppDevMapping"parameterclass="java.util.HashMap">
insertintoT_Device_App_R_Info(Device_ID,App_ID,Opr)values(#devId:varchar#,#appId:varchar#,'2');
</insert>
外联方式:
<parameterMapid="dapermitParams"class="java.util.HashMap">
<parameterproperty="devId"jdbcType="VARCHAR"/>
<parameterproperty="appId"jdbcType="VARCHAR"/>
</parameterMap>
<insertid="DAPermit.addAppDevMapping"parameterMap="dapermitParams">
insertintoT_Device_App_R_Info(Device_ID,App_ID,Opr)values(?,?,'2');
</insert>
-->
四,利用parameterMap调用存储过程:
<!--example11:存储过程-->
<resultMapid="returnResultMap"class="user">
<resultproperty="id"column="ID"/>
</resultMap>
<parameterMapid="paramUser"class="java.util.Map">
<parameterproperty="name"jdbcType="VARCHAR"javaType="string"mode="IN"/>
<parameterproperty="pass"jdbcType="VARCHAR"javaType="string"mode="IN"/>
<parameterproperty="id"jdbcType="INT"javaType="Integer"mode="INOUT"resultMap="returnResultMap"/>
</parameterMap>
<procedureid="pro_insertUser11"parameterMap="paramUser"resultclass="int">
<![CDATA[
{callproc_userinsert(?,?,?)}
]]>
</procedure>
然后在UserDaoTest.java中增加如下一个方法:
publicstaticvoidexample11()throwsException{
try{
Mapmap=newHashMap();
map.put("name","procedure");
map.put("pass","123456");
IntegerreturnValue=(Integer)sqlMapClient.insert("pro_insertUser11",map);
System.out.println(returnValue);
}catch(Exceptione){
e.printStackTrace();
}
}