SQL映射文件
SQL映射文件頂級元素配置
- mapper:映射文件的根元素點,只有一個屬性namespace(命名空間),其作用如下:
- 用於區分不同的mapper,全局唯一
- 綁定dao接口,即面向接口編程(mapper.xml的namespace必須和接口同名)
- 在不同的mapper文件中,子元素的id可以相同(MyBatis通過namespace和子元素的id聯合區分)
- cache:配置給定命名空間的緩存
- cache-ref:從其他命名空間引用緩存配置
- resultMap:用來描述數據庫結果集和對象的對應關係
- sql:可重用的SQL塊,也可以被其他語句引用
- insert:映射插入語句
- update:映射更新語句
- select:映射查詢語句
- delete:映射刪除語句
使用select
<!-- 根據供應商名稱查詢供應商列表(模糊查詢) -->
<select id="getProviderListByproName" resultType="Provider"
parameterType="string">
SELECT * FROM smbms_provider WHERE proName LIKE CONCAT
('%',#{proName},'%')
</select>
- id
- 命名空間中唯一的標識符
- 接口中的方法與映射文件中的SQL語句id一一對應
- parameterType
- 傳入SQL語句的參數類型
- 它支持基礎數據類型和複雜數據類型
- 對於一個參數入參可以使用Java基礎數據類型,通過#{參數名}取值
- 若是多參數入參,需要複雜參數數據類型來支持,包括Java實體類、Map,通過#{屬性名}或#{Map的key}來獲取傳入的參數值
- 內建別名對大小寫不敏感
- resultType
- SQL語句返回值類型的完整類名或別名
使用resultMap
<!-- 數據庫字段名與pojo的屬性名不一致時,自動映射 -->
<resultMap type="User" id="userList">
<result property="id" column="id" />
<result property="userCode" column="userCode" />
<result property="userName" column="userName" />
<result property="phone" column="phone" />
<result property="birthday" column="birthday" />
<result property="gender" column="gender" />
<result property="userRole" column="userRole" />
<result property="userRoleName" column="roleName" />
</resultMap>
<!-- 查詢用戶列表(參數:對象入參) -->
<select id="getUserList" resultMap="userList" parameterType="User">
SELECT u.*,r.`roleName` FROM `smbms_user` u,`smbms_role` r WHERE
u.`userName` LIKE CONCAT ('%',#{userName},'%') AND
u.`userRole`=#{userRole} AND
u.`userRole`=r.`id`
</select>
resultMap元素用來描述如何將結果集映射到Java對象,此處使用resultMap對列表展示所需的必要字段來進行自由映射,特別是當數據庫的字段名和POJO中的屬性名不一致的情況下,比如角色名稱,字段名column是roleName,而User對象的屬性名則爲userRoleName,此時就要做映射。
resultMap元素的屬性值和子節點
- id 屬性:resultMap的唯一標識 (此id值用於select元素resultMap屬性的引用)
- type屬性:表示resultMap映射結果類型
- result子節點:
- id:一般對應數據庫中該行的主鍵id,設置此項可提高MyBatis性能
- result:映射到JavaBean的某個“簡單類型”屬性
- association:映射到JavaBean的某個“複雜類型”屬性,比如JavaBean類
- collection:映射到JavaBean的某個“複雜類型”屬性,比如集合
resultType和resultMap的關聯和區別:
resultType :直接表示返回類型
resultMap :對外部resultMap的引用,它的應用場景:數據庫字段信息與對象屬性不一致或者複雜的聯合查詢,自由控制映射結果。
二者不能同時存在,本質上都是Map數據結構
MyBatis對resultMap自動映射的三個匹配級別
- NONE:禁止自動匹配
- PARTIAL(默認):自動匹配所有屬性,有內部嵌套(association,collection)的除外。
- FULL:自動匹配所有。
association
- 複雜的類型關聯,一對一
- 內部嵌套
- 映射一個嵌套JavaBean屬性
- 屬性
- property:映射數據庫列的實體對象的屬性
- javaType:完整Java類名或者別名
- resultMap:引用外部resultMap
- 子元素
- id(即使不指定ID,MyBatis也會工作,但是會導致嚴重的性能開銷,所以選擇儘量少的屬性來唯一表示結果,主鍵和聯合主鍵均可)
- result
- property:映射數據庫列的實體對象的屬性
- column:數據庫列名或者別名(確保所有列名都是唯一無歧義的)
column:數據庫列名或者別名
<!-- 結果映射 -->
<resultMap type="User" id="userRoleResult">
<id property="id" column="id" />
<result property="userCode" column="userCode" />
<result property="userName" column="userName" />
<result property="userRole" column="userRole" />
<association property="role" javaType="Role" resultMap="roleResult" />
</resultMap>
<resultMap type="Role" id="roleResult">
<id property="id" column="r_id" />
<result property="roleCode" column="roleCode" />
<result property="roleName" column="roleName" />
</resultMap>
<!-- 根據角色id查詢用戶列表 -->
<select id="getUserListByRoleId" parameterType="Integer"
resultMap="userRoleResult">
SELECT u.*,r.`id` AS r_id,r.`roleCode`,r.`roleName` FROM
smbms_user u,smbms_role r WHERE u.`userRole`=#{userRole} AND
U.`userRole`=R.`id`
</select>
collection
- 複雜類型集合,一對多
- 內部嵌套
- 映射一個嵌套結果集到一個列表
- 屬性
- property:映射數據庫列的實體對象的屬性
- ofType:完整Java類名或者別名(集合所包括的類型)
- resultMap:引用外部resultMap
- 子元素
- id
- result
- property:映射數據庫列的實體對象的屬性
- column:數據庫列名或者別名
<!-- 根據供應商id查詢其相關信息和其下的所有訂單 -->
<resultMap type="Provider" id="providerListResult">
<id property="id" column="id"/>
<result property="proCode" column="proCode"/>
<result property="proName" column="proName"/>
<result property="proContact" column="proContact"/>
<result property="proPhone" column="proPhone"/>
<collection property="billList" ofType="Bill">
<result property="billCode" column="billCode"/>
<result property="productName" column="productName"/>
<result property="totalPrice" column="totalPrice"/>
<result property="isPayment" column="isPayment"/>
</collection>
</resultMap>
<select id="getProListAndBillByProId" resultMap="providerListResult" parameterType="Integer">
SELECT p.*,b.`billCode`,b.`productName`,b.`totalPrice`,b.`isPayment`
FROM `smbms_provider` p,`smbms_bill` b
WHERE p.`id`=1
AND p.`id`=b.`providerId`
</select>
增刪改(insert、update、delete)
<!-- 增加供應商信息 -->
<insert id="addProvider" parameterType="Provider">
INSERT INTO
smbms_provider(proCode,proName,proDesc,proContact,proPhone,proAddress,
proFax,createdBy,creationDate)
VALUES(#{proCode},#{proName},#{proDesc},
#{proContact},#{proPhone},#{proAddress},#{proFax},
#{createdBy},#{creationDate})
</insert>
<!-- 根據供應商id刪除供應商信息 -->
<delete id="deleteProvider" parameterType="Integer">
delete from
smbms_provider where id=#{id}
</delete>
<!-- 根據供應商ID修改供應商信息 -->
<update id="updateProvider" parameterType="Provider">
UPDATE smbms_provider
SET
proCode=#{proCode},proName=#{proName},proDesc=#{proDesc},proContact=#{proContact},
proPhone=#{proPhone},proAddress=#{proAddress},proFax=#{proFax},modifyBy=#{modifyBy},
modifyDate=#{modifyDate}
WHERE id=#{id}
</update>
對於增刪改這類數據庫更新操作,需要注意的兩點:
- 該類型的操作本身默認返回執行SQL影響的行數,所以DAO層的接口方法返回值一般設置爲int類型。最好不要是boolean類型。
- insert、update、delete元素中軍沒有resultType屬性,只有查詢操作需要對返回結果類型(resultType/resultMap)進行相應的指定。
使用@Param註解實現多參數入參()
如修改密碼的業務只需要傳入兩個參數(id和新密碼)
<!-- 修改用戶當前密碼 -->
<update id="updatePwd">
UPDATE `smbms_user` SET
userPassword=#{userPassword}
WHERE id=#{id}
</update>
/**
* 修改當前用戶密碼
* @param id
* @param pwd
* @return
*/
public int updatePwd(@Param("id")Integer id,@Param("userPassword")String pwd);
在MyBatis中參數入參,何時需要封裝成對象入參,何時又需要使用多參數入參?
- 超過4個以上的參數最好封裝成對象入參
- 對於參數固定的業務方法,最好使用多參數入參。原因是這種方法比較靈活,代碼可讀性高,可以清晰地看出接口方法中所需的參數是什麼。比如修改個人密碼,根據用戶id刪除用戶,根據用戶id查看用戶明細。
MyBatis 緩存
- 一級緩存
作用範圍爲session域內,當session flush或者close之後,該session中的所有cache就會被清空 - 二級緩存
二級緩存就是global caching,它超出session之外,可以被所有SqlSession共享,開啓它只需要在MyBatis的核心配置文件(mybatis-config.xml) settings中設置即可。
一級緩存緩存的是SQL語句,二級緩存緩存的是結果對象。 - 緩存配置
- MyBatis的全局cache配置
- 在Mapper XML文件中設置緩存,默認情況下是沒有開啓緩存的
- 在Mapper XML文件配置支持cache後,如果需要對個別查詢進行調整,可以單獨設置cache
<!-- MyBatis的全局cache配置-->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<!-- 在Mapper XML文件中設置緩存,默認情況下是沒有開啓緩存的-->
<cache eviction="FIFO" flushInterval="60000"
size="512" readOnly="true"/>
<!-- 在Mapper XML文件配置支持cache後,如果需要對個別查詢進行調整,可以單獨設置cache-->
<select id="selectAll" resultType="Emp"
useCache="true">