mybatis学习9-一对一,一对多查询

mysql

CREATE DATABASE `mybatis`;
USE `mybatis`;
CREATE TABLE `teacher` (
  `id` INT(10) auto_increment PRIMARY KEY,
  `name` VARCHAR(30) DEFAULT NULL
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO teacher(`name`) VALUES ('秦老师'); 
INSERT INTO teacher(`name`) VALUES ('周老师'); 

CREATE TABLE `student` (
  `id` INT(10) auto_increment PRIMARY KEY,
  `name` VARCHAR(30) DEFAULT NULL,
  `tid` INT(10) DEFAULT NULL,
  KEY `fktid` (`tid`),
  CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO `student` (`name`, `tid`) VALUES ('小明', '1'); 
INSERT INTO `student` (`name`, `tid`) VALUES ('小红', '1'); 
INSERT INTO `student` (`name`, `tid`) VALUES ('小张', '1'); 
INSERT INTO `student` (`name`, `tid`) VALUES ('小李', '1'); 
INSERT INTO `student` (`name`, `tid`) VALUES ('小王', '1'); 

INSERT INTO `student` (`name`, `tid`) VALUES ('大明', '2'); 
INSERT INTO `student` (`name`, `tid`) VALUES ('大红', '2'); 
INSERT INTO `student` (`name`, `tid`) VALUES ('大张', '2'); 
INSERT INTO `student` (`name`, `tid`) VALUES ('大李', '2'); 
INSERT INTO `student` (`name`, `tid`) VALUES ('大王', '2'); 

一对一(一对多)

学生类

import lombok.Data;//lombook插件
@Data//GET,SET,ToString,有参,无参构造
public class Student {
    private int id;
    private String name;
    private Teacher teacher;
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

老师类


import lombok.Data;//lombook插件
@Data
public class Teacher {
    private int id;
    private String name;
}

学生类的代理接口

public interface StudentMapper {
    List<Student> listStudent();//获取学生及其老师的信息
    List<Student> listStudent2();//获取学生及其老师的信息
}

查询学生的同时查询出他的老师是哪个,可以直接通过一个语句直接查询到结果,但是这样是封装不到pojo对象的

select * from student s,teacher t
where s.tid = t.id

可以通过resultMap进行结果映射,有两种方法

1.按照结果嵌套处理

association关联属性

property:类的属性名

column:数据库中表的列名,或者列的别名,这里用的就是别名(select语句中定义了别名)

javaType:属性的类型

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cong.dao.StudentMapper">
    <!--直接查询出结果,进行结果集的映射-->
    <resultMap id="studentMap" type="student">
        <id property="id" column="sid"/>
        <result property="name" column="sname"/>
        <!--关联对象property 关联对象在Student实体类中的属性-->
        <association property="teacher" javaType="teacher">
            <id property="id" column="tid"/>
            <result property="name" column="tname"/>
        </association>
    </resultMap>
    <select id="listStudent" resultMap="studentMap">
        select s.id sid,s.name sname,t.id tid,t.name tname
        from student s,teacher t
        where s.tid = t.id
    </select>
</mapper>

2.还有一种,是按照查询进行嵌套处理的

根据数据库中学生表的tid获取老师的信息,在数据库中一般用关联查询

做一个结果集映射studentMap2,它的结果类型是Student

学生类中包含一个老师的属性teacher,对应数据库中的tid

其中select * from teacher where id = #{tid}是根据 select * from student 传递过来的tid进行查询的,

只有一个参数,所以这个#{tid}可以是任意值,比如#{aaaaaa},#{tttttt},都行

    <select id="listStudent2" resultMap="studentMap2">
        select * from student
    </select>
    <select id="getTeacher" resultType="teacher">
        select * from teacher where id = #{tid}
    </select>
    <resultMap id="studentMap2" type="student">
        <association property="teacher" column="tid" javaType="teacher" select="getTeacher"/>
    </resultMap>

如果是多个参数的话,是通过键值对的形式进行传递的

association中column多参数配置: column="{key=value,key=value}" ,key是传给下个sql的取值名称,value是片段一中sql查询的字段名。

比如

<resultMap id="StudentTeacher" type="Student">
    <association property="teacher"  column="{id=tid,name=tid}" javaType="Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="teacher">
    select * from teacher where id = #{id} and name = #{name}
</select>

测试类

public class Test1 {
    @Test
    public void test1() {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> students = mapper.listStudent();
        for (Student student : students) {
            System.out.println(
                    "学生:" + student.toString() +
                            "\t的老师是:\t" + student.getTeacher().toString()
            );
        }
    }
}

结果

小结

按照查询进行嵌套处理就像SQL中的子查询

按照结果进行嵌套处理就像SQL中的联表查询

一对多

查询一个老师,并且查询这个老师的所有学生

一个老师拥有多个学生

如果对于老师这边,就是一个一对多的现象,即一个老师下面拥有一群学生(集合)!

实体类

import lombok.Data;
@Data
public class Teacher {
    private int id;
    private String name;
    private List<Student> students;//一个老师多个学生
    @Override
    public String toString() {
        return "Teacher{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}


import lombok.Data;
@Data
public class Student {
    private int id;
    private String name;
    private int tid;
}

TeacherMapper接口

public interface TeacherMapper {
    Teacher getTeacher(int id);//获取指定老师,及老师下的所有学生
    Teacher getTeacher2(int id);//获取指定老师,及老师下的所有学生
}

思路:

1. 从学生表和老师表中查出学生id,学生姓名,老师姓名

2. 对查询出来的操作做结果集映射

因为老师类中的学生属性是一个集合,要使用collection

JavaType和ofType都是用来指定对象类型的

JavaType是用来指定pojo中属性的类型

ofType指定的是映射到list集合属性中pojo的类型。

1.第一种,是按照结果进行嵌套处理的

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cong.dao.TeacherMapper">
    <resultMap id="teacherMap" type="teacher">
        <id property="id" column="id"/>
        <result property="name" column="tname"/>
        <collection property="students" ofType="student">
            <id property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="tid"/>
        </collection>
    </resultMap>
    <select id="getTeacher" resultMap="teacherMap">
        select t.id,t.name tname,s.id sid,s.name sname,s.tid from teacher t,student s
        where t.id = s.tid and t.id = #{id}
    </select>
</mapper>

2.还有一种,是按照查询进行嵌套处理的

    <select id="getTeacher2" resultMap="teacherMap2">
        select * from teacher where id = #{id}
    </select>
    <select id="getStudentByTeacherId" resultType="student">
        select * from student where tid = #{id}
    </select>
    <resultMap id="teacherMap2" type="teacher">
        <id property="id" column="id"/>
        <!--column是一对多的外键 , 写的是一对多种一的主键的列名-->
        <collection property="students" column="id" javaType="arrayList" ofType="student" select="getStudentByTeacherId"/>
    </resultMap>

测试类

public class MyTest {
    @Test
    public void test1() {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        TeacherMapper teacherMapper = sqlSession.getMapper(TeacherMapper.class);
        Teacher teacher = teacherMapper.getTeacher(2);
        System.out.println("老师:  " + teacher.toString() + "\n他的学生:");
        List<Student> students = teacher.getStudents();
        for (Student student : students) {
            System.out.println("\t"+student.toString());
        }
        sqlSession.close();
    }
}

结果

 

小结

  1. 关联-association
  2. 集合-collection
  3. 所以association是用于一对一和多对一,而collection是用于一对多的关系
  4. JavaType和ofType都是用来指定对象类型的

    • JavaType是用来指定pojo中属性的类型
    • ofType指定的是映射到list集合属性中pojo的类型。

注意说明:

  1. 保证SQL的可读性,尽量通俗易懂
  2. 根据实际要求,尽量编写性能更高的SQL语句
  3. 注意属性名和字段不一致的问题
  4. 注意一对多和多对一 中:字段和属性对应的问题
  5. 尽量使用Log4j,通过日志来查看自己的错误
posted @ 2019-08-10 07:08  匆匆、  阅读(452)  评论(0编辑  收藏  举报