Mybatis级联查询和缓存

1.表结构


create table t_lecture(
 id int(20) not null auto_increment comment '编号',
 lecture_name varchar(60) not null comment '课程名',
 note varchar(1024) comment '备注',
 primary key (id)
);
create table t_student(
 id int (20) not null auto_increment comment '编号',
 cnname varchar(60) not null comment '学生姓名',
 sex tinyint(4) not null comment '性别',
 selfcard_no int(20) not null comment '学生证号',
 note varchar(1024) comment '备注',
 primary key (id)
);
create table t_student_health_female(
 id int(20) not null auto_increment comment '编号',
 student_id int(20) not null comment '学生编号',
 check_datae date not null comment '检查日期',
 heart varchar(60) not null comment '心',
 liver varchar(60) not null comment '肝',
 spleen varchar(60) not null comment '脾',
 lung varchar(60) not null comment '肺',
 kidney varchar(60) not null comment '肾',
 uterus varchar(60) not null comment '子宫',
 note varchar(1024) comment '备注',
 primary key (id)
);
create table t_student_health_male(
 id int(20) not null auto_increment comment '编号',
 student_id int(20) not null comment '学生编号',
 check_datae date not null comment '检查日期',
 heart varchar(60) not null comment '心',
 liver varchar(60) not null comment '肝',
 spleen varchar(60) not null comment '脾',
 lung varchar(60) not null comment '肺',
 kidney varchar(60) not null comment '肾',
 prostate varchar(60) not null comment '前列腺',
 note varchar(1024) comment '备注',
 primary key (id)
);
create table t_student_lecture(
 id int(20) not null auto_increment comment '编号',
 student_id int(20) not null comment '学生编号',
 lecture_id int(20) not null comment '课程编号',
 grade decimal(16,2) not null comment '评分',
 note varchar(1024) comment '备注',
 primary key (id)
);
create table t_student_selfcard(
 id int(20) not null auto_increment comment '编号',
 student_id int(20) not null comment '学生编号',
 native varchar(60) not null comment '籍贯',
 issue_date date not null comment '发证日期',
 end_date date not null comment '结束日期',
 note varchar(1024) comment '备注',
 primary key (id)
);

2.association一对一关联

学生和学生证是一对一关联的
@Alias("studentSelfcard")
public class StudentSelfcard {

    private Integer id;

    private Integer studentId;

    private String anative;

    private Date issueDate;

    private Date endDate;

    private String note;
@Alias("student")
public class Student {

    private Integer id;

    private String cnname;

    private Integer sex;

    private StudentSelfcard studentSelfcard;

    private String note;
<mapper namespace="com.zhp.dao.StudentSelfcardDao">

    <resultMap id="studentSelfcard" type="studentSelfcard">
        <id property="id" column="id"/>
        <result property="studentId" column="student_id"/>
        <result property="anative" column="native"/>
        <result property="issueDate" column="issue_date"/>
        <result property="endDate" column="end_date"/>
        <result property="note" column="note"/>
    </resultMap>
    
    <select id="findByStudentId" resultMap="studentSelfcard">
        SELECT id,student_id,native,issue_date,end_date,note FROM t_student_selfcard
        WHERE student_id=#{studentId}
    </select>

</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhp.dao.StudentDao">

    <resultMap id="student" type="student">
        <id property="id" column="id"/>
        <result property="cnname" column="cnname"/>
        <result property="sex" column="sex"/>
        <result property="note" column="note"/>
        <!--一对一关联查询 -->
        <association property="studentSelfcard" column="id" select="com.zhp.dao.StudentSelfcardDao.findByStudentId"/>

    </resultMap>

    <select id="getStudnetById" resultMap="student">
      SELECT id,cnname,sex,note FROM t_student WHERE id=#{id}
    </select>


</mapper>
执行代码如下
public class MainXml {
    public static void main(String[] args) throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            StudentDao mapper = sqlSession.getMapper(StudentDao.class);
            Student student = mapper.getStudnetById(1);
            System.out.println(student);
        } finally {
            sqlSession.close();
        }
    }
}
默认是没有开启延迟加载的。输出如下
DEBUG  2017-10-16 16:07:33,746   com.zhp.dao.StudentDao.getStudnetById   ==>  Preparing: SELECT id,cnname,sex,note FROM t_student WHERE id=? 
DEBUG  2017-10-16 16:07:33,777   com.zhp.dao.StudentDao.getStudnetById   ==> Parameters: 1(Integer)
DEBUG  2017-10-16 16:07:33,792   com.zhp.dao.StudentSelfcardDao.findByStudentId   ====>  Preparing: SELECT id,student_id,native,issue_date,end_date,note FROM t_student_selfcard WHERE student_id=? 
DEBUG  2017-10-16 16:07:33,792   com.zhp.dao.StudentSelfcardDao.findByStudentId   ====> Parameters: 1(Integer)
DEBUG  2017-10-16 16:07:33,792   com.zhp.dao.StudentSelfcardDao.findByStudentId   <====      Total: 1
DEBUG  2017-10-16 16:07:33,792   com.zhp.dao.StudentDao.getStudnetById   <==      Total: 1
com.zhp.entity.Student@71a794e5

