Mybatis_复杂环境(一对多,多对一)实现,查询嵌套、结果嵌套,association、collection

复杂环境(一对多,多对一)实现

  • 一对多
  • 多对一

多个学生和一个老师的问题

image-20200818140945757

不同的角度分析问题,

  • 对于学生而言,关联,多个学生关联一个老师(多对一)

  • 对于老师而言,集合,一个老师,有多个学生(一对多 )

在resultMap设置中还有其余一些设置

  • association 一个复杂类型的关联
  • collection 一个复杂类型的集合
  • image-20200818141539221

环境搭建

  1. 添加student表和teacher表

    1. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SgZSfBdQ-1597762948536)(…/…/…/AppData/Roaming/Typora/typora-user-images/image-20200818150653053.png)]
    2. 要设置外键
  2. image-20200818153628192

    1. 模块结构

    2. 实体类、实体类接口,接口映射xml文件,核心配置文件、工具类

      1. 实体类

      2. @Data
        @AllArgsConstructor
        @NoArgsConstructor
        public class Student {
            private int id;
            private String name;
            private Teacher teacher;
        }
        
      3. 实体类映射接口

      4. public interface TeacherMapper {
            @Select("select * from teacher where id = #{tid}")
            List<Teacher> getTeacher(@Param("tid") int id);
        }
        
      5. mapper.xml文件

      6. <?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.haoyun.dao.TeacherMapper">
        </mapper>
        
      7. 核心配置文件

      8. <mappers>
            <mapper resource="StudentMapper.xml"/>
            <mapper resource="TeacherMapper.xml"/>
        </mappers>
        
      9. 简单测试

      10. @Test
        public void teacher(){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
            List<Teacher> teacher = mapper.getTeacher(2);
            for (Teacher teacher1 : teacher) {
                System.out.println(teacher1);
            }
            sqlSession.close();
        
        }
        

多对一的处理

  • sql可以直接写出来,
select * from student,teacher where teacher.id=student.tid

有两种形式:

  • 按照查询嵌套处理
  • 按照结果嵌套处理

如何写入方法思路:

  1. 查询所有学生信息
  2. 根据查询出来的学生的tid,寻找对应的老师寻找对应的老师

解决问题,主要流程:

  • JavaBean类设置别名好操作
  • 编写mapper.xml文件
    • 使用resultMap的association设置
  • 注册核心文件
  • 测试

按照查询嵌套处理

  1. 设置别名

    1. @Data
      @AllArgsConstructor
      @NoArgsConstructor
      @Alias("Student")
      public class Student {
          private int id;
          private String name;
          private Teacher teacher;
      }
      
    2. @Data
      @AllArgsConstructor
      @NoArgsConstructor
      @Alias("Teacher")
      public class Teacher {
          private int id;
          private String name;
      }
      
  2. 编写mapper.xml文件

    1. <?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.haoyun.dao.StudentMapper">
      
          <resultMap id="StudentTeacher" type="Student">
              <!--映射名称  返回值类型-->
      <!--        <result property="name" column="name"/>-->
              <!--属性名和字段名同名的可以不用写了-->
              <!--association  关联-->
              <!--collection  集合-->
              <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
              <!--这里的property是一个对象,通过tid不能直接获取,javaType设置这个对象的类型,然后加入一个查询getTeacher-->
          </resultMap>
      
          <select id="getStudent" resultMap="StudentTeacher">
              select * from student
          </select>
      
          <select id="getTeacher" resultType="Teacher">
              <!--这个子查询的#引用因为只有一个,所以名字随便写也会自动匹配-->
              select  * from teacher where  id  =#{id}
          </select>
      
      </mapper>
      
    2. 有点类似子查询,按照查询嵌套处理

  3. 添加核心配置文件映射

    1. <mappers>
          <mapper resource="StudentMapper.xml"/>
          <mapper resource="TeacherMapper.xml"/>
      </mappers>
      
  4. 测试

    1. @Test
      public void teacher(){
          SqlSession sqlSession = MybatisUtils.getSqlSession();
          StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
          List<Student> student = mapper.getStudent();
          for (Student student1 : student) {
              System.out.println(student1);
          }
          sqlSession.close();
      
      }
      
    2. image-20200818191356284

