关联属性的封装(连接查询 & 分步查询),延迟加载

关联属性的封装(连接查询 & 分步查询),延迟加载

在项目中,不可避免的存在着类与类之间的关联,在数据库的表中,这样的关联使用关联属性的主键表示;但在对象中,被关联的属性一般是以对象的形式存在。

举个例子:

学生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>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章