立即进行了两次查询而且Student不是代理对象
我们开启延迟加载配置
<!--延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
再次执行看结果
DEBUG  2017-10-16 16:10:59,766   org.apache.ibatis.transaction.jdbc.JdbcTransaction   Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@530612ba]
DEBUG  2017-10-16 16:10:59,781   com.zhp.dao.StudentDao.getStudnetById   ==>  Preparing: SELECT id,cnname,sex,note FROM t_student WHERE id=? 
DEBUG  2017-10-16 16:10:59,797   com.zhp.dao.StudentDao.getStudnetById   ==> Parameters: 1(Integer)
DEBUG  2017-10-16 16:10:59,844   com.zhp.dao.StudentDao.getStudnetById   <==      Total: 1
zhp

当我只输出cnname时 是没有查询t_student_selfcard表的。如果我们改为输出学生正对象,看执行结果
DEBUG  2017-10-16 16:12:47,963   com.zhp.dao.StudentDao.getStudnetById   ==>  Preparing: SELECT id,cnname,sex,note FROM t_student WHERE id=? 
DEBUG  2017-10-16 16:12:47,994   com.zhp.dao.StudentDao.getStudnetById   ==> Parameters: 1(Integer)
DEBUG  2017-10-16 16:12:48,041   com.zhp.dao.StudentDao.getStudnetById   <==      Total: 1
DEBUG  2017-10-16 16:12:48,041   com.zhp.dao.StudentSelfcardDao.findByStudentId   ==>  Preparing: SELECT id,student_id,native,issue_date,end_date,note FROM t_student_selfcard WHERE student_id=? 
DEBUG  2017-10-16 16:12:48,041   com.zhp.dao.StudentSelfcardDao.findByStudentId   ==> Parameters: 1(Integer)
DEBUG  2017-10-16 16:12:48,041   com.zhp.dao.StudentSelfcardDao.findByStudentId   <==      Total: 1
StudentSelfcard{id=1, studentId=1, anative='henan', issueDate=Mon Oct 16 13:00:00 CST 2017, endDate=Wed Oct 25 13:00:00 CST 2017, note='code'}
com.zhp.entity.Student_$$_jvst713_0@8b96fde

我们看到执行了两次查询而且Student对象是一个代理对象。

3.collection 一对多关联

 每个学生可以有多门课程,每个学生的课程对应一个成绩。
@Alias("student")
public class Student {

    private Integer id;

    private String cnname;

    private Integer sex;

    private StudentSelfcard studentSelfcard;

    private String note;

    private List<StudentLecture> studentLectureList;

@Alias("studentLecture")
public class StudentLecture {
    private Integer id;

    private Integer studentId;

    private Lecture lecture;

    private BigDecimal grade;

    private String note;
@Alias("lecture")
public class Lecture {

    private Integer id;

    private String lectureName;

    private String note;

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhp.dao.StudentDao">

    <resultMap id="student" type="student">
        <id property="id" column="id"/>
        <result property="cnname" column="cnname"/>
        <result property="sex" column="sex"/>
        <result property="note" column="note"/>
        <!--一对一关联查询 -->
        <association property="studentSelfcard" column="id" select="com.zhp.dao.StudentSelfcardDao.findByStudentId"/>

        <!--一对多关联查询 -->
        <collection property="studentLectureList" column="id" select="com.zhp.dao.StudentLectureDao.getByStudentId"/>
    </resultMap>

    <select id="getStudnetById" resultMap="student">
      SELECT id,cnname,sex,note FROM t_student WHERE id=#{id}
    </select>


</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhp.dao.StudentLectureDao">

    <resultMap id="studentLecture" type="studentLecture">
        <id property="id" column="id"/>
        <result property="studentId" column="student_id"/>
        <result property="grade" column="grade"/>
        <result property="note" column="note"/>
        <association property="lecture" column="lecture_id" select="com.zhp.dao.LectureDao.findById"/>
    </resultMap>

    <select id="getByStudentId" resultMap="studentLecture">
        SELECT id,student_id,lecture_id,grade,note FROM t_student_lecture
        WHERE student_id=#{studentId}
    </select>

</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhp.dao.LectureDao">