按照结果嵌套处理

  1. 嵌套处理

    1. <resultMap id="StudentTeacher2" type="Student">
          <result property="id" column="sid"/>
          <result property="name" column="sname"/>
      
          <association property="teacher" javaType="Teacher">
              <!--在Student,javaBean中,教师是用属性名teacher的,类型为Teacher,这里面嵌套一个结果集映射-->
              <result property="name" column="tname"/>
          </association>
          
      </resultMap>
      
      <select id="getStudent2" resultMap="StudentTeacher2">
          select s.id sid,s.name sname,t.name tname
          from teacher t,student s
          where s.tid = t.id;
      </select>
      
  2. 测试

    1. 结果是一样的
  3. 总结:

    1. 多对一查询方式主要也就两种
      1. 子查询
      2. 联表查询

一对多的处理

  • 重点就是在配置TeacherMapper.xml上
  1. 编写JavaBean

    1. @Data
      @AllArgsConstructor
      @NoArgsConstructor
      @Alias("Teacher")
      public class Teacher {
          private int id;
          private String name;
          private List<Student> students;
      
      }
      
    2. 一个老师对应多个学生,学生是一个集合用list装起来

    3. @Data
      @AllArgsConstructor
      @NoArgsConstructor
      @Alias("Student")
      public class Student {
          private int id;
          private String name;
          private int tid;
      }
      
    4. 学生的一些属性

  2. 编写TeacherMapper.xml文件时要先理清关系,要做的是个一个老师有哪些学生,所以先定位哪个老师

    1. image-20200818214803299

    2. 这样就能查出老师id为1的老师有哪些学生

    3. image-20200818214840807

    4. 需要传递一个老师对应的id

    5. 所以编写接口的时候需要传递id

    6. List<Teacher> getTeacherById(@Param("id")int id);
      
    7. <mapper namespace="com.haoyun.dao.TeacherMapper">
          <resultMap id="TeacherStudent" type="Teacher">
              <result property="id" column="tid"/>
              <result property="name" column="tname"/>
              
              <collection property="students" ofType="Student">
                  <result property="id" column="sid"/>
                  <result property="name" column="sname"/>
                  <result property="tid" column="tid"/>
              </collection>
              
          </resultMap>
      
          <select id="getTeacherById" resultMap="TeacherStudent">
              select s.id sid,s.name sname,t.name tname,t.id tid
              from teacher t,student s
              where s.tid=t.id and t.id = #{id}
          </select>
      
      
      
      </mapper>
      
    8. 因为这条select语句采用了很多别名,所以编写map的时候需要多加几个结果集映射

    9. 这是按照结果嵌套来处理的

  • 按照查询嵌套

  • <select id="getTeacherById2" resultMap="TeacherStudent2">
        select * from teacher where id = #{id}
    </select>
    <resultMap id="TeacherStudent2" type="Teacher">
        <collection property="students" javaType="ArrayList"  ofType="Student" select="student" column="id"/>
    </resultMap>
    
    <select id="student" resultType="Student">
        select  * from student where tid = #{id}
    </select>
    
  • 查询嵌套,先查询一个再查询一个

小结:

  • 关联 association(多对一)
  • 集合 collection(一对多)
  • javaType & ofType
    • javaType 用来指定实体类中属性的类型
    • ofType 用来指定映射到List或者集合中的POJO类型(List),泛型中的约束类型
  • 注意点
  • 保证sql的可读性
  • 注意属性名和字段问题
  • 使用日志好进行错误排查,建议使用LOG4J

慢SQL,比较慢,就是少自己写,多搜集点效率高的sql语句,到时遇到了直接用

面试高频:

  • Mysql引擎
  • InnoDB底层原理
  • 索引
  • 索应优化
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值