iBatis查询select笔记

<select>是iBatis已经映射的语句类型,就是查询了,为了配合说明,这里再介绍两个标记:<sql>和<include>,前者用来建立一个文本片断,这些片断能够组合起来建立完整的SQL语句;后者很显然就是包含的意思了。假设咱们有以下代码段: java

<sql id="select-user">  
    select * from users  
</sql>  
<sql id="select-count">  
    select count(*) as value from users  
</sql>  
<sql id="where-age-over-value">  
    <![CDATA[ 
        where age > #value:INT# 
    ]]>  
</sql>  
<select id="getUserAgeOver" resultClass="hashmap">  
    <include refid="select-user" />  
    <include refid="where-age-over-value" />  
</select>  
<select id="getUserCountAgeOver" resultClass="int">  
    <include refid="select-count" />  
    <include refid="where-age-over-value" />  
</select>


该部分代码展现了sql和include的使用,其中使用了CDATA段,这是由于XML标签本体中出现了于XML标签冲突的字符,这很好理解。后面两个查询就是咱们执行的语句部分,程序代码能够这么来写:
sql

List users = sqlMap.queryForList("User.getUserAgeOver","23");  
System.out.println(users);  
int userCount = (Integer) sqlMap.queryForObject(  
    "User.getUserCountAgeOver", "22");  
System.out.println(userCount);
若是能够查询到记录,那么就会打印出来了。上面的例子中咱们是用了#来标识传递的参数,#被成为占位符,这是内联参数的传递方式的一种。

<select id="getUserById" resultClass="User">  
    select  
        userId,  
        userName,  
        password,  
        age,  
        mobile,  
        mail  
    from  
        users  
    where  
        userId = #value#  
</select>
在程序中,用下面这些代码就能达到查询效果了。

User user = (User) sqlMap.queryForObject("User.getUserById", new Integer(1));  
System.out.println(user);
 #value#是告诉iBatis传递一个简单的参数,iBatis处理该语句时,将会把#value#转换为预处理参数形式,而后将这个参数的值设置为1(就是queryForObject()方法的第二个参数),以后执行该预处理语句。最后iBatis接受返回的结果,而后把它映射到一个Java对象并返回该对象,这就是sqlMap的执行过程。 
    下面来看另一种内联参数形式,就是使用$做为占位符。它能够直接把参数插入到SQL语句中,这在该SQL语句被转变为参数化语句以前就执行了。如此就会留下安全隐患,它可能给SQL注入有隙可乘,并且过分使用还会有性能问题,看下面这个语句: 

<select id="getUserByLikeEmail" resultClass="User">  
    select  
        userId,  
        userName,  
        password,  
        age,  
        mobile,  
        email  
    from  
        users  
    where  
        email like '%$value$%'  
</select>
在程序中,咱们可使用以下代码来执行模糊查询: 
List<User> users = sqlMap.queryForList("User.getUserByLikeEmail", "gmail"); 
System.out.println(users); 
    若要使用#方式来当占位符,那么模糊查询时可能不是那么方便,须要以下进行:email like concat('%',#value#,'%'),这是MySQL的状况。因此模糊查询使用$比较方便。 
    以上的查询中咱们使用了resultClass这种自动结果映射,这是iBatis的一种执行机制,而咱们也能够进行自定义结果映射,就是使用resultMap。若是咱们在查询中二者都没有使用的话,那么iBatis执行查询可是不能返回任何东西。 
    当咱们使用bean做为结果映射时要注意若是结果列存在于数据库而不存在于bean中,那么咱们不会获得任何数据,并且执行不会报错。自动映射使用起来很方便,可是更稳健的要数外部结果映射了。 
    若是语句中的字段可变,那么可使用动态结果映射,如:

