映射器是MyBatis最強大的工具,也是我們使用MyBatis時用得做多的工具,因此熟練掌握它是十分必要的。MyBatis是針對映射器構造的SQL構建的輕量級框架,並且通過配置生成對應的JavaBean返回給調用者,而這些配置主要便是映射器。
映射器的主要元素
select元素
select元素常用配置:
舉例:
<select id="findAll" resultType="user">
select
<include refid="column_list" />
from user
</select>
其中user表示User對象的別名,這裏的id標識了這條SQL,resultType定義返回值類型
使用Map傳遞參數
<resultMap type="com.example.demo.entity.User" id="UserMap">
<id column="id" jdbcType="BIGINT" property="id" />
<!-- 兩種方式 使用自定義的typeHandler -->
<!-- <result column="name" property="name" javaType="string" jdbcType="VARCHAR"
/> -->
<result column="name" property="name"
typeHandler="com.example.demo.handler.MyStringTypeHandler" />
<result column="sex" property="sex"
typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler" />
<result column="age" property="age" jdbcType="INTEGER" />
</resultMap>
<sql id="column_list">
id,name,age
</sql>
<select id="findAll" parameterMap="map" resultMap="UserMap">
select
<include refid="column_list" />
from user
where name=#{name}
</select>
與之對應的,我們定義了一個接口方法
List<User> findAll (Map<String,String> params);
//在調用時:
Map<String,String> paramsMap=new HashMap<>;
paramsMap.put("name","wojiushiwo");
userMapper.findAll(paramsMap);//這裏未給出userMapper的定義
這種方法雖然簡單易用,但是有一個弊端:由於Map需要鍵值對應,由於業務關聯性不強,造成代碼可讀性下降。
使用註解方法傳遞參數
我們需要使用MyBatis的參數註解@Param來實現想要的功能,如
//接口如下:
List<User> findAll (@Param("name") String name);
//查詢方式:
<sql id="column_list">
id,name,age
</sql>
<select id="findAll" resultMap="UserMap">
select
<include refid="column_list" />
from user
where name=#{name}
</select>
當我們把參數傳遞給後臺的時候,通過@Param提供的名稱MyBatis就會知道#{name}代表name參數,參數的可讀性大大提高。但是如果參數較多的情況下,這種情況就不適用了。
使用JavaBean傳遞參數
在參數過多的情況下,Mybatis允許組織一個JavaBean,通過簡單的getter和setter方法設置參數,這樣可以提高我們的可讀性。
public class User{
private Long id;
private String name;
private int age;
...
}
//查詢方式改爲:
<select id="findAll" parameterType="user" resultMap="UserMap">
select
id,age,name
from user
where name=#{name}
</select>
//這裏的user是實體類的別名,在Mybatis-conf.xml文件中配置的
使用resultMap映射結果集
其實在上面我們已經使用過了resultMap,現在我們大概瞭解一下其內部構造吧。
<resultMap type="com.example.demo.entity.User" id="UserMap">
<id column="id" jdbcType="BIGINT" property="id" />
<!-- 兩種方式 使用自定義的typeHandler -->
<!-- <result column="name" property="name" javaType="string" jdbcType="VARCHAR"
/> -->
<result column="name" property="name"
typeHandler="com.example.demo.handler.MyStringTypeHandler" />
<result column="sex" property="sex"
typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler" />
<result column="age" property="age" jdbcType="INTEGER" />
</resultMap>
定義了一個唯一標識(id)爲UserMap的resultMap,用type屬性去定義它對用的是哪個JavaBean(也可以使用別名)
通過id元素定義resultResultMap,這個對象代表着使用哪個屬性作爲其主鍵,result元素定義普通列的映射關係,例如,把SQL結果返回的列name和type屬性定義的JavaBean的屬性name對應
resultMap一般用於複雜、級聯這些關聯的配置,在簡單的情況下,我們可以使用resultType通過自動映射來完成,這樣配置的工作量就會大大減少。
insert元素
insert元素,將對於select元素而言要簡單許多。MyBatis會在執行插入之後返回一個整數,以表示你進行操作後插入的記錄數。
舉例:
<insert id="insert" parameterType="user">
insert into
user
(name,sex,age)
values
(#{name},#{sex},#{age})
</insert>
在現實中我們插入數據後往往需要獲得這個主鍵,以便於未來的操作。同樣地,MyBatis提供了實現的方法
首先我們可以使用keyProperty屬性指定哪個是主鍵字段,同時使用useGeneratedKeys屬性告訴MyBatis這個主鍵是否使用數據庫內置策略生成
<insert id="insert" parameterType="user" useGeneratedKeys="true" keyProperty="id">
insert into
user
(name,sex,age)
values
(#{name},#{sex},#{age})
</insert>
這樣我們傳入的user對象就無需設置id的值,MyBatis就會用數據庫的設置進行處理。這樣做的好處是在Mybatis插入的時候,它會回填JavaBean的id值。
update元素&&delete元素
與insert一樣均爲DML語句,所以處理思路很相像。update和delete元素執行後會返回一個整數,標識執行後影響的記錄條數
<delete id="delete" parameterType="java.lang.Long">
delete from user
where id=#{id}
</delete>
<update id="update" parameterType="user">
update user
set
<if test="#{name}!=null">name=#{name},</if>
<if test="#{age}!=null">age=#{age}</if>
where id=#{id}
</update>
#和$
在MyBatis中,我們產出傳遞字符串,我們設置的參數#{name}在大多數情況下MyBatis會用創建預編譯的語句,然後MyBatis爲它賦值,而有的時候我們需要的是傳遞SQL語句的本身,而不是SQL所需要的參數。例如,根據某些列進行排序等
例如,爲orderColumn=“name” 表示待排序的列爲name列,那麼在Mybatis中可以這麼寫
select * from user order by ${orderColumn}
這樣MyBatis就不會幫我們轉義orderColumn,而變爲直出,而不是作爲SQL的參數進行設置。只是這樣是對SQL而言不安全
sql元素
其實在上面我們已經用到過了,
<sql id="column_list">
id,name,age
</sql>
sql元素的意義,在於我們可以定義一穿sql語句的組成部分,其他的語句可以通過引用來使用它。例如,你有一條sql需要select幾十個字段映射到JavaBean中去,我的第二個sql也是這幾十個字段映射到JavaBean中區,顯然這些字段寫兩遍不合適,因此我們就可以使用sql元素來完成
參考文獻:
深入淺出MyBatis技術原理與實戰