mybatis的级联和延迟加载配置

概述

存在数据库表:

--班级表
create table t_clazz(
    id int(12) not null auto_increment,
    cla_name varchar(64) not null ,
    primary key (id)
);
--学生表
create table t_student(
    id int(12) not null auto_increment,
    stu_name varchar(64) not null ,
    phone_num int(13),
    cla_id int(12) not null,
    add constraint foreign key (cla_id) references t_clazz(id),
    primary key (id)
);
--热水卡表
create table t_water_card(
    id int(12) not null auto_increment,
    stu_id int(12) not null ,
    balance double,
    constraint foreign key (stu_id) references t_student(id),
    primary key (id)
);

 

mybtis支持延迟加载,在说延迟加载之前,我们先了解为什么需要延迟加载?当我们对单个数据库表操作时,比如有一个热水卡类HotWaterCardt如下代码:

public class HotWaterCard{
    private long id;
    private long stuId;
    private long balance;
    private Student student;
    /****setter and getter****/
}

很显然,水卡和学生是一对一的级联关系,若采用mybatis的级联操作(代码如下)来获取HotWaterCard的数据,那么就会执行getStudentById的sql语句,查询出student数据。当我们只是要查看id为1的热水卡的余额,并不需要对应的学生信息时,很显然这样的操作会造成性能的浪费。因此,我们可以通过使用延迟加载,在需要student数据的时候再加载student的数据。这就是延迟加载的目的。(当然,这里用例的级联相当少,实际上对性能不会有太大的影响,但是当级联很多时,那加载不需要的数据过多就会造成很大的性能浪费问题)

<resultMap id="hotWaterCard" type="edu.ssm.pojo.HotWaterCard">
        <id column="id" property="id"/>
        <result column="stu_Id" property="stuId"/>
        <result column="balance" property="balance"/>
        <!--一对一级联操作
            将stu_id传给StudentMapper的getStudentById方法,返回给HotWaterCard的student属性-->
        <association property="student" column="stu_id" select="edu.ssm.mapper.StudentMapper.getStudentById"/>
</resultMap>

其他pojo

public class Student{
    private long id;
    private long claId;
    private String stuName;
    private String phoneNum;

    /****setter and getter****/

}
public class Clazz{
    private int id;
    private String claName;
    private List<Student> studentList;

    /****setter and getter****/
}

 

级联

那么级联又是什么?级联是数据库实体的概念。以上述三个实体,热水卡HotWaterCard、学生student和班级clazz为例,一个学生只有一张热水卡,一张热水卡只能被一个学生持有,因此学生和热水卡是一对一级联;一个学生只有一个班级,一个班级有多个学生,因此是一对多的关系。mybatis还有一种叫鉴别器的级联,它是一种可以选择具体实现类的级联。

在mybatis中,级联是在mapper.xml文件中resultMap属性中配置的。三种级联属性分别对应上述的三种级联。

  1. association:一对一级联。
  2. collection:一对多级联。
  3. discriminator:鉴别器。

在mybatis中,association的用法即上面热水卡和学生的配置。下面我们看collection的用法。

<resultMap id="clazz" type="edu.ssm.pojo.Clazz">
        <id column="id" property="id"/>
        <result column="cla_name" property="claName"/>
        <!--一对多级联
            将班级clazz的id属性传给StudentMapper的getStudentListByClaId,根据claId获取学生列表-->
        <collection property="student" column="id" select="edu.ssm.mapper.StudentMapper.getStudentListByClaId"/>
</resultMap>

其中,getStudentListByClaId的返回值类型是Student或者是List<Student>都可以,只要保证Clazz中的student属性是List<Student>就行。

缓存

在概述中,我们使用了一个例子来说明为什么要使用延迟加载,现在用一种更为正式的方式讲解一下。

级联操作中会产生N+1的问题。N+1问题指的是,假设现在在有n个关联关系完成了级联,那么只要再加入一个关联关系,就变成了N+1个级联,所有的级联SQL都会被执行,同时会有很多不是我们关心的数据被取出,这样会造成很大的资源浪费,这就是N+1问题。mybatis提供了延迟加载功能来应对N+1问题。

