Mybatis的一对一查询以及延迟加载

一对一的关联查询:

  1. 使用业务扩展类
  2. 使用ResultMap
  • 表如下
create table student(sid int(11) primary key not null,
sname varchar(20), 
cardid int(11));

create table studentcard(cardid int(11) primary key not null,
cardinfo varchar(20));

alter table student add constraint fk_student_studentcard_cardid
foreign key(cardid) references studentcard(cardid);

insert into studentcard values(1,'学生公交卡');
insert into studentcard values(2,'学生校园卡');
insert into studentcard values(3,'学生购物卡');
insert into student(sname,cardid) values('王富贵',1);
insert into student(sname,cardid) values('王祈年',2);
insert into student(sname,cardid) values('曾小贤',3);
  • StudentMapper.xml
<select id="TestOneForOne" resultType="entity.StudentBusiness">
        SELECT s.*,c.* from student s inner join studentcard c
        on s.cardid=c.cardid
        where s.sid=#{sid}
    </select>

因为查询到的信息是既包含student,又包含StudentCard。所以resultType需要一个同时包含这两个字段的实体类。

package entity;

/**
 * @ClassName:StudentAndStudentCard
 * @Description:学生业务扩展类
 * @author:zgy19
 * @data:2020/1/14 15:04
 * @History:
 * @UpdateDate:
 * @author:
 * @UpdateContent:
 */
public class StudentBusiness extends Student {
    private Integer cardid;
    private String cardinfo;

    @Override
    public Integer getCardid() {
        return cardid;
    }

    @Override
    public void setCardid(Integer cardid) {
        this.cardid = cardid;
    }

    public String getCardinfo() {
        return cardinfo;
    }

    public void setCardinfo(String cardinfo) {
        this.cardinfo = cardinfo;
    }

    @Override
    public String toString() {
        return super.toString()+", cardid='" + cardid +
                ", cardinfo='" + cardinfo + '\'';
    }
}

测试代码:

public static void main(String[] args) throws IOException {
        Reader reader= Resources.getResourceAsReader("config.xml");
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);
        SqlSession session=sqlSessionFactory.openSession();
        StudentMapper studentMapper=session.getMapper(StudentMapper.class);
        Student student=new Student();
        student.setSid(3);
        Student student1=studentMapper.selectStudentBySid(student);
        StudentBusiness studentBusiness=studentMapper.TestOneForOne(student);
        System.out.println(student1);
        System.out.println(studentBusiness);
        session.close();
    }

测试结果:

Student:sid=3, sname='曾小贤', cardid=3
Student:sid=3, sname='曾小贤',cardid='3, cardinfo='学生购物卡'

上面为使用业务扩展类的方法,适用于表较小且简单的查询
下面为使用使用ReultMap:

既然不使用业务扩展类,又需要返回类型中包含查询的所有字段,则需要把两个实体类关联起来。
在数据库中,两张表之间的关联使用外键,
在实体类中,我们使用属性使两张表相关联,如下Student.java所示
Student.java

 //学生信息
    private Integer sid;
    private String sname;
    private Integer cardid;

    //学生证信息
    private StudentCard studentCard;

StudentMapper.xml

<select id="TestOneForOne2" resultMap="student_studentcard_map">
        SELECT s.*,c.* from student s inner join studentcard c
        on s.cardid=c.cardid
        where s.sid=#{sid}
    </select>
    
    <resultMap id="student_studentcard_map" type="student">
        <!--这里的id标签中写主键-->
        <id property="sid" column="sid"></id>
        <result property="sname" column="sname"></result>
        <result property="cardid" column="cardid"></result>

        <!--因为是一对一的关系,所以使用association标签,如果是一对多,则使用collections标签-->
        <association property="studentCard" javaType="entity.StudentCard">
            <id property="cardid" column="cardid"></id>
            <result property="cardinfo" column="cardinfo"></result>
        </association>
    </resultMap>

测试结果如下(需要重写Student中的toString):

Student:sid=3, sname='曾小贤', cardid=3, cardinfo=学生购物卡

使用延迟加载
如果不采用延迟加载,在加载时,会将所有信息全部查询出来,无论你是否需要。这种情况在数据量很大时,会大大增加查询时间。降低效率。


使用延迟加载,先查询需要的数据,其他数据在需要时再加载。
StudentMapper.xml

<!--一对一使用ResultMap和延迟加载-->
    <select id="TestOneForOneAndLazyLoad" resultMap="student_studentcard_lazyload_map">
        SELECT * from student where sid=#{sid}
    </select>

    <resultMap id="student_studentcard_lazyload_map" type="student">
        <!--这里的id标签中写主键-->
        <id property="sid" column="sid"></id>
        <result property="sname" column="sname"></result>
        <result property="cardid" column="cardid"></result>

        <!--因为是一对一的关系,所以使用association标签,如果是一对多,则使用collection标签-->
        <association property="studentCard" javaType="entity.StudentCard" select="querystudentcardByCardid" column="cardid">
        </association>
    </resultMap>

    <!--根据cardid来查询证件信息-->
    <select id="querystudentcardByCardid" parameterType="int" resultType="entity.StudentCard">
        select * from studentcard where cardid=#{cardid}
    </select>

解释:重点标签

<association property="studentCard" javaType="entity.StudentCard" select="querystudentcardByCardid" column="cardid">
        </association>

这里的select中是需要延迟加载的语句,column是关联外键
此外还需要在config.xml中配置开启懒加载
config.xml

<settings>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
        <!--开启日志,并指定使用日志的类型-->
        <setting name="logImpl" value="LOG4J"></setting>
    </settings>

测试代码:

 Student student2=studentMapper.TestOneForOneAndLazyLoad(student);
 System.out.println(student2.getSname()+","+student2.getCardid());
 System.out.println(student2.getStudentCard().getCardid()+","+student2.getStudentCard().getCardinfo());

测试结果
在这里插入图片描述
可以看出,先查询了学生的信息,在执行第二个sout语句时,才执行查询studentcard的select语句。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值