    <resultMap id="lecture" type="lecture">
        <id property="id" column="id"/>
        <result property="lectureName" column="lecture_name"/>
        <result property="note" column="note"/>
    </resultMap>

    <select id="findById" resultMap="lecture">
        SELECT id,lecture_name,note FROM t_lecture
        WHERE id=#{lectureId}
    </select>

</mapper>

public class MainXml {
    public static void main(String[] args) throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            StudentDao mapper = sqlSession.getMapper(StudentDao.class);
            Student student = mapper.getStudnetById(1);
            System.out.println(student.getStudentLectureList());
        } finally {
            sqlSession.close();
        }
    }
}
我们只获得学生课程信息列表 输出结果如下:
DEBUG  2017-10-16 16:45:49,517   com.zhp.dao.StudentDao.getStudnetById   ==>  Preparing: SELECT id,cnname,sex,note FROM t_student WHERE id=? 
DEBUG  2017-10-16 16:45:49,533   com.zhp.dao.StudentDao.getStudnetById   ==> Parameters: 1(Integer)
DEBUG  2017-10-16 16:45:49,580   com.zhp.dao.StudentDao.getStudnetById   <==      Total: 1
DEBUG  2017-10-16 16:45:49,580   com.zhp.dao.StudentLectureDao.getByStudentId   ==>  Preparing: SELECT id,student_id,lecture_id,grade,note FROM t_student_lecture WHERE student_id=? 
DEBUG  2017-10-16 16:45:49,580   com.zhp.dao.StudentLectureDao.getByStudentId   ==> Parameters: 1(Integer)
DEBUG  2017-10-16 16:45:49,595   com.zhp.dao.StudentLectureDao.getByStudentId   <==      Total: 2
DEBUG  2017-10-16 16:45:49,595   com.zhp.dao.LectureDao.findById       ==>  Preparing: SELECT id,lecture_name,note FROM t_lecture WHERE id=? 
DEBUG  2017-10-16 16:45:49,595   com.zhp.dao.LectureDao.findById        ==> Parameters: 1(Integer)
DEBUG  2017-10-16 16:45:49,595   com.zhp.dao.LectureDao.findById        <==      Total: 1
DEBUG  2017-10-16 16:45:49,595   com.zhp.dao.LectureDao.findById       ==>  Preparing: SELECT id,lecture_name,note FROM t_lecture WHERE id=? 
DEBUG  2017-10-16 16:45:49,595   com.zhp.dao.LectureDao.findById        ==> Parameters: 2(Integer)
DEBUG  2017-10-16 16:45:49,595   com.zhp.dao.LectureDao.findById        <==      Total: 1
我们使用了延迟加载配置,看到只输出了studentLectureList相关sql语句;如果同时我们也想输出studentSelfcard呢;我们将配置添加如下选项 
<setting name="aggressiveLazyLoading" value="true"/>
看到多个一个sql的输出如下:
DEBUG  2017-10-16 16:52:39,815   com.zhp.dao.StudentSelfcardDao.findByStudentId   ==>  Preparing: SELECT id,student_id,native,issue_date,end_date,note FROM t_student_selfcard WHERE student_id=? 
DEBUG  2017-10-16 16:52:39,815   com.zhp.dao.StudentSelfcardDao.findByStudentId   ==> Parameters: 1(Integer)
DEBUG  2017-10-16 16:52:39,815   com.zhp.dao.StudentSelfcardDao.findByStudentId   <==      Total: 1


我们看到studentSelfcard相关sql也执行了。

总结:aggressiveLazyLoading 如果设置为true,则不相关的懒加载属性也会去执行查询。如:我只执行了获取学
生课程成绩信息,但同级的属性学生证信息也执行了查询。
private StudentSelfcard studentSelfcard;

private List<StudentLecture> studentLectureList;

4.discriminator鉴别器级联

  鉴别器级联是在特定条件下,返回不同的POJO。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhp.dao.StudentDao">

    <resultMap id="student" type="student">
        <id property="id" column="id"/>
        <result property="cnname" column="cnname"/>
        <result property="sex" column="sex"/>
        <result property="note" column="note"/>
        <!--一对一关联查询 -->
        <association property="studentSelfcard" column="id" select="com.zhp.dao.StudentSelfcardDao.findByStudentId"/>

        <!--一对多关联查询 -->
        <collection property="studentLectureList" column="id" select="com.zhp.dao.StudentLectureDao.getByStudentId"/>

        <discriminator javaType="int" column="sex">
            <case value="1" resultMap="maleStudent"/>
            <case value="2" resultMap="femaleStudent"/>
        </discriminator>
    </resultMap>
    
