文章目錄
關聯屬性的封裝(連接查詢 & 分步查詢),延遲加載
在項目中,不可避免的存在着類與類之間的關聯,在數據庫的表中,這樣的關聯使用關聯屬性的主鍵表示;但在對象中,被關聯的屬性一般是以對象的形式存在。
舉個例子:
學生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>