iBatis2学习笔记:入参和返回值的问题
iBatis2的难点之一就是如何处理好入参parameterClass和返回值(resultClass或resultMap)的问题。
一、入参问题
插入语句入参:parameterClass="类别名" 来设定。
查询语句入参:可以设定类别名,也可以设定为map,也可以设定为iBatis支持的原生类型(比如string、int、long等),当只有一个原生类型入参时,则在SQL中用value关键字来引用。比如:
<select id="getById" parameterClass="long" resultMap="result_base">
select * from customer where id = #value#
</select>
map是最强大的入参方式,任何入参方式都可以转换为这种入参方式,因为iBatis仅接受一个入参,当几个参数分布在不同对象中的时候,将这些对象的属性(或者对象本身put)到map中,然后一次传递给sql语句是非常有效。可以自己写一个将对象或者对象集合转换为map的工具(我已经实现一个了)。
另外,map的中的元素(比如pobj)是个复杂对象,则还可以在SQL中以#pobj.protyename#的格式来引用其中内嵌的属性。当然不推荐这么干。
SQL中引用parameterClass的参数有三种方式:
iBatis内置支持的类型,比如int、string,使用#value#来引用,这个value是关键字,不可变。
map类型的参数,使用#keyName#来引用,keyName为键名。
复杂对象的参数,使用#propertyName#来引用,propertyName类属性的名字。
模糊查询中参数的引用:模糊查询是针对字符串而言的,如果遇到两个单引号要包含一个参数,则不能再用#来引用变量了,而应该改为$,比如:'%$varName$%',当然,也可以使用 '%' || #varname# || '%' 来绕过此问题。
iBatis内置支持的类型,比如int、string,使用#value#来引用,这个value是关键字,不可变。
map类型的参数,使用#keyName#来引用,keyName为键名。
复杂对象的参数,使用#propertyName#来引用,propertyName类属性的名字。
模糊查询中参数的引用:模糊查询是针对字符串而言的,如果遇到两个单引号要包含一个参数,则不能再用#来引用变量了,而应该改为$,比如:'%$varName$%',当然,也可以使用 '%' || #varname# || '%' 来绕过此问题。
二、返回值的问题
下面通过一个例子详细讲述,此例子以本人iBatis2学习笔记:基本原理和配置为基础讲述:
表和实体的代码
表:
create table ACCOUNT(
ACC_ID bigint not null AUTO_INCREMENT,
ACC_FIRST_NAME varchar(20) default NULL,
ACC_LAST_NAME varchar(30) default NULL,
ACC_EMAIL varchar(30) default NULL,
PRIMARY KEY(ACC_ID)
) ENGINE=MyISAM DEFAULT CHARSET=gbk COMMENT='IBATIS简单测试'
ACC_ID bigint not null AUTO_INCREMENT,
ACC_FIRST_NAME varchar(20) default NULL,
ACC_LAST_NAME varchar(30) default NULL,
ACC_EMAIL varchar(30) default NULL,
PRIMARY KEY(ACC_ID)
) ENGINE=MyISAM DEFAULT CHARSET=gbk COMMENT='IBATIS简单测试'
实体类:
public class Account {
private int id;
private String firstName;
private String lastName;
private String emailAddress;
private int id;
private String firstName;
private String lastName;
private String emailAddress;
可以看到表列字段名和实体属性名完全不对应!!
下面给出一个完全正确的合理的映射:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="Account">
<typeAlias alias="Account" type="com.lavasoft.ibatissut.simple.domain.entity.Account"/>
<resultMap id="AccountResult" class="Account" >
<result property="id" column="ACC_ID"/>
<result property="firstName" column="ACC_FIRST_NAME"/>
<result property="lastName" column="ACC_LAST_NAME"/>
<result property="emailAddress" column="ACC_EMAIL"/>
</resultMap>
<select id="selectAllAccounts" resultMap="AccountResult">
select * from ACCOUNT
</select>
<select id="selectAccountById" parameterClass="int" resultClass="Account">
select
ACC_ID as id,
ACC_FIRST_NAME as firstName,
ACC_LAST_NAME as lastName,
ACC_EMAIL as emailAddress
from ACCOUNT
where ACC_ID = #id#
</select>
</sqlMap>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="Account">
<typeAlias alias="Account" type="com.lavasoft.ibatissut.simple.domain.entity.Account"/>
<resultMap id="AccountResult" class="Account" >
<result property="id" column="ACC_ID"/>
<result property="firstName" column="ACC_FIRST_NAME"/>
<result property="lastName" column="ACC_LAST_NAME"/>
<result property="emailAddress" column="ACC_EMAIL"/>
</resultMap>
<select id="selectAllAccounts" resultMap="AccountResult">
select * from ACCOUNT
</select>
<select id="selectAccountById" parameterClass="int" resultClass="Account">
select
ACC_ID as id,
ACC_FIRST_NAME as firstName,
ACC_LAST_NAME as lastName,
ACC_EMAIL as emailAddress
from ACCOUNT
where ACC_ID = #id#
</select>
</sqlMap>
当结果集列名和类属性名完全对应的时候,则应该使用resultClass来指定查询结果类型。当然有些列明不对应,可以在sql中使用as重命名达到一致的效果。
当查询结果列名和类属性名对应不上的时候,应该选择resultMap指定查询结果集类型。否则,则查询出来填充的对象属性为空(数字的为0,对象的为null)。
由于select *语句结果集列名与类属性名不对应,则需要使用显式resultMap="AccountResult"来指定映射关系。
而<select id="selectAccountById"查询则对没个字段做了重命名,与实体属性名保持一致,则结果集自动映射到类属性上。因此可以直接使用类做结果集返回类型,而不用再做额外的映射工作。