    <resultMap id="maleStudent" type="maleStudent" extends="student">
        <collection property="studentHealthMaleList" column="id" select="com.zhp.dao.StudentHealthMaleDao.getByStudentId"/>
    </resultMap>

    <resultMap id="femaleStudent" type="femaleStudent" extends="student">
        <collection property="studentHealthFemaleList" column="id" select="com.zhp.dao.StudentHealthFemaleDao.getByStudentId"/>
    </resultMap>

    <select id="getStudnetById" resultMap="student">
      SELECT id,cnname,sex,note FROM t_student WHERE id=#{id}
    </select>


</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhp.dao.StudentHealthFemaleDao">

    <resultMap id="studentHealthFemale" type="studentHealthFemale">
        <id property="id" column="id"/>
        <result property="studentId" column="student_id"/>
        <result property="checkDate" column="check_datae"/>
        <result property="heart" column="heart"/>
        <result property="liver" column="liver"/>
        <result property="spleen" column="spleen"/>
        <result property="lung" column="lung"/>
        <result property="kidney" column="kidney"/>
        <result property="uterus" column="uterus"/>
        <result property="note" column="note"/>
    </resultMap>

    <select id="getByStudentId" resultMap="studentHealthFemale">
        SELECT id,student_id,check_datae,heart,liver,spleen,lung,kidney,uterus,note FROM t_student_health_female
        WHERE student_id=#{studentId}
    </select>

</mapper>

<?xml version="1.0" encoding="UTF-8" ?>
<!OCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhp.dao.StudentHealthMaleDao">

    <resultMap id="studentHealthMale" type="studentHealthMale">
        <id property="id" column="id"/>
        <result property="studentId" column="student_id"/>
        <result property="checkDate" column="check_datae"/>
        <result property="heart" column="heart"/>
        <result property="liver" column="liver"/>
        <result property="spleen" column="spleen"/>
        <result property="lung" column="lung"/>
        <result property="kidney" column="kidney"/>
        <result property="prostate" column="prostate"/>
        <result property="note" column="note"/>
    </resultMap>

    <select id="getByStudentId" resultMap="studentHealthMale">
        SELECT id,student_id,check_datae,heart,liver,spleen,lung,kidney,prostate,note FROM t_student_health_male
        WHERE student_id=#{studentId}
    </select>

</mapper>
package com.zhp.entity;

public class StudentHealthFemale extends StudentHealth {

    private String uterus;

    public String getUterus() {
        return uterus;
    }

    public void setUterus(String uterus) {
        this.uterus = uterus;
    }
}
package com.zhp.entity;

public class StudentHealthMale extends StudentHealth {
    private String prostate;

    public String getProstate() {
        return prostate;
    }

    public void setProstate(String prostate) {
        this.prostate = prostate;
    }
}
@Alias("femaleStudent")
public class FemaleStudent {
    private List<StudentHealthFemale> studentHealthFemaleList;

    public List<StudentHealthFemale> getStudentHealthFemaleList() {
        return studentHealthFemaleList;
    }

    public void setStudentHealthFemaleList(List<StudentHealthFemale> studentHealthFemaleList) {
        this.studentHealthFemaleList = studentHealthFemaleList;
    }
}
@Alias("maleStudent")
public class MaleStudent extends Student {
    private List<StudentHealthMale> studentHealthMaleList;

    public List<StudentHealthMale> getStudentHealthMaleList() {
        return studentHealthMaleList;
    }

