關聯屬性的封裝(連接查詢 & 分步查詢),延遲加載

關聯屬性的封裝(連接查詢 & 分步查詢),延遲加載

在項目中,不可避免的存在着類與類之間的關聯,在數據庫的表中,這樣的關聯使用關聯屬性的主鍵表示;但在對象中,被關聯的屬性一般是以對象的形式存在。

舉個例子:

學生Student和學院College是多對一的關係,在這裏,學生類可以有一個字段,用來存儲他/她所在的學院。

public class Student {
    Integer id;
    String name;
    College college;
}

使用連接查詢

使用連接查詢獲得college,並且封裝到student對象中

public Student getStudentById(Integer id);
    <select id="getStudentById" resultMap="student">
        select *
        from student, college
        where studet.stuent_college = college.college_id
            and student_id = #{id}
    </select>

有了查詢的結果,顯然Mybatis不能自動封裝,需要根據我們配置的reslutMap進行封裝。

方式一:嵌套封裝

    <resultMap id="student" type="com.test.entity.Student">
        <id column="student_id" property="id"></id>
        <result column="student_name" property="name"></result>

        <!-- 封裝college,經過連接查詢,已經將對應的學院信息查詢出來了 -->
        <association property="college"><!--這裏封裝college這個bean-->
            <id column="college_id" property="id"></id>
            <result column="college_name" property="name"></result>
        </association>

    </resultMap>

方式二:級聯屬性

<resultMap id="student" type="com.test.entity.Student">
        <id column="student_id" property="id"></id>
        <result column="student_name" property="name"></result>
		 <!-- 封裝college,經過連接查詢,已經將對應的學院信息查詢出來了 -->
        <result column="college_id" property="college.id"></result>
        <result column="college_name" property="college.name"></result>

</resultMap>

使用分步查詢

分佈查詢也就是說,對於不同的表,不進行連接,而是分開查。

在這個例子中,可以先查詢學生的信息,因爲學生的信息中保存了college表中記錄的主鍵,可以再根據這個主鍵查詢college表,再將這次查詢的結果封裝到student對象的college字段。

public Student getStudentById(Integer id);

    <select id="getStudentById" resultMap="student">
        select * from student where student_id = #{id}
    </select>

首先,第一次查詢當前javabean的信息,它關聯的對象,交給resultMap查詢,並且封裝。

    <resultMap id="student" type="com.test.entity.Student">
        <id column="student_id" property="id"></id>
        <result column="student_name" property="name"></result>
        <association property="college" select="com.test.dao.ICollegeDao.getCollegeById" column="id=student_college">
            <id property="id" column="college_id"></id>
            <result property="name" column="college_name"></result>
        </association>
    </resultMap>

注意association的屬性:

  • property:表示要封裝的屬性(與id和result的property屬性一樣)
  • select:用來指定一個查詢的方法。這個屬性指定一個已經配置好的<select/>標籤,通過"名稱空間.id"進行查找(名稱空間找到對應的mapper配置,在這個配置中查找id指定的<select/>
  • column:這裏的column表示傳遞給查詢方法的參數。column和property屬性配套使用,含義就是將column指定的列映射爲property指定的屬性,在分佈查詢時,這個映射過程還需要經過一次查詢,通過select值得頂查詢的方式,而column正好是select的參數

column傳遞參數時,使用鍵值對的方式"id=student_college",這個鍵值對的含義就是,將student_college這一列的值,作爲參數id的值,傳遞給select方法。如果select方法接收多個參數,鍵值對通過都好隔開。

延遲加載

延遲加載是很強大很有用的功能,當我們僅需要學生的信息,而不需要他的學院信息,這時後,就沒必要將他所在的學院封裝到學生的bean。

首先,可以想到的就是再寫一個方法,讓他不封裝college。

另一個解決方法,就是使用延遲加載。延遲加載就是在使用時,才查表,然後封裝

也就是說,如果使用了延遲加載,我們通過分步查詢的方式,當我們獲取學生信息的時候,只會查一次學生表,當訪問到college字段時,纔會進行第二次查詢,將結果封裝到college。

開啓延遲加載方式一:全局配置

在全局配置文件中,進行下面的配置

<settings>
	<setting name="lazyLoadingEnabled" value="true"/>
	<setting name="aggressiveLazyLoading" value="false" />
</settings>

開啓延遲加載方式二:association標籤的fetchType屬性

應用官方文檔
可選的。有效值爲 lazy 和 eager。 指定屬性後,將在映射中忽略全局配置參數 lazyLoadingEnabled,使用屬性的值。

  • lazy:延遲加載(懶漢式)
  • eager:非延遲加載(餓漢式)
    <resultMap id="student" type="com.test.entity.Student">
        <id column="student_id" property="id"></id>
        <result column="student_name" property="name"></result>
        <association property="college" select="com.test.dao.ICollegeDao.getCollegeById" column="id=student_college" fetchType="lazy">
            <id property="id" column="college_id"></id>
            <result property="name" column="college_name"></result>
        </association>
    </resultMap>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章