舉例:由於一個訂單信息只會是一我的下的訂單,因此從查詢訂單信息出發,關聯查詢用戶信息爲一對一查詢。若是從用戶信息出發,查詢用戶下的訂單信息則爲一對多查詢,由於一個用戶能夠下多個訂單。java
查詢全部訂單信息,關聯查詢下單用戶信息。mysql
主信息:訂單表sql
從信息:用戶表數據庫
SELECT orders.*, user.username, user.address FROM orders LEFT JOIN user ON orders.user_id = user.id
返回resultType方式比較簡單,也比較經常使用,就不作介紹了。session
使用resultMap進行結果映射,定義專門的resultMap用於映射一對一查詢結果。mybatis
建立OrdersExt類(該類用於結果集封裝),加入User屬性,user屬性中用於存儲關聯查詢的用戶信息,由於訂單關聯查詢用戶是一對一關係,因此這裏使用單個User對象存儲關聯查詢的用戶信息。app
public class OrdersExt extends Orders { private User user;// 用戶對象 // get/set。。。。 }
在UserMapper.xml中,添加如下代碼:性能
<!-- 查詢訂單關聯用戶信息使用resultmap --> <resultMap type="OrdersExt" id="ordersAndUserRstMap"> <id column="id" property="id"/> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> <!-- 一對一關聯映射 --> <!-- property:Orders對象的user屬性 javaType:user屬性對應 的類型 --> <association property="user" javaType="com.kkb.mybatis.po.User"> <!-- column:user表的主鍵對應的列 property:user對象中id屬性--> <id column="user_id" property="id"/> <result column="username" property="username"/> <result column="address" property="address"/> </association> </resultMap> <select id="findOrdersAndUserRstMap" resultMap="ordersAndUserRstMap"> SELECT o.id, o.user_id, o.number, o.createtime, o.note, u.username, u.address FROM orders o JOIN `user` u ON u.id = o.user_id </select>
在UserMapper接口中,添加如下接口方法:測試
public List<OrdersExt> findOrdersAndUserRstMap() throws Exception;
在UserMapperTest測試類中,添加測試代碼:spa
public void testfindOrdersAndUserRstMap()throws Exception{ //獲取session SqlSession session = sqlSessionFactory.openSession(); //獲限mapper接口實例 UserMapper userMapper = session.getMapper(UserMapper.class); //查詢訂單信息 List<OrdersExt> list = userMapper.findOrdersAndUserRstMap(); System.out.println(list); //關閉session session.close(); }
使用resultMap進行結果映射時,具體是使用association完成關聯查詢的映射,將關聯查詢信息映射到pojo對象中。
查詢全部用戶信息及用戶關聯的訂單信息。
主信息:用戶信息
從信息:訂單信息
SELECT u.*, o.id oid, o.number, o.createtime, o.note FROM `user` u LEFT JOIN orders o ON u.id = o.user_id
在一對多關聯查詢時,只能使用resultMap進行結果映射:
一、一對多關聯查詢時,sql查詢結果有多條,而映射對象是一個。
二、resultType完成結果映射的方式的一條記錄映射一個對象。
三、resultMap完成結果映射的方式是以[主信息]爲主對象,[從信息]映射爲集合或者對象,而後封裝到主對象中。
在User類中加入List<Orders> orders屬性。
在UserMapper.xml文件中,添加如下代碼:
<resultMap type="user" id="userAndOrderRstMap"> <!-- 用戶信息映射 --> <id property="id" column="id"/> <result property="username" column="username"/> <result property="birthday" column="birthday"/> <result property="sex" column="sex"/> <result property="address" column="address"/> <!-- 一對多關聯映射 --> <collection property="orders" ofType="orders"> <id property="id" column="oid"/> <result property="userId" column="id"/> <result property="number" column="number"/> <result property="createtime" column="createtime"/> <result property="note" column="note"/> </collection> </resultMap> <select id="findUserAndOrderRstMap" resultMap="userAndOrderRstMap"> SELECT u.*, o.id oid, o.number, o.createtime, o.note FROM `user` u LEFT JOIN orders o ON u.id = o.user_id </select>
Collection標籤:定義了一對多關聯的結果映射。
// resultMap入門 public List<User> findUserAndOrdersRstMap() throws Exception;
@Test public void testFindUserAndOrdersRstMap() { SqlSession session = sqlSessionFactory.openSession(); UserMapper userMapper = session.getMapper(UserMapper.class); List<User> result = userMapper.findUserAndOrdersRstMap(); for (User user : result) { System.out.println(user); } session.close(); }
MyBatis根據對關聯對象查詢的select語句的執行時機,分爲三種類型:直接加載、侵入式加載與深度延遲加載
延遲加載策略須要在Mybatis的全局配置文件中,經過<settings>標籤進行設置。
查詢訂單信息及它的下單用戶信息。
經過對全局參數:lazyLoadingEnabled進行設置,默認就是false。
<settings> <!-- 延遲加載總開關 --> <setting name="lazyLoadingEnabled" value="false"/> </settings>
<settings> <!-- 延遲加載總開關 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 侵入式延遲加載開關 --> <setting name="aggressiveLazyLoading" value="true"/> </settings>
<settings> <!-- 延遲加載總開關 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 侵入式延遲加載開關 --> <setting name="aggressiveLazyLoading" value="false"/> </settings>
動態SQL的思想:就是使用不一樣的動態SQL標籤去完成字符串的拼接處理、循環判斷。
解決的問題是:
綜合查詢的案例中,查詢條件是由頁面傳入,頁面中的查詢條件可能輸入用戶名稱,也可能不輸入用戶名稱。
<select id="findUserList" parameterType="queryVo" resultType="user"> SELECT * FROM user where 1=1 <if test="user != null"> <if test="user.username != null and user.username != ''"> AND username like '%${user.username}%' </if> </if> </select>
注意:要作『不等於空』字符串校驗。
上邊的sql中的1=1,雖然能夠保證sql語句的完整性:可是存在性能問題。Mybatis提供where標籤解決該問題。
代碼修改以下:
<select id="findUserList" parameterType="queryVo" resultType="user"> SELECT * FROM user <!-- where標籤會處理它後面的第一個and --> <where> <if test="user != null"> <if test="user.username != null and user.username != ''"> AND username like '%${user.username}%' </if> </if> </where> </select>
在映射文件中可以使用sql標籤將重複的sql提取出來,而後使用include標籤引用便可,最終達到sql重用的目的,具體實現以下:
原映射文件中的代碼:
<select id="findUserList" parameterType="queryVo" resultType="user"> SELECT * FROM user <!-- where標籤會處理它後面的第一個and --> <where> <if test="user != null"> <if test="user.username != null and user.username != ''"> AND username like '%${user.username}%' </if> </if> </where> </select>
<sql id="query_user_where"> <if test="user != null"> <if test="user.username != null and user.username != ''"> AND username like '%${user.username}%' </if> </if> </sql>
<!-- 使用包裝類型查詢用戶 使用ognl從對象中取屬性值,若是是包裝對象可使用.操做符來取內容部的屬性 --> <select id="findUserList" parameterType="queryVo" resultType="user"> SELECT * FROM user <!-- where標籤會處理它後面的第一個and --> <where> <include refid="query_user_where"></include> </where> </select>
注意:
一、若是引用其它mapper.xml的sql片斷,則在引用時須要加上namespace,以下:
<include refid="namespace.sql片斷」/>
綜合查詢時,傳入多個id查詢用戶信息,用下邊兩個sql實現:
SELECT * FROM USER WHERE username LIKE '%老郭%' AND (id =1 OR id =10 OR id=16) SELECT * FROM USER WHERE username LIKE '%老郭%' AND id IN (1,10,16)
在pojo中定義list屬性ids存儲多個用戶id,並添加getter/setter方法
<sql id="query_user_where"> <if test="user != null"> <if test="user.username != null and user.username != ''"> AND username like '%${user.username}%' </if> </if> <if test="ids != null and ids.size() > 0"> <!-- collection:指定輸入的集合參數的參數名稱 --> <!-- item:聲明集合參數中的元素變量名 --> <!-- open:集合遍歷時,須要拼接到遍歷sql語句的前面 --> <!-- close:集合遍歷時,須要拼接到遍歷sql語句的後面 --> <!-- separator:集合遍歷時,須要拼接到遍歷sql語句之間的分隔符號 --> <foreach collection="ids" item="id" open=" AND id IN ( " close=" ) " separator=","> #{id} </foreach> </if> </sql>
在UserMapperTest測試代碼中,修改testFindUserList方法,以下:
@Test public void testFindUserList() throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); // 得到mapper的代理對象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 建立QueryVo對象 QueryVo queryVo = new QueryVo(); // 建立user對象 User user = new User(); user.setUsername("老郭"); queryVo.setUser(user); List<Integer> ids = new ArrayList<Integer>(); ids.add(1);// 查詢id爲1的用戶 ids.add(10); // 查詢id爲10的用戶 queryVo.setIds(ids); // 根據queryvo查詢用戶 List<User> list = userMapper.findUserList(queryVo); System.out.println(list); sqlSession.close(); }
若是parameterType不是POJO類型,而是List或者Array的話,那麼foreach語句中,collection屬性值須要固定寫死爲list或者array。