    public void setStudentHealthMaleList(List<StudentHealthMale> studentHealthMaleList) {
        this.studentHealthMaleList = studentHealthMaleList;
    }
}  
public class MainXml {
    public static void main(String[] args) throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            StudentDao mapper = sqlSession.getMapper(StudentDao.class);
            Student student = mapper.getStudnetById(1);
            System.out.println(student);
        } finally {
            sqlSession.close();
        }
    }
}
我们看输出
DEBUG  2017-10-16 17:33:43,422   com.zhp.dao.StudentDao.getStudnetById   ==>  Preparing: SELECT id,cnname,sex,note FROM t_student WHERE id=? 
DEBUG  2017-10-16 17:33:43,453   com.zhp.dao.StudentDao.getStudnetById   ==> Parameters: 1(Integer)
DEBUG  2017-10-16 17:33:43,484   com.zhp.dao.StudentHealthMaleDao.getByStudentId   ====>  Preparing: SELECT id,student_id,check_datae,heart,liver,spleen,lung,kidney,prostate,note FROM t_student_health_male WHERE student_id=? 
DEBUG  2017-10-16 17:33:43,484   com.zhp.dao.StudentHealthMaleDao.getByStudentId   ====> Parameters: 1(Integer)
DEBUG  2017-10-16 17:33:43,500   com.zhp.dao.StudentHealthMaleDao.getByStudentId   <====      Total: 0
DEBUG  2017-10-16 17:33:43,500   com.zhp.dao.StudentDao.getStudnetById   <==      Total: 1
DEBUG  2017-10-16 17:33:43,500   com.zhp.dao.StudentLectureDao.getByStudentId   ==>  Preparing: SELECT id,student_id,lecture_id,grade,note FROM t_student_lecture WHERE student_id=? 
DEBUG  2017-10-16 17:33:43,500   com.zhp.dao.StudentLectureDao.getByStudentId   ==> Parameters: 1(Integer)
DEBUG  2017-10-16 17:33:43,500   com.zhp.dao.StudentLectureDao.getByStudentId   <==      Total: 2
DEBUG  2017-10-16 17:33:43,500   com.zhp.dao.StudentSelfcardDao.findByStudentId   ==>  Preparing: SELECT id,student_id,native,issue_date,end_date,note FROM t_student_selfcard WHERE student_id=? 
DEBUG  2017-10-16 17:33:43,500   com.zhp.dao.StudentSelfcardDao.findByStudentId   ==> Parameters: 1(Integer)
DEBUG  2017-10-16 17:33:43,515   com.zhp.dao.StudentSelfcardDao.findByStudentId   <==      Total: 1
com.zhp.entity.MaleStudent_$$_jvst713_0@35083305

实际生成的对象是MaleStudent

5.另一种级联

   通过sql一次性查询出所有的数据,根据关联配置,让mybatis帮你组装关联的数据。
<select id="findAllStudent" resultMap="student2" >
    SELECT s.id,s.cnname,s.sex,s.note AS snote,
        IF(sex=1,shm.id,shf.id) AS hid,
        IF(sex=1,shm.check_datae,shf.check_datae) AS check_date,
        IF(sex=1,shm.heart,shf.heart) AS heart,
        IF(sex=1,shm.liver,shf.liver) AS liver,
        IF(sex=1,shm.spleen,shf.spleen) AS spleen,
        IF(sex=1,shm.lung,shf.lung) AS lung,
        IF(sex=1,shm.kidney,shf.kidney) AS kidney,
        IF(sex=1,shm.note,shf.note) AS shnote,
        shm.prostate,shf.uterus,
        ss.id AS ssid, ss.native AS native,
        ss.issue_date,ss.end_date,ss.note AS ssnote,
        sl.id AS slid,
        sl.lecture_id,sl.grade,sl.note AS slnote,
        l.lecture_name,l.note AS lnote
        FROM t_student s
        LEFT JOIN t_student_health_male shm ON s.id=shm.student_id
        LEFT JOIN t_student_health_female shf ON s.id=shf.student_id
        LEFT JOIN t_student_selfcard ss ON s.id=ss.student_id
        LEFT JOIN t_student_lecture sl ON s.id =sl.student_id
        LEFT JOIN t_lecture l ON l.id=sl.lecture_id
</select>

<resultMap id="student2" type="student">
    <id property="id" column="id"/>
    <result property="cnname" column="cnname"/>
    <result property="sex" column="sex"/>
    <result property="note" column="snote"/>
    <association property="studentSelfcard" column="id" javaType="studentSelfcard">
        <id property="id" column="ssid"/>
        <result property="studentId" column="id"/>
        <result property="anative" column="native"/>
        <result property="issueDate" column="issue_date"/>
        <result property="endDate" column="end_date"/>
        <result property="note" column="ssnote"/>
    </association>

    <collection property="studentLectureList" column="id" ofType="studentLecture">
        <id property="id" column="slid"/>
        <result property="studentId" column="id"/>
        <result property="grade" column="grade"/>
        <result property="note" column="slnote"/>
        <association property="lecture" column="lecture_id" javaType="lecture">
            <id property="id" column="lecture_id"/>
            <result property="lectureName" column="lecture_name"/>
            <result property="note" column="lnote"/>
        </association>
    </collection>

    <discriminator javaType="int" column="sex">
        <case value="1" resultMap="maleStudent2"/>
        <case value="2" resultMap="femaleStudent2"/>
    </discriminator>
</resultMap>

<resultMap id="maleStudent2" type="maleStudent" extends="student2">
    <collection property="studentHealthMaleList" column="id" ofType="StudentHealthMale">
        <id property="id" column="hid"/>
        <result property="studentId" column="id"/>
        <result property="checkDate" column="check_date"/>
        <result property="heart" column="heart"/>
        <result property="liver" column="liver"/>
        <result property="spleen" column="spleen"/>
        <result property="lung" column="lung"/>
        <result property="kidney" column="kidney"/>
        <result property="prostate" column="prostate"/>
        <result property="note" column="note"/>
    </collection>
