ssm框架學習---mybatis中延遲載入實現
阿新 • • 發佈:2019-01-09
在處理查詢結果中,如果需要延遲載入,即屬於對查詢結果有要求的那種,需要使用resultMap來實現,並結合association或者collection,
引入延遲載入的目的:單表或者簡單聯合查詢速度較快,通過延遲載入可以按需載入,減輕資料庫的壓力。
假設需求時查詢訂單時延遲載入所關聯的使用者資訊,定義mapper.xml檔案如下;
其中在association中引用了一個依據id查詢Customer的statement,它的定義如下:<!--需求:實現延遲載入,先查詢出訂單資訊,然後再延遲載入訂單所對應的使用者資訊--> <!--定義延遲載入的resultmap,因為只有resultMap有延遲載入的功能,因此這裡不能夠使用resultType--> <resultMap id="OrdersCustomerLazyLoadingMap" type="com.ajin.mybatis.model.OrdersCustomerMap"> <!--配置訂單的基本資訊--> <id column="ono" property="ono"></id> <result column="otime" property="otime"></result> <result column="gno" property="gno"></result> <result column="cno" property="cno"></result> <!--配置關聯的使用者資訊,使用association實現延遲載入 select:用來指定延遲載入查詢語句的sql,這裡引用了CustomerMapper中的statement,因此需要新增完整名稱空間 column:用來指定關聯的用來關聯查詢的屬性 --> <association property="customer" javaType="com.ajin.mybatis.model.Customer" select="com.ajin.mybatis.mapper.CustomerMapper.selectCustomerById" column="cno"> <!--需要注意這裡和普通的一對一關聯查詢不一樣,這裡面不需要寫任何東西--> </association> </resultMap> <!--這裡面只需要編寫單表查詢訂單的sql語句--> <select id="selectOrdersCustomerLazyLoading" resultMap="OrdersCustomerLazyLoadingMap"> select * from orders; </select>
至於這個statement對應的介面定義這裡就不列出來了,很簡單。<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ajin.mybatis.mapper.CustomerMapper"> <select id="selectCustomerById" parameterType="int" resultType="com.ajin.mybatis.model.Customer"> select * from customer where cno=#{value} </select> </mapper>
接下來是上述mapper.xml對應的介面定義如下:
在編寫測試用例之前,需要將上述的xml檔案新增到sqlMapConfig.xml的mybatis配置檔案中,同時因為需要用到延遲載入功能,但是預設沒有開啟,需要如下設定package com.ajin.mybatis.mapper; import com.ajin.mybatis.model.OrdersCustomerMap; import com.ajin.mybatis.model.OrdersCustomer; import java.util.List; /** * Created by ajin on 16-12-19. */ public interface OrdersCustomerMapper { //基於resultType方式一對一查詢 public OrdersCustomer selectOrdersCustomerById(int id); //基於resultMap方式一對一查詢 public OrdersCustomerMap selectOrdersCustomerMapById(int id); //延遲載入介面方法定義 public List<OrdersCustomerMap> selectOrdersCustomerLazyLoading(); }
<!--配置延遲載入屬性,首先開啟延遲載入,然後關閉積極載入-->
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
最後編寫我們的測試用例:
package com.ajin.mybatis.mapper;
import com.ajin.mybatis.model.Customer;
import com.ajin.mybatis.model.OrdersCustomerMap;
import com.ajin.mybatis.model.OrdersCustomer;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;
import static org.junit.Assert.*;
/**
* Created by ajin on 16-12-19.
*/
public class OrdersCustomerMapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws Exception {
String resource = "config/SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void selectOrdersCustomerById() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
try{
OrdersCustomerMapper ordersCustomerMapper = sqlSession.getMapper(OrdersCustomerMapper.class);
OrdersCustomer ordersCustomer=ordersCustomerMapper.selectOrdersCustomerById(5);
System.out.println(ordersCustomer);
}finally {
sqlSession.close();
}
}
@Test
public void selectOrdersCustomerMapById() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
try{
OrdersCustomerMapper ordersCustomerMapper = sqlSession.getMapper(OrdersCustomerMapper.class);
OrdersCustomerMap ordersCustomer=ordersCustomerMapper.selectOrdersCustomerMapById(5);
System.out.println(ordersCustomer);
}finally {
sqlSession.close();
}
}
@Test
public void selectOrdersCustomerLazyLoading() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
try{
OrdersCustomerMapper ordersCustomerMapper = sqlSession.getMapper(OrdersCustomerMapper.class);
//在執行下面這句的時候,只是會執行對於訂單表的單表查詢
// 日誌輸出如下:
// DEBUG [main] - ==> Preparing: select * from orders;
// DEBUG [main] - ==> Parameters:
// DEBUG [main] - <== Total: 7
List<OrdersCustomerMap> lists=ordersCustomerMapper.selectOrdersCustomerLazyLoading();
for(OrdersCustomerMap list:lists){
//在執行這一句話時才會延遲載入去獲得所關聯的使用者資訊
// 日誌輸出如下:
// DEBUG [main] - ==> Preparing: select * from customer where cno=?
// DEBUG [main] - ==> Parameters: 1(Integer)
// DEBUG [main] - <== Total: 1
// Customer{cno=1, cname='zcj', csex='male', cphone='13036144569', caddress='wuhan'}
//並且在查詢相同的id時,並不會從新生成sql語句,這就涉及到一級快取了
Customer customer =list.getCustomer();
System.out.println(customer);
}
}finally {
sqlSession.close();
}
}
}
使用collection的方法類似,當然如果框架沒有提供,我們可以採用二次呼叫不同mapper的介面方法來實現延遲載入,框架只是將這一層給封裝到了一起,內部原理仍然如此