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.一旦配置了全域性變數後,又配置了局部變數,那麼區域性變數就會覆蓋全域性變數.如此.我們就可以靈活的配置,哪些需要即時載入,哪些要延遲載入.