</resultMap>

<resultMap id="femaleStudent2" type="femaleStudent" extends="student2">
    <collection property="studentHealthFemaleList" column="id" ofType="StudentHealthFemale">
        <id property="id" column="hid"/>
        <result property="studentId" column="id"/>
        <result property="checkDate" column="check_date"/>
        <result property="heart" column="heart"/>
        <result property="liver" column="liver"/>
        <result property="spleen" column="spleen"/>
        <result property="lung" column="lung"/>
        <result property="kidney" column="kidney"/>
        <result property="uterus" column="uterus"/>
        <result property="note" column="note"/>
    </collection>
</resultMap>
public class MainXml {
    public static void main(String[] args) throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            StudentDao mapper = sqlSession.getMapper(StudentDao.class);
            List<Student> allStudent = mapper.findAllStudent();
            System.out.println(allStudent.size());
            for (Student student : allStudent) {
                System.out.println(student.getStudentLectureList().size());
            }
        } finally {
            sqlSession.close();
        }
    }
}
运行程序 查看结果
DEBUG  2017-10-17 10:38:39,241   org.apache.ibatis.datasource.pooled.PooledDataSource   Created connection 1825027294.
DEBUG  2017-10-17 10:38:39,241   org.apache.ibatis.transaction.jdbc.JdbcTransaction   Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@6cc7b4de]
DEBUG  2017-10-17 10:38:39,257   com.zhp.dao.StudentDao.findAllStudent   ==>  Preparing: SELECT s.id,s.cnname,s.sex,s.note AS snote, IF(sex=1,shm.id,shf.id) AS hid, IF(sex=1,shm.check_datae,shf.check_datae) AS check_date, IF(sex=1,shm.heart,shf.heart) AS heart, IF(sex=1,shm.liver,shf.liver) AS liver, IF(sex=1,shm.spleen,shf.spleen) AS spleen, IF(sex=1,shm.lung,shf.lung) AS lung, IF(sex=1,shm.kidney,shf.kidney) AS kidney, IF(sex=1,shm.note,shf.note) AS shnote, shm.prostate,shf.uterus, ss.id AS ssid, ss.native AS native, ss.issue_date,ss.end_date,ss.note AS ssnote, sl.id AS slid, sl.lecture_id,sl.grade,sl.note AS slnote, l.lecture_name,l.note AS lnote FROM t_student s LEFT JOIN t_student_health_male shm ON s.id=shm.student_id LEFT JOIN t_student_health_female shf ON s.id=shf.student_id LEFT JOIN t_student_selfcard ss ON s.id=ss.student_id LEFT JOIN t_student_lecture sl ON s.id =sl.student_id LEFT JOIN t_lecture l ON l.id=sl.lecture_id 
DEBUG  2017-10-17 10:38:39,272   com.zhp.dao.StudentDao.findAllStudent   ==> Parameters: 
DEBUG  2017-10-17 10:38:39,288   com.zhp.dao.StudentDao.findAllStudent   <==      Total: 2
1
2
返回两条数据,但是通过拼装后,只有一个,数据库是只有一个学生的数据的。结果正确。

6.mybatis 一级缓存和二级缓存

mybatis 默认只开启一级缓存,一级缓存只是相对应同一个SqlSession而言。
public class MainXml {
    public static void main(String[] args) throws IOException, InterruptedException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            StudentDao mapper = sqlSession.getMapper(StudentDao.class);
            Student studnetById1 = mapper.getStudnetById(1);
            System.out.println("第一次查询结束");
            Thread.sleep(2000);
            Student studnetById2 = mapper.getStudnetById(1);
            System.out.println("第二次查询结束");
            System.out.println(studnetById1 == studnetById2);
        } finally {
            sqlSession.close();
        }
    }
}
运行结果如下:
DEBUG  2017-10-17 10:49:59,956   com.zhp.dao.StudentDao.getStudnetById   ==>  Preparing: SELECT id,cnname,sex,note FROM t_student WHERE id=? 
DEBUG  2017-10-17 10:49:59,971   com.zhp.dao.StudentDao.getStudnetById   ==> Parameters: 1(Integer)
DEBUG  2017-10-17 10:50:00,018   com.zhp.dao.StudentHealthMaleDao.getByStudentId   ====>  Preparing: SELECT id,student_id,check_datae,heart,liver,spleen,lung,kidney,prostate,note FROM t_student_health_male WHERE student_id=? 
DEBUG  2017-10-17 10:50:00,018   com.zhp.dao.StudentHealthMaleDao.getByStudentId   ====> Parameters: 1(Integer)
DEBUG  2017-10-17 10:50:00,018   com.zhp.dao.StudentHealthMaleDao.getByStudentId   <====      Total: 0
DEBUG  2017-10-17 10:50:00,018   com.zhp.dao.StudentDao.getStudnetById   <==      Total: 1
第一次查询结束
第二次查询结束
true