配置延迟加载可以采用全局设置和局部设置的方式。

全局设置在setting中设置属性lazyLoadingEnable(全局延迟加载开关,true为开启)为true, aggressiveLazyLoading(层级加载开关,false为不开启)为false。

 <settings>
        <!--lazyLoadingEnabled:决定是否开始延迟加载-->
        <!--aggressiveLazyLoading:决定是否采用层级加载-->
        <!--在级联操作中,最优的性能选择是lazyLoadingEnabled为true,aggressiveLazyLoading为false。
            但是以上设置为全局设置,会影响全部级联,并不能完全满足业务需求。例如,在同一个层级中有4个表,
            但业务只需要用到其中一个,若采用全局的aggressiveLazyLoading设置不采用层级加载,
            则导致需要用到的表也被延迟加载,而采用层级加载则会多加载3个无用的表数据影响性能。
            因此,可以在association或collection中加入属性fetchType=eager或lazy,
            eager表示马上加载,lazy表示延迟加载。
            fetchType属性会忽视全局配置项lazyLoadingEnabled和aggressiveLazyLoading。
            从而可以选择同一个层级中某一些表立马加载,某一些表延迟加载。-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
     
</settings>


局部采用在association和collection中设置fetchType(fetchType属性会忽视全局配置项lazyLoadingEnabled和aggressiveLazyLoading),有如下两个值:当值为eager时,遇到当前pojo后,立即加载对应的数据,当值为lazy时,则延迟加载。

<resultMap id="hotWaterCard" type="edu.ssm.pojo.HotWaterCard">
        <id column="id" property="id"/>
        <result column="stu_Id" property="stuId"/>
        <result column="balance" property="balance"/>
        <!--一对一级联操作
            将stu_id传给StudentMapper的getStudentById方法,返回给HotWaterCard的student属性-->
        <association property="student" column="stu_id" select="edu.ssm.mapper.StudentMapper.getStudentById" fetchType="lazy"/>
    </resultMap>
    <resultMap id="clazz" type="edu.ssm.pojo.Clazz">
        <id column="id" property="id"/>
        <result column="cla_name" property="claName"/>
        <!--一对多级联
            将班级clazz的id属性传给StudentMapper的getStudentListByClaId,根据claId获取学生列表-->
        <collection property="student" column="id" select="edu.ssm.mapper.StudentMapper.getStudentListByClaId" fetchType="eager"/>
</resultMap>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
大学生参加学科竞赛有着诸多好处,不仅有助于个人综合素质的提升,还能为未来职业发展奠定良好基础。以下是一些分析: 首先,学科竞赛是提高专业知识和技能水平的有效途径。通过参与竞赛,学生不仅能够深入学习相关专业知识,还能够接触到最新的科研成果和技术发展趋势。这有助于拓展学生的学科视野,使其对专业领域有更深刻的理解。在竞赛过程中,学生通常需要解决实际问题,这锻炼了他们独立思考和解决问题的能力。 其次,学科竞赛培养了学生的团队合作精神。许多竞赛项目需要团队协作来完成,这促使学生学会有效地与他人合作、协调分工。在团队合作中,学生们能够学到如何有效沟通、共同制定目标和分工合作,这对于日后进入职场具有重要意义。 此外,学科竞赛是提高学生综合能力的一种途径。竞赛项目通常会涉及到理论知识、实际操作和创新思维等多个方面,要求参赛者具备全面的素质。在竞赛过程中,学生不仅需要展现自己的专业知识,还需要具备创新意识和解决问题的能力。这种全面的综合能力培养对于未来从事各类职业都具有积极作用。 此外,学科竞赛可以为学生提供展示自我、树立信心的机会。通过比赛的舞台,学生有机会展现自己在专业领域的优势,得到他人的认可和赞誉。这对于培养学生的自信心和自我价值感非常重要,有助于他们更加积极主动地投入学习和未来的职业生涯。 最后,学科竞赛对于个人职业发展具有积极的助推作用。在竞赛中脱颖而出的学生通常能够引起企业、研究机构等用人单位的关注。获得竞赛奖项不仅可以作为个人履历的亮点,还可以为进入理想的工作岗位提供有力的支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值