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不須要不少代碼,但它的效率就慢了,沒有強類型的檢測。 
相關文章
相關標籤/搜索