mybatis(中)——操作多表(一对一、一对多、多对多)

〇、附

1、自定义一个工具类,用于获取sqlSession

package com.hbw.util;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class SqlSessionUtil {
    //读取核心配置文件
     static InputStream inputStream;
    //构建SqlSessionFactory
     static SqlSessionFactory sqlSessionFactory;
    static{
        try {
            inputStream = Resources.getResourceAsStream("mybatiesConfig.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

Ⅰ、一对一

一对一使用,association标签property bean中属性名称;javaType返回值类型。

表关系:一个学生一辆自行车。不要设置外键,不好维护。

学生表
在这里插入图片描述
学生实体类Student.java

package com.hbw.bean;

import java.io.Serializable;

public class Student implements Serializable {
   private int sid;
   private String sname;
   private int sage;
   private String ssex;
   private String semail;
   private Bicycle bicycle;

    public int getSid() {
        return sid;
    }

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

    public String getSname() {
        return sname;
    }

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

    public int getSage() {
        return sage;
    }

    public void setSage(int sage) {
        this.sage = sage;
    }

    public String getSsex() {
        return ssex;
    }

    public void setSsex(String ssex) {
        this.ssex = ssex;
    }

    public String getSemail() {
        return semail;
    }

    public void setSemail(String semail) {
        this.semail = semail;
    }

    public Bicycle getBicycle() {
        return bicycle;
    }

    public void setBicycle(Bicycle bicycle) {
        this.bicycle = bicycle;
    }

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

自行车表
在这里插入图片描述
自行车实体类Bicycle.java

package com.hbw.bean;

import java.io.Serializable;

public class Bicycle implements Serializable {
    private int bid;
    private String bname;
    private double bprice;

    public int getBid() {
        return bid;
    }

    public void setBid(int bid) {
        this.bid = bid;
    }

    public String getBname() {
        return bname;
    }

    public void setBname(String bname) {
        this.bname = bname;
    }

    public double getBprice() {
        return bprice;
    }

    public void setBprice(double bprice) {
        this.bprice = bprice;
    }
    @Override
    public String toString() {
        return "Bicycle{" +
                "bid=" + bid +
                ", bname='" + bname + '\'' +
                ", bprice=" + bprice +
                '}';
    }
}

一、嵌套结果集(连接查询)

因为是连接查询,所以sql语句比较复杂,但是步骤较少。数据库学得好的推荐这类
原理:左外连接查询学生信息和自行车信息,通过共同字段sid联系起来。

这里,展示全部代码信息,后面的其他方式中,直接补充新增加的内容。

1、dao层接口StudentDao.java

package com.hbw.dao;

import com.hbw.bean.Student;

public interface StudentDao {
    /**
     * 通过学生id查询学生信息和学生的自行车的信息,,嵌套结果集
     */
    public Student getStudentBicycleByid(int sid);
}

2、映射文件StudentMapperDao.xml

<?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.hbw.dao.StudentDao">
    <!--通过学生id查询学生信息和学生用于的自行车的信息,,嵌套结果集-->
    <resultMap id="studentBicycle" type="student">
        <id column="sid" property="sid"></id>
        <result column="sname" property="sname"></result>
        <result column="sage" property="sage"></result>
        <result column="ssex" property="ssex"></result>
        <result column="semail" property="semail"></result>
        <!--一对一使用,association标签-->
        <!--property bean中属性名称;javaType返回值类型-->
        <association property="bicycle" javaType="bicycle">
            <id column="bid" property="bid"></id>
            <result column="bname" property="bname"></result>
            <result column="bprice" property="bprice"></result>
        </association>
    </resultMap>
    <select id="getStudentBicycleByid" resultMap="studentBicycle">
        SELECT s.sid,s.sname,s.sage,s.ssex,s.semail,b.bid,b.bname,b.bprice
            FROM student s LEFT JOIN bicycle b ON s.sid=b.sid
            WHERE s.sid=#{sid};
    </select>
</mapper>

3、测试StudentUtil.java

import com.hbw.bean.Student;
import com.hbw.dao.StudentDao;
import com.hbw.util.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class StudentUtil {
    private SqlSession sqlSession;
    private  StudentDao sd;
    @Before
    public void before(){
        sqlSession = SqlSessionUtil.getSqlSession();
        sd = sqlSession.getMapper(StudentDao.class);
    }
    @After
    public void after(){
        sqlSession.commit();
        sqlSession.close();
    }
    /**
     * 测试一对一关系,嵌套结果集
     */
    @Test
    public void test2(){
        Student stu = sd.getStudentBicycleByid(17);
        System.out.println(stu);
    }
}

4、结果
Student{sid=17, sname=‘张三’, sage=17, ssex=‘男’, semail=‘110@qq.com’, bicycle=Bicycle{bid=1, bname=‘FRW 辐轮王’, bprice=1200.0}}

二、嵌套查询(子查询)

因为是多次查询,所以比较繁杂,但是sql语句简单。
原理:第一次查询学生信息,再通过学生id查询自行车信息

1、在StudentDao.java中新增内容

 	/**
     * 通过学生id查询学生信息和学生的自行车的信息,,嵌套查询
     */
    public Student getStudentBicycleByid2(int sid);

2、在StudentMapperDao.xml中新增内容

 <!--通过学生id查询学生信息和学生用于的自行车的信息,嵌套查询-->
    <resultMap id="studentBicycle2" type="student">
        <id column="sid" property="sid"></id>
        <result column="sname" property="sname"></result>
        <result column="sage" property="sage"></result>
        <result column="ssex" property="ssex"></result>
        <result column="semail" property="semail"></result>
        <!--一对一使用,association标签-->
        <!--property bean中属性名称;column第二次查询的入参;select再次查询-->
        <association property="bicycle" column="sid"  select="com.hbw.dao.BicycleDao.getBicycleById"></association>
    </resultMap>
    <select id="getStudentBicycleByid2" resultMap="studentBicycle2">
        select sid,sname,sage,ssex,semail from student where sid=#{sid}
    </select>

3、新建BicycleMapper.xml

<?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.hbw.dao.BicycleDao">
    <select id="getBicycleById" resultType="bicycle">
        select bid,bname,bprice from bicycle where sid=#{sid}
    </select>
</mapper>

4、在StudentUtil.java中新增内容

/**
     * 测试一对一关系,嵌套查询
     */
    @Test
    public void test3(){
        Student stu = sd.getStudentBicycleByid2(17);
        System.out.println(stu);
    }

5、结果
在这里插入图片描述

Ⅱ、一对多

collection标签关联一对多关系表查询;oftype属性指定集合中自定义的类(查询的多条数据封装在集合中的类型)

表关系:一个学生有多位任课老师

老师表
在这里插入图片描述
老师表实体类Teacher.java

package com.hbw.bean;

import java.io.Serializable;

public class Teacher implements Serializable {
    private int tid;
    private String tname;
    private double twages;

    public int getTid() {
        return tid;
    }

    public void setTid(int tid) {
        this.tid = tid;
    }

    public String getTname() {
        return tname;
    }

    public void setTname(String tname) {
        this.tname = tname;
    }

    public double getTwages() {
        return twages;
    }

    public void setTwages(double twages) {
        this.twages = twages;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "tid=" + tid +
                ", tname='" + tname + '\'' +
                ", twages=" + twages +
                '}';
    }
}

修改学生表Student.java
在这里插入图片描述

一、嵌套结果集

1、在StudentDao.java中新增内容

/*一对多通过学生id查询学生信息,还有他的任课老师的信息,嵌套结果集*/
    public Student getStudentTeacherById(int sid);

2、在StudentMapperDao.xml中新增内容

<!--一对多通过学生id查询学生信息,还有他的任课老师的信息,嵌套结果集-->
    <resultMap id="studentTeacher" type="student">
        <id column="sid" property="sid"></id>
        <result column="sname" property="sname"></result>
        <result column="sage" property="sage"></result>
        <result column="ssex" property="ssex"></result>
        <result column="semail" property="semail"></result>
        <!--collection是对应一对多关系的标签;property:Student实体类中的属性名;ofType:返回值类型(主配置文件去了别名)-->
        <collection property="teacherList" ofType="teacher">
            <id column="tid" property="tid"></id>
            <result column="tname" property="tname"></result>
            <result column="twages" property="twages"></result>
        </collection>
    </resultMap>
    <select id="getStudentTeacherById" resultMap="studentTeacher">
        SELECT s.sid,s.sname,s.sage,s.ssex,s.semail,t.tid,t.tname,t.twages
        FROM student s LEFT JOIN teacher t ON s.sid=t.sid
        WHERE s.sid=#{sid};
    </select>

3、在StudentUtil.java中新增内容

/*通过学生id获取学生信息,并获取他的任课老师,嵌套结果集*/
    @Test
    public void test4(){
        Student stu = sd.getStudentTeacherById(17);
        System.out.println(stu);
    }

4、结果
在这里插入图片描述

二、嵌套查询

1、在StudentDao.java中新增内容

 /*一对多通过学生id查询学生信息,还有他的任课老师的信息,嵌套查询*/
    public Student getStudentTeacherById2(int sid);

2、在StudentMapperDao.xml中新增内容

<!--一对多通过学生id查询学生信息,还有他的任课老师的信息,嵌套结果集-->
    <resultMap id="studentTeacher2" type="student">
        <id column="sid" property="sid"></id>
        <result column="sname" property="sname"></result>
        <result column="sage" property="sage"></result>
        <result column="ssex" property="ssex"></result>
        <result column="semail" property="semail"></result>
        <!--collection是对应一对多关系的标签;property:Student实体类中的属性名;ofType:返回值类型(主配置文件去了别名)-->
        <collection property="teacherList" column="sid" select="com.hbw.dao.TeacherDao.getTeacherById"></collection>
    </resultMap>
    <select id="getStudentTeacherById2" resultMap="studentTeacher2">
        SELECT sid,sname,sage,ssex,semail FROM student WHERE sid=#{sid};
    </select>

3、新建TeacherMapper.xml

<?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.hbw.dao.TeacherDao">
    <!--一对多,通过sid'查到tacher的信息-->
    <select id="getTeacherById" resultType="teacher">
        select tid,tname,twages from teacher where sid=#{sid}
    </select>
</mapper>

4、在StudentUtil.java中新增内容

/*通过学生id获取学生信息,并获取他的任课老师,嵌套查询*/
    @Test
    public void test5(){
        Student stu = sd.getStudentTeacherById2(17);
        System.out.println(stu);
    }

5、结果
在这里插入图片描述

Ⅲ、多对多

表关系:一个学生多位老师,每位老师多门课程,中间用课程表来连接
课程种类表course
在这里插入图片描述
课程表timeable
比如,一号老师(张老师)教1、2、3号课程(语数外)
在这里插入图片描述

课程表实体类Course

package com.hbw.bean;

import java.io.Serializable;

public class Course implements Serializable {
    private int cid;
    private String cname;

    public int getCid() {
        return cid;
    }

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

    public String getCname() {
        return cname;
    }

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

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

修改实体类Teacher.java
在这里插入图片描述

一、嵌套结果集

1、在StudentDao.java中新增内容

 /*多对多通过学生id查找学生信息、老师信息,再通过老师的tid查找老师的课程,嵌套结果集*/
    public Student getStudentTeacherCourseById(int sid);

2、在StudentMapperDao.xml中新增内容

 <!--多对多通过学生id查找学生信息、老师信息,再通过老师的tid查找老师的课程,嵌套结果集-->
    <resultMap id="studentTeacherCourse" type="student">
        <id column="sid" property="sid"></id>
        <result column="sname" property="sname"></result>
        <result column="sage" property="sage"></result>
        <result column="ssex" property="ssex"></result>
        <result column="semail" property="semail"></result>
         <!--collection多对多关系也使用这个标签(单向看其实也就是一对多的关系),property实体类中属性名;ofType返回值类型-->
        <collection property="teacherList" ofType="teacher">
            <id column="tid" property="tid"></id>
            <result column="tname" property="tname"></result>
            <result column="twages" property="twages"></result>
            <collection property="courseList" ofType="course">
                <id column="cid" property="cid"></id>
                <result column="cname" property="cname"></result>
            </collection>
        </collection>
    </resultMap>
    <select id="getStudentTeacherCourseById" resultMap="studentTeacherCourse">
        SELECT s.sid,s.sname,s.sage,s.ssex,s.semail,t.tid,t.tname,t.twages,c.cid,c.cname
        FROM student s LEFT JOIN teacher t ON s.sid=t.sid
        LEFT JOIN timetable tt ON t.tid=tt.tid
        LEFT JOIN course c ON tt.cid=c.cid
        WHERE s.sid=#{sid};
    </select>

3、在StudentUtil.java中新增内容

 /*多对多,嵌套查询*/
    @Test
    public void test6(){
        Student stu = sd.getStudentTeacherCourseById(17);
        System.out.println(stu);
    }

4、结果
在这里插入图片描述
17号张三同学的任课老师有张老师、李老师、王老师;
张老师教了语数外;
李老师教了体育;
王老师教了物理

二、嵌套查询

1、在StudentDao.java新增内容

/*多对多通过学生id查找学生信息、老师信息,再通过老师的tid查找老师的课程,嵌套查询*/
    public Student getStudentTeacherCourseById2(int sid);

2、在StudentMapperDao.xml新增内容

第一次查询

<!--多对多通过学生id查找学生信息、老师信息,再通过老师的tid查找老师的课程,嵌套查询-->
    <resultMap id="studentTeacherCourse2" type="student">
        <id column="sid" property="sid"></id>
        <result column="sname" property="sname"></result>
        <result column="sage" property="sage"></result>
        <result column="ssex" property="ssex"></result>
        <result column="semail" property="semail"></result>
        <!--collection多对多关系也使用这个标签(单向看其实也就是一对多的关系),property实体类中属性名;ofType返回值类型-->
        <collection property="teacherList" column="sid" select="com.hbw.dao.TeacherDao.getTeacherByIds"></collection>
    </resultMap>
    <select id="getStudentTeacherCourseById2" resultMap="studentTeacherCourse2">
        SELECT s.sid,s.sname,s.sage,s.ssex,s.semail FROM student s  WHERE s.sid=#{sid};
    </select>

3、在TeacherMapper.xml新增内容

第二次查询

<!--多对多,通过sid'查到tacher的信息-->
    <resultMap id="teachers" type="teacher">
        <id column="tid" property="tid"></id>
        <result column="tname" property="tname"></result>
        <result column="twages" property="twages"></result>
        <collection property="courseList" column="tid" select="com.hbw.dao.Course.getCourseById"></collection>
    </resultMap>
    <select id="getTeacherByIds" resultMap="teachers">
        select tid,tname,twages from teacher where sid=#{sid}
    </select>

4、新建CourseMapper.xml

第三次查询。使用tid,通过中间表timetable查询课程信息

<?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.hbw.dao.Course">
    <select id="getCourseById" resultType="course">
        SELECT c.cid,c.cname
        FROM course c LEFT JOIN timetable tt ON c.cid=tt.cid
        WHERE tid=#{tid};
    </select>
</mapper>

5、在StudentUtil.java中新增内容

 /*多对多,嵌套查询*/
    @Test
    public void test7(){
        Student stu = sd.getStudentTeacherCourseById2(17);
        System.out.println(stu);
    }

6、结果
在这里插入图片描述






总结 0

1、嵌套结果集与嵌套查询
嵌套结果集:连接查询,sql语句复杂,步骤少
嵌套查询操作:多次查询,sql语句简单,步骤多

2、一对一
1)嵌套结果集。
使用association标签,其中property属性表示bean中成员名称;javaType属性表示返回值类型(一般是实体类全类名,这里批量取别名了)

 <association property="bicycle" javaType="bicycle">
      <id column="bid" property="bid"></id>
      <result column="bname" property="bname"></result>
      <result column="bprice" property="bprice"></result>
  </association>

2)嵌套查询
使用association标签,其中property属性表示bean中成员名称;column属性表示再次查询的入参;select再次查询的路径

 <association property="bicycle" column="sid"  select="com.hbw.dao.BicycleDao.getBicycleById"></association>

3、一对多、多对多(单向看也是一对多)
1)嵌套结果集
使用collection标签,其中property属性表示实体类中的成员变量名(一般都是集合);ofType属性表示返回值类型(一般是实体类全限定名称,这里批量取别名了)

<collection property="teacherList" ofType="teacher">
     <id column="tid" property="tid"></id>
     <result column="tname" property="tname"></result>
     <result column="twages" property="twages"></result>
 </collection>

2)嵌套查询
使用collection标签,其中property属性表示实体类中的成员变量名(一般都是集合);column表示再次查询的入参;select表示再次查询的路径

<collection property="teacherList" column="sid" select="com.hbw.dao.TeacherDao.getTeacherById"></collection>

4、查询多表时,返回值类型只能使用ResultMap

5、注意:每新增一个映射配置文件,都需要在主配置文件的mappers(映射器)中添加mapper映射路径

<!--resource就是主程序配置文件夹Resources-->
<mappers>
  <mapper resource="AMapper.xml"/>
  <mapper resource="BMapper.xml"/>
</mappers>





疑惑
dao层接口如何找到mapper配置文件中对应的查询语句

👉Mybatis(上)——简介、入门案例、主配置文件、映射配置文件、基于接口操作数据库、模糊查询、参数传递、执行原理
👉mybatis(下)——<![CDATA[…]]>、动态sql语句详解、懒加载、缓存、逆向工程、纯注解操作数据库

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈年_H

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值