最终只查询了一次。第二次查询使用了第一次查询的结果。两次查询返回的Student是对一个对象。

如果我们再打开一个SqlSession重新查询。看一下结果
public class MainXml {
    public static void main(String[] args) throws IOException, InterruptedException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            StudentDao mapper = sqlSession.getMapper(StudentDao.class);
            Student studnetById1 = mapper.getStudnetById(1);
            System.out.println("第一次查询结束");
            Thread.sleep(2000);
            Student studnetById2 = mapper.getStudnetById(1);
            System.out.println("第二次查询结束");
            System.out.println(studnetById1 == studnetById2);
        } finally {
            sqlSession.close();
        }

        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        try {
            StudentDao mapper = sqlSession2.getMapper(StudentDao.class);
            Student studnetById1 = mapper.getStudnetById(1);
            System.out.println("第三次查询结束");
        } finally {
            sqlSession2.close();
        }
    }
}
DEBUG  2017-10-17 10:53:05,561   org.apache.ibatis.transaction.jdbc.JdbcTransaction   Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@679b62af]
DEBUG  2017-10-17 10:53:05,561   com.zhp.dao.StudentDao.getStudnetById   ==>  Preparing: SELECT id,cnname,sex,note FROM t_student WHERE id=? 
DEBUG  2017-10-17 10:53:05,593   com.zhp.dao.StudentDao.getStudnetById   ==> Parameters: 1(Integer)
DEBUG  2017-10-17 10:53:05,624   com.zhp.dao.StudentHealthMaleDao.getByStudentId   ====>  Preparing: SELECT id,student_id,check_datae,heart,liver,spleen,lung,kidney,prostate,note FROM t_student_health_male WHERE student_id=? 
DEBUG  2017-10-17 10:53:05,624   com.zhp.dao.StudentHealthMaleDao.getByStudentId   ====> Parameters: 1(Integer)
DEBUG  2017-10-17 10:53:05,624   com.zhp.dao.StudentHealthMaleDao.getByStudentId   <====      Total: 0
DEBUG  2017-10-17 10:53:05,624   com.zhp.dao.StudentDao.getStudnetById   <==      Total: 1
第一次查询结束
第二次查询结束
true
DEBUG  2017-10-17 10:53:07,638   org.apache.ibatis.transaction.jdbc.JdbcTransaction   Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@679b62af]
DEBUG  2017-10-17 10:53:07,638   org.apache.ibatis.transaction.jdbc.JdbcTransaction   Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@679b62af]
DEBUG  2017-10-17 10:53:07,638   org.apache.ibatis.datasource.pooled.PooledDataSource   Returned connection 1738236591 to pool.
DEBUG  2017-10-17 10:53:07,638   org.apache.ibatis.transaction.jdbc.JdbcTransaction   Opening JDBC Connection
DEBUG  2017-10-17 10:53:07,638   org.apache.ibatis.datasource.pooled.PooledDataSource   Checked out connection 1738236591 from pool.
DEBUG  2017-10-17 10:53:07,638   org.apache.ibatis.transaction.jdbc.JdbcTransaction   Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@679b62af]
DEBUG  2017-10-17 10:53:07,638   com.zhp.dao.StudentDao.getStudnetById   ==>  Preparing: SELECT id,cnname,sex,note FROM t_student WHERE id=? 
DEBUG  2017-10-17 10:53:07,638   com.zhp.dao.StudentDao.getStudnetById   ==> Parameters: 1(Integer)
DEBUG  2017-10-17 10:53:07,638   com.zhp.dao.StudentHealthMaleDao.getByStudentId   ====>  Preparing: SELECT id,student_id,check_datae,heart,liver,spleen,lung,kidney,prostate,note FROM t_student_health_male WHERE student_id=? 
DEBUG  2017-10-17 10:53:07,638   com.zhp.dao.StudentHealthMaleDao.getByStudentId   ====> Parameters: 1(Integer)
DEBUG  2017-10-17 10:53:07,638   com.zhp.dao.StudentHealthMaleDao.getByStudentId   <====      Total: 0
DEBUG  2017-10-17 10:53:07,638   com.zhp.dao.StudentDao.getStudnetById   <==      Total: 1
第三次查询结束

我们看到第三次查询有执行Sql动作。


