1. 程式人生 > >mybatis的一對一,一對多的關係對映配置及效能分析(延遲載入)

mybatis的一對一,一對多的關係對映配置及效能分析(延遲載入)

一對一關係對映

1)自動關聯(偷懶的辦法):可以自定義一個大而全的pojo類,然後自動對映其實是根據資料庫總的欄位名稱和
	pojo中的屬性名稱對應.
2)手動關聯: 需要指定資料庫中表的欄位名稱和java的pojo類中的屬性名稱的對應關係.
	使用association標籤

需求: 查詢訂單所屬的客戶

UserMapper.xml配置:

<resultMap type="Orders" id="OrdersOneToOneMap">
	<!--id:唯一性標識
    	column:表示sql查詢出來的欄位名。
    	property:代表欄位對映的實體類的屬性名
	-->
<id column="id" property="id" /> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <!--association:用於對映關聯查詢單個物件的資訊 property:要將關聯查詢的使用者資訊對映到Orders中那個屬性 association:表示進行關聯查詢單條記錄 javaType:表示關聯查詢的結果型別 -->
<association property="user" javaType="User"> <id column="user_id" property="id"/> <result column="username" property="username"/> <result column="sex" property="sex"/> <result column="birthday" property="birthday"/> <result column="address" property="address"
/>
</association> </resultMap> <!-- 查詢訂單對應的客戶一對一關係 --> <select id="findOrdersOneToOne" resultMap="OrdersOneToOneMap"> SELECT o.*, u.username, u.birthday, u.sex, u.address FROM orders o, USER u WHERE o.user_id = u.id; </select>
還有另外一種方法:
 <resultMap type="Orders" id="OrdersOneToOneMap">
   <id column="id" property="id" />
   <result column="user_id" property="userId"/>
   <result column="number" property="number"/>
   <result column="createtime" property="createtime"/>
   <!--column:指定傳遞給select的引數,如果是多個引數,用逗號隔開;select:指定的sql去查詢--> 
   <association property="user" column="id" select="com.learn.chapter4.OrerMapper.seletOrderByuserId"/>
 </resultMap>
 <!-- 查詢訂單對應的客戶一對一關係 -->
 <select id="findOrdersOneToOne"  resultMap="OrdersOneToOneMap">
 	SELECT
 	    u.username,
 		u.birthday,
 		u.sex,
 		u.address
 	FROM
 		USER u
 	WHERE
 		u.user_id = #{id};
 
 </select>
一對多的關係對映:
只能使用手動對映:指定表中欄位名稱和pojo中屬性名稱的對應關係
	使用collection標籤

需求:查詢一個使用者對應多個訂單;
    在user實體類中有List<Orders> ordersList;的集合

    <!--將查詢到的資訊對映到實體bean-->
	<resultMap type="User" id="UserOrdersMap">
	<!--id:唯一性標識
	column:表示sql查詢出來的欄位名。
	property:代表欄位對映的實體類的屬性名-->
	<id column="id" property="id"/>
	<result column="username" property="username"/>
	<result column="sex" property="sex"/>
	<result column="address" property="address"/>

	<!--使用resultMap的collection對關聯查詢的多條記錄對映到一個list集合屬性中。-->
	 <!-- 關聯訂單明細資訊 
            一個使用者關聯查詢出了多條訂單明細,要使用collection對映
            collection:對關聯查詢到的多條記錄對映到集合中
            property:將關聯查詢到的多條記錄對映到orders類的那個屬性
            ofType:指定對映的集合屬性中pojo的型別
         -->
	<collection property="ordersList" ofType="Orders">
	<!--id:唯一性標識-->
		<id column="order_id" property="id"/>
		<result column="number" property="number"/>
		<result column="createtime" property="createtime"/>
	</collection>

</resultMap>

<!--resultMap需要定義,並且此處的resultMap的值與定義的resultMap的id一致--->
<select id="findUserOrders" resultMap="UserOrdersMap">
	SELECT
		u.*, o.id order_id,
		o.number,
		o.createtime,
		o.note
	FROM
		USER u,
		orders o
	WHERE
		o.user_id = u.id;

</select>


    在Usermapper.java 中新增介面方法:
        public List<User> findUserOrders();
    
    測試類
   
    //查詢使用者訂單--一對多對映
	@Test
	public void testFindUserOrders(){
		SqlSession sqlSession = sqlSessionFactory.openSession();
		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
		List<User> list = mapper.findUserOrders();
		for (User user : list) {
			System.out.println("使用者===="+user);
			for (Orders orders : user.getOrdersList()) {
				System.out.println("訂單===="+orders);
			}
			
		}
	}

延遲載入

級聯的優勢是能夠快速的獲取資料,比如學生和學生資訊,這往往是常用的資訊,這個級聯是必要的.多層級聯的時候,建議超過三層級聯的時候,建議少用級聯,因為這會導致sql特別複雜,不利於他人的理解和維護.另外一點就是,我們可能有時候並不需要獲得所有的資料,這樣的話,如果多層級聯,可能就導致多執行幾條SQL,導致效能下降.所以這時候可以考慮使用延遲載入.

延遲載入的意義在於:一開始並不取出級聯資料,只有當使用它的時候,才傳送sql到資料庫查詢.

在Mybatis中有2個全域性延遲載入的引數:lazyLoadingEnabled和aggressiveLazyLoading.

lazyLoadingEnabled:是否開啟延遲載入的功能;

aggressiveLazyLoading:是否採用層級載入策略;舉例:假如我們有學生表,學生成績表以及學生證表.而學生成績表和學生證表在一個層級,當我們訪問學生課程成績的時候,預設情況下是系統採用層級載入策略,也就是說也會把學生證資訊找出來,但這並不是我們需要的,這個時候aggressiveLazyLoading就可以用起來了.在配置檔案中配置如下程式碼

<setting name="aggressiveLazyLoading" value="false"/>

當然,還有另外一種情況,區域性需要即時載入,區域性需要延遲載入.這個時候就使用到區域性載入引數 fetchType;

我們可以在association和collection中配置屬性fetchType,對應的屬性值有lazy 和eager.預設是eager.一旦配置了全域性變數後,又配置了局部變數,那麼區域性變數就會覆蓋全域性變數.如此.我們就可以靈活的配置,哪些需要即時載入,哪些要延遲載入.