<select id="getUserByLikeEmail" resultClass="User" parameterClass="parameterMap">  
    select  
        userId,  
        userName,  
    <dynamic>  
        <isEqual property="includePassword" compareValue="true">  
            password,  
        </isEqual>  
    </dynamic>  
        age,  
        mobile,  
        email  
    from   
        users   
    where   
        email like concat('%',#email#,'%')  
</select>
程序中咱们先定义一个ParameterMap类型,而后执行查询,以下:

ParameterMap params = new ParameterMap("email", "gmail",  
        "includePassword", true);  
List users = sqlMap.queryForList("User.getUserByLikeEmail", params);  
System.out.println(users);
这样咱们就能人为控制password字段是输出了。下面咱们来看外部参数映射,使用外部参数映射主要是在XML中定义parameterMap,标识它的id和class后再在其中定义parameter,它包括以下属性:property,javaType,jdbcType,nullValue,mode和typeHandler。要区分这和咱们上面定义的ParameterMap类型是两回事。咱们定义的ParameterMap是以下定义的:

package ibatis.util;  
import java.util.HashMap;  
public class ParameterMap extends HashMap<Object, Object> {  
    private static final long serialVersionUID = 1L;  
    public ParameterMap(Object... parameters) {  
        for (int i = 0; i < parameters.length - 1; i += 2) {  
            super.put(parameters[i], parameters[i + 1]);  
        }  
    }  
}
它是做为辅助类来用的,给SQL语句提供参数,在配置文件中,我没使用的是typeAlias来为它重命名的,并且在select标签中咱们使用的是parameterClass属性,而不是parameterMap属性,这里要区分开,它们能够说是彻底不一样的。 
    说完了外部参数映射,再说说外部结果映射。上面的例子中咱们使用的映射有JavaBean形式的,也有hashmap形式的,但要注意咱们是用的都是resultClass属性来标识它们的,它们都属于内联结果映射。外部结果映射是使用resultMap来定义的,咱们来看一个实例,来更直观的说明,首先定义一个resultMap的类型: 

package ibatis.util;  
public class PrimitiveResult {  
    private int userCount;  
    public int getUserCount() {  
        return userCount;  
    }  
    public void setUserCount(int userCount) {  
        this.userCount = userCount;  
    }  
    @Override  
    public String toString() {  
        return "PrimitiveResult [userCount=" + userCount + "]";  
    }  
}
很简单的一个类型,就是描述用户数量的。再在XML中定义这个类型:

<resultMap class="ibatis.util.PrimitiveResult" id="primitiveResultMap">  
<result property="userCount" column="userCount" javaType="java.lang.Integer" jdbcType="int" />  
</resultMap>
这里说明一下property就是定义PrimitiveResult中的一个属性名,这里是userCount,后面的column应该是数据库中的字段名,这里数据库中没有统计用户数量这个字段,咱们能够在SQL语句中使用as重命名来进行,javaType和jdbcType就好理解了,分别是Java对象的类型和数据库字段的类型。 
    下面来看看查询部分的定义: 

<select id="selectPrimitiveByUserId" resultMap="primitiveResultMap">  
    select  
        count(*) as userCount  
    from  
        users  
</select>
注意这里是resultMap就好了,再也不是resultClass了,下面就是程序代码了:

rimitiveResult userCount = (PrimitiveResult) sqlMap.queryForObject(  
            "User.selectPrimitiveByUserId");  
System.out.println(userCount);
由于咱们以前在PrimitiveResult中覆盖了toString()方法,那么咱们执行程序,就获得了:PrimitiveResult [userCount=2],这就是外部结果映射的使用了。 
    最后咱们来比较一下javabean的结果映射和map结果映射。Javabean形式的映射都是咱们手写的bean类,而map就直接使用,是内联状况的。它们各有好处也有缺点。好比使用javabean那么性能很好,并且是强类型检测,缺点是不少的get/set方法。而用map不须要不少代码,但它的效率就慢了,没有强类型的检测。 
相关文章
相关标签/搜索