java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > MyBatis高级映射及延迟加载

MyBatis高级映射及延迟加载的实现

作者:代码代码快快显灵

MyBatis在处理对象关系映射时,多对一关系是常见的场景,本文就来介绍了MyBatis高级映射及延迟加载的实现,感兴趣的可以了解一下

多对一:

多种方式,常见的包括三种:

怎么区分主表和副表?

原则:谁在前面谁是主表

例如:多对一,多在前面,那么多的那个表就是主表

级联属性映射:

Student类:

package pojo;

/**
 * 学生信息
 * 没有cid这个属性,后期会有特殊的方式来处理这个关系字段
 */
public class Student {
    private Integer sid;
    private String sname;
    private Clazz clazz;

    public Clazz getClazz() {
        return clazz;
    }

    public void setClazz(Clazz clazz) {
        this.clazz = clazz;
    }

    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", sname='" + sname + '\'' +
                ", clazz=" + clazz +
                '}';
    }

    public Student() {
    }

    public Student(Integer sid, String sname) {
        this.sid = sid;
        this.sname = sname;
    }

    public Integer getSid() {
        return sid;
    }

    public void setSid(Integer sid) {
        this.sid = sid;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }
}

对应的sql映射文件:

<?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="mapper.StudentMapper">

    <!-- 级联属性映射 -->

    <resultMap id="studentResultMap" type="Student">
        <id property="sid" column="sid"/>
        <result property="sname" column="sname"/>
        <result property="clazz.cid" column="cid"/>
        <result property="clazz.cname" column="cname"/>
    </resultMap>
    <select id="selectById" resultMap="studentResultMap">
        SELECT
            s.sid, s.sname, c.cid, c.cname
        FROM
            t_student_plus s
                LEFT JOIN
            t_clazz c ON s.cid = c.cid
        WHERE
            s.sid = #{sid}
    </select>

</mapper>
@Test
    public void testSelectBySid(){
        StudentMapper mapper = SqlSessionUtil.openSession().getMapper(StudentMapper.class);
        Student student = mapper.selectBySid(1);
        System.out.println(student);
    }

sql语句:

2024-10-14 13:29:58.511 [main] DEBUG mapper.StudentMapper.selectById - ==>  Preparing: 
SELECT s.sid, s.sname, c.cid, c.cname FROM t_student_plus s 
LEFT JOIN t_clazz c ON s.cid = c.cid WHERE s.sid = ?

association

对应的sql映射文件:

  <resultMap id="studentResultMapAssociation" type="Student">
        <id property="sid" column="sid"/>
        <result property="sname" column="sname"/>
        <!-- 嵌套映射,将 clazz 对象中的 cid 和 cname 映射 -->
        <association property="clazz" javaType="Clazz">
            <id property="cid" column="cid"/>
            <result property="cname" column="cname"/>
        </association>
    </resultMap>
    <select id="selectByIdAssociation" resultMap="studentResultMap">
        SELECT
            s.sid, s.sname, c.cid, c.cname
        FROM
            t_student_plus s
                LEFT JOIN
            t_clazz c ON s.cid = c.cid
        WHERE
            s.sid = #{sid}
    </select>

association翻译为:关联。 学生对象关联一个班级对象。

关键点说明

分步查询

  <resultMap id="studentResultMapByStep" type="Student">
        <id property="sid" column="sid"/>
        <id property="sname" column="sname"/>
       <association property="clazz"
                            select="mapper.ClazzMapper.selectByCid"
                            column="cid"/>
    </resultMap>

