iBatis查询select详解

编程技术  /  houtizong 发布于 3年前   87
[align=center][/align][color=red][/color]   <select>是iBatis已经映射的语句类型,就是查询了,为了配合说明,这里再介绍两个标记:<sql>和<include>,前者用来创建一个文本片段,这些片段可以组合起来创建完整的SQL语句;后者很显然就是包含的意思了。假设我们有如下代码段:

Xml代码 
1.<sql id="select-user"> 
2.    select * from users  
3.</sql> 
4.<sql id="select-count"> 
5.    select count(*) as value from users  
6.</sql> 
7.<sql id="where-age-over-value"> 
8.    <![CDATA[ 
9.        where age > #value:INT# 
10.    ]]> 
11.</sql> 
12.<select id="getUserAgeOver" resultClass="hashmap"> 
13.    <include refid="select-user" /> 
14.    <include refid="where-age-over-value" /> 
15.</select> 
16.<select id="getUserCountAgeOver" resultClass="int"> 
17.    <include refid="select-count" /> 
18.    <include refid="where-age-over-value" /> 
19.</select> 
<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标签冲突的字符,这很好理解。后面两个查询就是我们执行的语句部分,程序代码可以这么来写:

Java代码 
1.List users = sqlMap.queryForList("User.getUserAgeOver","23");  
2.System.out.println(users);  
3.int userCount = (Integer) sqlMap.queryForObject(  
4.    "User.getUserCountAgeOver", "22");  
5.System.out.println(userCount); 
List users = sqlMap.queryForList("User.getUserAgeOver","23");
System.out.println(users);
int userCount = (Integer) sqlMap.queryForObject(
"User.getUserCountAgeOver", "22");
System.out.println(userCount);
    如果可以查询到记录,那么就会打印出来了。上面的例子中我们是用了#来标识传递的参数,#被成为占位符,这是内联参数的传递方式的一种。

Xml代码 
1.<select id="getUserById" resultClass="User"> 
2.    select  
3.        userId,  
4.        userName,  
5.        password,  
6.        age,  
7.        mobile,  
8.        mail  
9.    from  
10.        users  
11.    where  
12.        userId = #value#  
13.</select> 
<select id="getUserById" resultClass="User">
select
userId,
userName,
password,
age,
mobile,
mail
from
users
where
userId = #value#
</select>
    在程序中,用下面这些代码就能达到查询效果了。

Java代码 
1.User user = (User) sqlMap.queryForObject("User.getUserById", new Integer(1));  
2.System.out.println(user); 
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注入有机可乘,而且过度使用还会有性能问题,看下面这个语句:

Xml代码 
1.<select id="getUserByLikeEmail" resultClass="User"> 
2.    select  
3.        userId,  
4.        userName,  
5.        password,  
6.        age,  
7.        mobile,  
8.        email  
9.    from  
10.        users  
11.    where  
12.        email like '%$value$%'  
13.</select> 
<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中,那么我们不会得到任何数据,而且执行不会报错。自动映射使用起来很方便,但是更稳健的要数外部结果映射了。
    如果语句中的字段可变,那么可以使用动态结果映射,如:

Xml代码 
1.<select id="getUserByLikeEmail" resultClass="User" parameterClass="parameterMap"> 
2.    select  
3.        userId,  
4.        userName,  
5.    <dynamic> 
6.        <isEqual property="includePassword" compareValue="true"> 
7.            password,  
8.        </isEqual> 
9.    </dynamic> 
10.        age,  
11.        mobile,  
12.        email  
13.    from   
14.        users   
15.    where   
16.        email like concat('%',#email#,'%')  
17.</select> 
<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类型,然后执行查询,如下:

Java代码 
1.ParameterMap params = new ParameterMap("email", "gmail",  
2.        "includePassword", true);  
3.List users = sqlMap.queryForList("User.getUserByLikeEmail", params);  
4.System.out.println(users); 
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是如下定义的:

Java代码 
1.package ibatis.util;  
2.import java.util.HashMap;  
3.public class ParameterMap extends HashMap<Object, Object> {  
4.    private static final long serialVersionUID = 1L;  
5.    public ParameterMap(Object... parameters) {  
6.        for (int i = 0; i < parameters.length - 1; i += 2) {  
7.            super.put(parameters[i], parameters[i + 1]);  
8.        }  
9.    }  
10.} 
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的类型:

Java代码 
1.package ibatis.util;  
2.public class PrimitiveResult {  
3.    private int userCount;  
4.    public int getUserCount() {  
5.        return userCount;  
6.    }  
7.    public void setUserCount(int userCount) {  
8.        this.userCount = userCount;  
9.    }  
10.    @Override 
11.    public String toString() {  
12.        return "PrimitiveResult [userCount=" + userCount + "]";  
13.    }  
14.} 
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中定义这个类型:

Xml代码 
1.<resultMap class="ibatis.util.PrimitiveResult" id="primitiveResultMap"> 
2.<result property="userCount" column="userCount" javaType="java.lang.Integer" jdbcType="int" /> 
3.</resultMap> 
<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对象的类型和数据库字段的类型。
    下面来看看查询部分的定义:

Xml代码 
1.<select id="selectPrimitiveByUserId" resultMap="primitiveResultMap"> 
2.    select  
3.        count(*) as userCount  
4.    from  
5.        users  
6.</select> 
<select id="selectPrimitiveByUserId" resultMap="primitiveResultMap">
select
count(*) as userCount
from
users
</select>
    注意这里是resultMap就行了,不再是resultClass了,下面就是程序代码了:

Java代码 
1.PrimitiveResult userCount = (PrimitiveResult) sqlMap.queryForObject(  
2.            "User.selectPrimitiveByUserId");  
3.System.out.println(userCount); 
PrimitiveResult userCount = (PrimitiveResult) sqlMap.queryForObject(
"User.selectPrimitiveByUserId");
System.out.println(userCount);
    因为我们之前在PrimitiveResult中覆盖了toString()方法,那么我们执行程序,就得到了:PrimitiveResult [userCount=2],这就是外部结果映射的使用了。
    最后我们来比较一下javabean的结果映射和map结果映射。Javabean形式的映射都是我们手写的bean类,而map就直接使用,是内联情况的。它们各有好处也有缺点。比如使用javabean那么性能很好,而且是强类型检测,缺点是很多的get/set方法。而用map不需要很多代码,但它的效率就慢了,没有强类型的检测。
    一家之言,仅供参考,欢迎交流,希望对使用者有用。

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!

留言需要登陆哦

技术博客集 - 网站简介:
前后端技术:
后端基于Hyperf2.1框架开发,前端使用Bootstrap可视化布局系统生成

网站主要作用:
1.编程技术分享及讨论交流,内置聊天系统;
2.测试交流框架问题,比如:Hyperf、Laravel、TP、beego;
3.本站数据是基于大数据采集等爬虫技术为基础助力分享知识,如有侵权请发邮件到站长邮箱,站长会尽快处理;
4.站长邮箱:[email protected];

      订阅博客周刊 去订阅

文章归档

文章标签

友情链接

Auther ·HouTiZong
侯体宗的博客
© 2020 zongscan.com
版权所有ICP证 : 粤ICP备20027696号
PHP交流群 也可以扫右边的二维码
侯体宗的博客