ibatis中輸入/輸出各種型別的引數分析及#與$區別 (轉)
阿新 • • 發佈:2019-01-22
(1)
在資料庫持久層的框架中,大家一定聽過Hibernate的大名了吧,經典的SSH框架就有它的一份哦!可是我今天要說的卻是另外一個持久層的框架,它就是iBatis。與Hibrenate相比,它的主要優勢就是簡單、小巧、輕量級,但是它的功能卻絲毫不亞於 Hibernate,下面讓我們來看看iBatis在專案中的應用吧! iBatis確實很簡單,它的工作原理就是通過SQL Map對映檔案將sql語句和java物件對應起來(如:在利用物件屬性的getter從屬性中獲取值,查詢結果後,將各值用setter方法放到物件中).在iBatis中,sql語句是我們手工編寫好的,這一點與Hibernate不同,Hibernate是通過對映java物件和資料庫表字段來自動生成的sql語句。 (2)
ibatis中的namespace與resultMap
<sqlMap namespace="admin">在運用時如下:
this.getSqlMapClient().update(“admin.update”, entity);
分析:
ibatis 配置檔案中的useStatementNamespaces:是否使用Statement名稱空間。這裡的名稱空間指的是對映檔案中,sqlMap節點的 namespace屬性,如:<sqlMap namespace="User">。這裡,指定了此sqlMap節點下定義的操作均從屬於"User"名稱空間。
在 useStatementNamespaces="true"的情況下,Statement呼叫需追加名稱空間,如:sqlMap.update("User.updateUser",user);否則直接通過Statement名稱呼叫即可,如:sqlMap.update("updateUser",user);
好處:
在實際應用中,利用namespace可以防止兩個同名的方法而引起衝突。如有兩個updateUser,可以通過A updateUser/B. updateUser來區分。
另一種方法:
但有一種更方便的方法,可以在不採用namspace的情況下,解決上面的問題:即直接在方法的前面直接命名為A updateUser/B. updateUser。呼叫時,直接呼叫A updateUser/B. updateUser即可 。如下:
<sqlMap>
<typeAlias type="com.admin.entity.Admin" alias="Admin" />
<select id="Admin.findUserByLoginName" parameterClass="java.lang.String"
resultMap="AdminResult">
select * from T_ADMINISTRATORS where longinName = #value#
and status != 4
</select>
呼叫時,getSqlMapClientTemplate.queryForList(“Admin.findUserByLoginName”,”test”);即可。
請注意:
此時需要保證所有對映檔案中,Statement定義無重名。
第二:
resultMap:結果對映,需結合resultMap節點對對映關係加以定義。
<sqlMap>
<typeAlias type="com.admin.entity.Admin" alias="Admin" />
<resultMap id="AdminResult" class="Admin">
<result column="staff_id" property="id" />
<result column="loginName" property="loginName" />
<result column="password" property="password" />
<result column="staff_name" property="username" />
<result column="status" property="status" />
<result column="phone" property="phone" />
<result column="email" property="email" />
</resultMap>
<select id="Admin.findUserByLoginName" parameterClass="java.lang.String"
resultMap="AdminResult">
select * from T_ADMINISTRATORS where longinName = #value#
and status != 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各種引數資料集 原型引數
<select id="select1" parameterClass="java.lang.String" resultClass="AppLog">
select
ID as id,
TYPE as type,
DESCR as descr
from APP_LOG
where ID = #id#
</select>
sqlMapper.queryForObject("select0", id); --引數名與傳入值名稱一樣。--應該也可用引數#value#表示
Map類引數
<select id="select2" parameterClass="java.util.HashMap" resultClass="AppLog">
select
ID as id,
TYPE as type,
DESCR as descr
from APP_LOG
where ID = #ids#
</select>
map.put("ids", id);
AppLog log = (AppLog) sqlMapper.queryForObject("select0", map); --通過key來獲取值
物件引數
<select id="select3" parameterClass="AppLog" resultClass="AppLog">
select
ID as id,
TYPE as type,
DESCR as descr
from APP_LOG
where ID = #id#
</select>
AppLog p=new AppLog();
p.setId(id);
AppLog log = (AppLog) sqlMapper.queryForObject("select3", p); 動態欄位、表
<select id="selectd" resultClass="java.util.HashMap" parameterClass="java.util.HashMap" remapResults="true">
select $fieldList$
from $table$
where ID = #id#
</select>
Map p = new HashMap();
p.put("id", id);
p.put("table","APP_LOG");
p.put("fieldList", "ID,TYPE,DESCR");
Map map = (Map) sqlMapper.queryForObject("selectd", p);
String id1 = (String) map.get("ID");
String type = (String) map.get("TYPE");
String descr = (String) map.get("DESCR"); 注意:#與$區別:
1.#是把傳入的資料當作字串,如#field#傳入的是id,則sql語句生成是這樣,order by "id",這當然會報錯..
2.$傳入的資料直接生成在sql裡,如#field#傳入的是id,則sql語句生成是這樣,order by id, 這就對了.
$方式一般用於傳入資料庫物件.例如傳入表名. #方式一般用於傳入插入/更新的值或查詢/刪除的where條件 ibatis各種返回資料集
別名對映->實體類 + resultClass
<select id=" selectAll" resultClass="AppLog">
select
ID as id,
TYPE as type,
DESCR as descr
from APP_LOG
where ID = #id#
</select>
List list = sqlMapper.queryForList("selectAll");
for (int i = 0; i < list.size(); i ) {
AppLog log = (AppLog) list.get(i);
//add your code here;
}
注意:
為什麼定義了resultClass="AppLog",而queryForList出來的是list?
這裡的resultClass="AppLog",是指查詢出來的每條記錄的格式是AppLog。
當我們queryForList時,系統會將各條記錄(即各個AppLog放到list中)傳回給我們。當我們queryForObject時,就只傳回一個AppLog。
別名對映->Map類+resultClass --》把每條記錄放於map中,欄位名為key,值為value.
<select id=" selectAll" resultClass="java.util.HashMap">
select
ID as id,
TYPE as type,
DESCR as descr
from APP_LOG
where ID = #id#
</select>
List list = sqlMapper.queryForList("selectAll");
for (int i = 0; i < list.size(); i ) {
Map map = (Map) list.get(i);
String id = (String) map.get("id");
String type = (String) map.get("type");
String descr = (String) map.get("descr");
//add your code here;
} 無對映
<select id="selectAll3" resultClass="java.util.HashMap">
select * from APP_LOG
</select>
List list = sqlMapper.queryForList("selectAll3");
for (int i = 0; i < list.size(); i ) {
Map map = (Map) list.get(i);
String id = (String) map.get("ID");
String type = (String) map.get("TYPE");
String descr = (String) map.get("DESCR");
}
顯式對映->實體類:resultMap
<resultMap id="AppLogResult" class="AppLog">
<result property="id" column="ID"/>
<result property="type" column="Type"/>
<result property="descr" column="DESCR"/>
</resultMap>
<select id="selectAll" resultMap="AppLogResult">
select * from APP_LOG
</select>
List list = sqlMapper.queryForList("selectAll");
for (int i = 0; i < list.size(); i ) {
AppLog log = (AppLog) list.get(i);
//add your code here;
}
顯式對映->Map類:resultMap --》把每條記錄放於map中,欄位名為key,值為value.
<resultMap id="map-result" class="java.util.HashMap">
<result property="id" column="ID"/>
<result property="type" column="Type"/>
<result property="descr" column="DESCR"/>
</resultMap>
<select id="selectAll2" resultMap="map-result">
select * from APP_LOG
</select>
List list = sqlMapper.queryForList("selectAll2");
for (int i = 0; i < list.size(); i ) {
Map map = (Map) list.get(i);
String id = (String) map.get("id");
String type = (String) map.get("type");
String descr = (String) map.get("descr");
} 又如:
map.put("appIds", Ids);
executor.update("Device.OpenClientApp", map);
下面的property屬性及迴圈變數,都是對應map的key名。
-----證明,ibatis對於hashmap,都是通過key來獲取值的。所以,所有引數須用key來表示!!!
如下:
<update id="Device.OpenClientApp" parameterClass="java.util.HashMap">
update T_Device_App_R_Info set Opr='1' where App_ID in
<iterate conjunction="," open="(" close=")" property="appIds">
#appIds[]#
</iterate>
</update>
例子:
<statement id=”statementName” parameterClass=” examples.domain.Product”>
insert into PRODUCT values (#id#, #description#, #price#, #classify.id#)
</statement> 藍色部分#classify.id#翻譯過來實際是product.getClassify().getId(),classify是Product物件的一個子物件。 (4)關於引數的三種設定方法 及 ParameterMap用法 前提:有一個user的javabean. 一,自動引數對映:
<insert id="insertUser7" parameterClass="user">
<![CDATA[
INSERT INTO t_user ( ID, NAME, PASS )VALUES( #id#,#name#,#pass# )
]]>
</insert>
二,內聯引數對映:
<insert id="insertUser8" parameterClass="user">
<![CDATA[
INSERT INTO t_user ( ID, NAME, PASS ) VALUES( #id:INT#, #name:VARCHAR#, #pass:VARCHAR# )
]]>
</insert> 備註: 好像將屬性對應的資料型別故意寫錯,程式也可正常執行,沒報錯.
三,外聯引數對映: 以上二種方式都用paramClass,但此處用parameterMap.
<parameterMap id="parameterMap" class="user">
<parameter property="id" jdbcType="INTEGER" />
<parameter property="name" jdbcType="VARCHAR" />
<parameter property="pass" jdbcType="VARCHAR" />
</parameterMap>
<insert id="insertUser9" parameterMap="parameterMap">
<![CDATA[
INSERT INTO t_user ( ID, NAME, PASS )VALUES( ?,?,? )
]]>
</insert> 若此處的物件不是javabean,而是一個hashMap.用法也一樣,只是id,name,pass不是javabean的屬性,而是hashMap的key.
在資料庫持久層的框架中,大家一定聽過Hibernate的大名了吧,經典的SSH框架就有它的一份哦!可是我今天要說的卻是另外一個持久層的框架,它就是iBatis。與Hibrenate相比,它的主要優勢就是簡單、小巧、輕量級,但是它的功能卻絲毫不亞於 Hibernate,下面讓我們來看看iBatis在專案中的應用吧! iBatis確實很簡單,它的工作原理就是通過SQL Map對映檔案將sql語句和java物件對應起來(如:在利用物件屬性的getter從屬性中獲取值,查詢結果後,將各值用setter方法放到物件中).在iBatis中,sql語句是我們手工編寫好的,這一點與Hibernate不同,Hibernate是通過對映java物件和資料庫表字段來自動生成的sql語句。 (2)
<sqlMap namespace="admin">在運用時如下:
this.getSqlMapClient().update(“admin.update”, entity);
分析:
ibatis 配置檔案中的useStatementNamespaces:是否使用Statement名稱空間。這裡的名稱空間指的是對映檔案中,sqlMap節點的 namespace屬性,如:<sqlMap namespace="User">。這裡,指定了此sqlMap節點下定義的操作均從屬於"User"名稱空間。
在 useStatementNamespaces="true"的情況下,Statement呼叫需追加名稱空間,如:sqlMap.update("User.updateUser",user);否則直接通過Statement名稱呼叫即可,如:sqlMap.update("updateUser",user);
好處:
在實際應用中,利用namespace可以防止兩個同名的方法而引起衝突。如有兩個updateUser,可以通過A updateUser/B. updateUser來區分。
另一種方法:
但有一種更方便的方法,可以在不採用namspace的情況下,解決上面的問題:即直接在方法的前面直接命名為A updateUser/B. updateUser。呼叫時,直接呼叫A updateUser/B. updateUser即可
<sqlMap>
<typeAlias type="com.admin.entity.Admin" alias="Admin" />
<select id="Admin.findUserByLoginName" parameterClass="java.lang.String"
resultMap="AdminResult">
select * from T_ADMINISTRATORS where longinName = #value#
and status != 4
</select>
呼叫時,getSqlMapClientTemplate.queryForList(“Admin.findUserByLoginName”,”test”);即可。
請注意:
此時需要保證所有對映檔案中,Statement定義無重名。
第二:
resultMap:結果對映,需結合resultMap節點對對映關係加以定義。
<sqlMap>
<typeAlias type="com.admin.entity.Admin" alias="Admin" />
<resultMap id="AdminResult" class="Admin">
<result column="staff_id" property="id" />
<result column="loginName" property="loginName" />
<result column="password" property="password" />
<result column="staff_name" property="username" />
<result column="status" property="status" />
<result column="phone" property="phone" />
<result column="email" property="email" />
</resultMap>
<select id="Admin.findUserByLoginName" parameterClass="java.lang.String"
resultMap="AdminResult">
select * from T_ADMINISTRATORS where longinName = #value#
and status != 4
</select>
</sqlMap> (3)關於ibatis中輸入/輸出各種型別的引數分析
resultclass/resultMap的型別大都是:物件/hashmap 當parameterClass為string,int時,可用#value#表示或直接用傳入的值名錶示。
當parameterClass/resultMap的型別是物件時,用#屬性#表示。程式會呼叫JAVABEAN的getter方法,進行獲取屬性值。
當parameterClass/resultMap的型別是hashmap(Map是key-value結構的)時,那程式會直接通過key來分析取引數。 具體請見以下兩部分: ibatis各種引數資料集 原型引數
<select id="select1" parameterClass="java.lang.String" resultClass="AppLog">
select
ID as id,
TYPE as type,
DESCR as descr
from APP_LOG
where ID = #id#
</select>
sqlMapper.queryForObject("select0", id); --引數名與傳入值名稱一樣。--應該也可用引數#value#表示
Map類引數
<select id="select2" parameterClass="java.util.HashMap" resultClass="AppLog">
select
ID as id,
TYPE as type,
DESCR as descr
from APP_LOG
where ID = #ids#
</select>
map.put("ids", id);
AppLog log = (AppLog) sqlMapper.queryForObject("select0", map); --通過key來獲取值
物件引數
<select id="select3" parameterClass="AppLog" resultClass="AppLog">
select
ID as id,
TYPE as type,
DESCR as descr
from APP_LOG
where ID = #id#
</select>
AppLog p=new AppLog();
p.setId(id);
AppLog log = (AppLog) sqlMapper.queryForObject("select3", p); 動態欄位、表
<select id="selectd" resultClass="java.util.HashMap" parameterClass="java.util.HashMap" remapResults="true">
select $fieldList$
from $table$
where ID = #id#
</select>
Map p = new HashMap();
p.put("id", id);
p.put("table","APP_LOG");
p.put("fieldList", "ID,TYPE,DESCR");
Map map = (Map) sqlMapper.queryForObject("selectd", p);
String id1 = (String) map.get("ID");
String type = (String) map.get("TYPE");
String descr = (String) map.get("DESCR"); 注意:#與$區別:
1.#是把傳入的資料當作字串,如#field#傳入的是id,則sql語句生成是這樣,order by "id",這當然會報錯..
2.$傳入的資料直接生成在sql裡,如#field#傳入的是id,則sql語句生成是這樣,order by id, 這就對了.
$方式一般用於傳入資料庫物件.例如傳入表名. #方式一般用於傳入插入/更新的值或查詢/刪除的where條件 ibatis各種返回資料集
別名對映->實體類 + resultClass
<select id=" selectAll" resultClass="AppLog">
select
ID as id,
TYPE as type,
DESCR as descr
from APP_LOG
where ID = #id#
</select>
List list = sqlMapper.queryForList("selectAll");
for (int i = 0; i < list.size(); i ) {
AppLog log = (AppLog) list.get(i);
//add your code here;
}
注意:
為什麼定義了resultClass="AppLog",而queryForList出來的是list?
這裡的resultClass="AppLog",是指查詢出來的每條記錄的格式是AppLog。
當我們queryForList時,系統會將各條記錄(即各個AppLog放到list中)傳回給我們。當我們queryForObject時,就只傳回一個AppLog。
別名對映->Map類+resultClass --》把每條記錄放於map中,欄位名為key,值為value.
<select id=" selectAll" resultClass="java.util.HashMap">
select
ID as id,
TYPE as type,
DESCR as descr
from APP_LOG
where ID = #id#
</select>
List list = sqlMapper.queryForList("selectAll");
for (int i = 0; i < list.size(); i ) {
Map map = (Map) list.get(i);
String id = (String) map.get("id");
String type = (String) map.get("type");
String descr = (String) map.get("descr");
//add your code here;
} 無對映
<select id="selectAll3" resultClass="java.util.HashMap">
select * from APP_LOG
</select>
List list = sqlMapper.queryForList("selectAll3");
for (int i = 0; i < list.size(); i ) {
Map map = (Map) list.get(i);
String id = (String) map.get("ID");
String type = (String) map.get("TYPE");
String descr = (String) map.get("DESCR");
}
顯式對映->實體類:resultMap
<resultMap id="AppLogResult" class="AppLog">
<result property="id" column="ID"/>
<result property="type" column="Type"/>
<result property="descr" column="DESCR"/>
</resultMap>
<select id="selectAll" resultMap="AppLogResult">
select * from APP_LOG
</select>
List list = sqlMapper.queryForList("selectAll");
for (int i = 0; i < list.size(); i ) {
AppLog log = (AppLog) list.get(i);
//add your code here;
}
顯式對映->Map類:resultMap --》把每條記錄放於map中,欄位名為key,值為value.
<resultMap id="map-result" class="java.util.HashMap">
<result property="id" column="ID"/>
<result property="type" column="Type"/>
<result property="descr" column="DESCR"/>
</resultMap>
<select id="selectAll2" resultMap="map-result">
select * from APP_LOG
</select>
List list = sqlMapper.queryForList("selectAll2");
for (int i = 0; i < list.size(); i ) {
Map map = (Map) list.get(i);
String id = (String) map.get("id");
String type = (String) map.get("type");
String descr = (String) map.get("descr");
} 又如:
map.put("appIds", Ids);
executor.update("Device.OpenClientApp", map);
下面的property屬性及迴圈變數,都是對應map的key名。
-----證明,ibatis對於hashmap,都是通過key來獲取值的。所以,所有引數須用key來表示!!!
如下:
<update id="Device.OpenClientApp" parameterClass="java.util.HashMap">
update T_Device_App_R_Info set Opr='1' where App_ID in
<iterate conjunction="," open="(" close=")" property="appIds">
#appIds[]#
</iterate>
</update>
例子:
<statement id=”statementName” parameterClass=” examples.domain.Product”>
insert into PRODUCT values (#id#, #description#, #price#, #classify.id#)
</statement> 藍色部分#classify.id#翻譯過來實際是product.getClassify().getId(),classify是Product物件的一個子物件。 (4)關於引數的三種設定方法 及 ParameterMap用法 前提:有一個user的javabean. 一,自動引數對映:
<insert id="insertUser7" parameterClass="user">
<![CDATA[
INSERT INTO t_user ( ID, NAME, PASS )VALUES( #id#,#name#,#pass# )
]]>
</insert>
二,內聯引數對映:
<insert id="insertUser8" parameterClass="user">
<![CDATA[
INSERT INTO t_user ( ID, NAME, PASS ) VALUES( #id:INT#, #name:VARCHAR#, #pass:VARCHAR# )
]]>
</insert> 備註: 好像將屬性對應的資料型別故意寫錯,程式也可正常執行,沒報錯.
三,外聯引數對映: 以上二種方式都用paramClass,但此處用parameterMap.
<parameterMap id="parameterMap" class="user">
<parameter property="id" jdbcType="INTEGER" />
<parameter property="name" jdbcType="VARCHAR" />
<parameter property="pass" jdbcType="VARCHAR" />
</parameterMap>
<insert id="insertUser9" parameterMap="parameterMap">
<![CDATA[
INSERT INTO t_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]); <!-- 自動引數對映方式 --> <insert id="DAPermit.addAppDevMapping" parameterClass="java.util.HashMap"> insert into T_Device_App_R_Info(Device_ID,App_ID,Opr) values (#devId#,#appId#,'2'); </insert> <!-- 內聯方式: <insert id="DAPermit.addAppDevMapping" parameterClass="java.util.HashMap"> insert into T_Device_App_R_Info(Device_ID,App_ID,Opr) values (#devId:varchar#,#appId:varchar#,'2'); </insert> 外聯方式: <parameterMap id="dapermitParams" class="java.util.HashMap"> <parameter property="devId" jdbcType="VARCHAR"/> <parameter property="appId" jdbcType="VARCHAR"/> </parameterMap> <insert id="DAPermit.addAppDevMapping" parameterMap="dapermitParams"> insert into T_Device_App_R_Info(Device_ID,App_ID,Opr) values (?,?,'2'); </insert> -->四,利用parameterMap呼叫儲存過程:
<!-- example 11: 儲存過程 -->
<resultMap id="returnResultMap" class="user">
<result property="id" column="ID" />
</resultMap>
<parameterMap id="paramUser" class="java.util.Map">
<parameter property="name" jdbcType="VARCHAR" javaType="string" mode="IN" />
<parameter property="pass" jdbcType="VARCHAR" javaType="string" mode="IN" />
<parameter property="id" jdbcType="INT" javaType="Integer" mode="INOUT" resultMap="returnResultMap" />
</parameterMap>
<procedure id="pro_insertUser11" parameterMap="paramUser" resultClass="int">
<![CDATA[
{call proc_userinsert(?,?,?)}
]]>
</procedure>
然後在UserDaoTest.java中增加如下一個方法:
public static void example11() throws Exception {
try {
Map map = new HashMap();
map.put("name", "procedure");
map.put("pass", "123456");
Integer returnValue = (Integer)sqlMapClient.insert("pro_insertUser11", map);
System.out.println(returnValue);
} catch (Exception e) {
e.printStackTrace();
}
}