为了跨SqlSession共享数据,需要开启二级缓存,也就是SqlSessionFactory层面上。
mybatis配置文件中设置如下配置
<setting name="cacheEnabled" value="true"/>
mapper文件开启缓存
<cache/>
再次运行结果,输出如下:
DEBUG  2017-10-17 11:00:11,492   com.zhp.dao.StudentDao.getStudnetById   ==>  Preparing: SELECT id,cnname,sex,note FROM t_student WHERE id=? 
DEBUG  2017-10-17 11:00:11,524   com.zhp.dao.StudentDao.getStudnetById   ==> Parameters: 1(Integer)
DEBUG  2017-10-17 11:00:11,602   com.zhp.dao.StudentHealthMaleDao.getByStudentId   ====>  Preparing: SELECT id,student_id,check_datae,heart,liver,spleen,lung,kidney,prostate,note FROM t_student_health_male WHERE student_id=? 
DEBUG  2017-10-17 11:00:11,602   com.zhp.dao.StudentHealthMaleDao.getByStudentId   ====> Parameters: 1(Integer)
DEBUG  2017-10-17 11:00:11,602   com.zhp.dao.StudentHealthMaleDao.getByStudentId   <====      Total: 0
DEBUG  2017-10-17 11:00:11,602   com.zhp.dao.StudentDao.getStudnetById   <==      Total: 1
第一次查询结束
DEBUG  2017-10-17 11:00:13,602   com.zhp.dao.StudentDao                 Cache Hit Ratio [com.zhp.dao.StudentDao]: 0.0
第二次查询结束
true
DEBUG  2017-10-17 11:00:13,602   org.apache.ibatis.transaction.jdbc.JdbcTransaction   Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@282003e1]
DEBUG  2017-10-17 11:00:13,602   org.apache.ibatis.transaction.jdbc.JdbcTransaction   Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@282003e1]
DEBUG  2017-10-17 11:00:13,602   org.apache.ibatis.datasource.pooled.PooledDataSource   Returned connection 673186785 to pool.
DEBUG  2017-10-17 11:00:13,634   com.zhp.dao.StudentDao                 Cache Hit Ratio [com.zhp.dao.StudentDao]: 0.3333333333333333
第三次查询结束


我们看到第三次查询也命中了缓存。实际上第三次查询出的对象地址和第一次第二次是不一样的。因为有序列化和反序列化操作。

缓存配置总结:
<cache/> 默认配置
1.mapper文件中所有的select语句将会被缓存。
2.mapper文件中所有的insert,update,delete语句会刷新缓存。
3.缓存会使用默认的LRU算法来回收。
4.缓存会存储1024个对象引用。
5.缓存是可读写的。
自定义配置
<cache flushInterval="1000" readOnly="true" eviction="LRU" size="1024"/>

eviction:回收策略。LRU,FIFO,SOFT(软引用),WEAK(弱引用)
flushInterval:刷新间隔时间,单位为毫秒。
size:缓存对象个数。
readOnly:是否只读,默认false。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Mybatis级联查询可以通过在Mapper文件中使用嵌套查询的方式实现,具体步骤如下: 1. 在POJO类中定义关联属性(如一对多、多对多等),并提供对应的setter和getter方法。 2. 在Mapper文件中定义对应的嵌套查询语句,使用关联属性的getter方法来获取关联对象的数据,例如: ```xml <select id="findUserById" parameterType="int" resultMap="userResultMap"> select * from user where id = #{id} </select> <resultMap id="userResultMap" type="User"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="age" property="age"/> <association property="department" javaType="Department"> <id column="dept_id" property="id"/> <result column="dept_name" property="name"/> </association> </resultMap> <select id="findUserWithDeptById" parameterType="int" resultMap="userResultMap"> select u.*, d.dept_name from user u left join department d on u.dept_id = d.id where u.id = #{id} </select> ``` 在上述代码中,`findUserById`只查询User表中的数据,而`findUserWithDeptById`则查询User表和Department表中的数据,并将Department作为User对象的关联属性返回。 3. 在业务层中调用Mapper接口的方法,即可进行级联查询,例如: ```java User user = userMapper.findUserWithDeptById(1); System.out.println(user.getDepartment().getName()); ``` 在上述代码中,`userMapper.findUserWithDeptById`方法会返回一个User对象,其中的Department属性已经被赋值为关联的Department对象,通过getDepartment()方法即可获取Department对象的数据。 需要注意的是,在进行级联查询时,需要定义好关联属性的类型和对应的嵌套查询语句,否则会导致查询失败或数据不完整。同时,级联查询也会增加数据库的查询开销,应该根据实际情况进行使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值