<!--两条sql语句,完成多对一的分布查询-->
<!--    这是第一步,根据id值查询学生的所有信息,这些信息当中含有班级id(cid-->
<select id="selectByIdStep1" resultMap="studentResultMapByStep" >
    select sid,sname,cid from t_student_plus where sid = #{sid}
</select>

解释:

 在ClazzMapper接口中添加方法

public interface ClazzMapper {

    /**
     * 分布查询第二步
     * 根据cid获取Clazz信息
     * @param cid
     * @return
     */
    Clazz selectByCid(Integer cid);
}

 ClazzMapper的sql映射文件:

<?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="mapper.ClazzMapper">
<select id="selectByCid" resultType="Clazz">
    select cid,cname from t_clazz where cid = #{cid}
</select>
</mapper>

执行结果,可以很明显看到先后有两条sql语句执行:

延迟加载

一对多延迟加载机制和多对一是一样的。同样是通过两种方式:

第一种:fetchType="lazy"

  <resultMap id="studentResultMapByStep" type="Student">
        <id property="sid" column="sid"/>
        <id property="sname" column="sname"/>
       <association property="clazz"
                            select="mapper.ClazzMapper.selectByCid"
                            column="cid"
                            fetchType="lazy"/> <!--添加延迟-->
    </resultMap>

<!--两条sql语句,完成多对一的分布查询-->
<!--    这是第一步,根据id值查询学生的所有信息,这些信息当中含有班级id(cid-->
<select id="selectByIdStep1" resultMap="studentResultMapByStep" >
    select sid,sname,cid from t_student_plus where sid = #{sid}
</select>

第二种:修改全局的配置setting,lazyLoadingEnabled=true,如果开启全局延迟加载,想让某个sql不使用延迟加载:fetchType="eager"

一对多

一对多的实现,通常是在一的一方中有List集合属性。

在Clazz类中添加List<Student> stus; 属性。

package pojo;

import java.util.List;

/**
 * 班级信息
 */
public class Clazz {

    public Clazz() {
    }

    private Integer cid;
    private String cname;
    private List<Student> stus;

    public List<Student> getStus() {
        return stus;
    }

    @Override
    public String toString() {
        return "Clazz{" +
                "cid=" + cid +
                ", cname='" + cname + '\'' +
                ", stus=" + stus +
                '}';
    }

    public void setStus(List<Student> stus) {
        this.stus = stus;
    }

    public Integer getCid() {
        return cid;
    }

    public void setCid(Integer cid) {
        this.cid = cid;
    }

    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }

    public Clazz(Integer cid, String cname) {
        this.cid = cid;
        this.cname = cname;
    }
}

一对多的实现通常包括两种实现方式:

collection:

public interface ClazzMapper {

    /**
     * 根据cid获取Clazz信息
     * @param cid
     * @return
     */
    Clazz selectByCid(Integer cid);

    /**
     * 根据班级编号查询班级信息。同时班级中所有的学生信息也要查询。
     * @param cid
     * @return
     */
    Clazz selectClazzAndStusByCid(Integer cid);
}
<resultMap id="clazzResultMap" type="Clazz">
  <id property="cid" column="cid"/>
  <result property="cname" column="cname"/>
  <collection property="stus" ofType="Student">
    <id property="sid" column="sid"/>
    <result property="sname" column="sname"/>
  </collection>
</resultMap>

<select id="selectClazzAndStusByCid" resultMap="clazzResultMap">
  select * from t_clazz c join t_student s on c.cid = s.cid where c.cid = #{cid}
</select>

 注意是ofType,表示“集合中的类型”!!!

分步查询:

<resultMap id="clazzResultMap" type="Clazz">
  <id property="cid" column="cid"/>
  <result property="cname" column="cname"/>
  <!--主要看这里-->
  <collection property="stus"
              select="com.powernode.mybatis.mapper.StudentMapper.selectByCid"
              column="cid"/>
</resultMap>

<!--sql语句也变化了-->
<select id="selectClazzAndStusByCid" resultMap="clazzResultMap">
  select * from t_clazz c where c.cid = #{cid}
</select>
/**
* 根据班级编号获取所有的学生。
* @param cid
* @return
*/
List<Student> selectByCid(Integer cid);
<select id="selectByCid" resultType="Student">
  select * from t_student where cid = #{cid}
</select>

延迟加载

一对多延迟加载机制和多对一是一样的。同样是通过两种方式:

到此这篇关于MyBatis高级映射及延迟加载的实现的文章就介绍到这了,更多相关MyBatis高级映射及延迟加载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文