自学内容网 自学内容网

MyBatis关联映射

目录

一、什么是关联注解?

二、数据库建表

1.学生表

2.教师表

三、一般查询

(1)创建StudentTeacher类

(2)mapper层

(3)Dao接口

(4)Test类

(5)测试结果

四、关联映射:一对一、多对一 

1、第一种形式 连表查询

(1)创建Student实体类

(2)mapper层

 (3)Dao接口

(4)Test类

(5)运行结果

 2.第二种形式 分步查询

(1)mapper层

(2)Dao层

(3)Test类

(4)运行结果

五、关联映射:一对多

1.第一种形式:按照结果嵌套处理

(1)设置实体类

(2)mapper层

(3)Dao接口

(4)Test类

(5)运行结果

2.第二种形式:按照查询嵌套处理 

(1).设置实体类

(2)mapper层

(3)Dao层

(4)Test类

(5)运行结果


一、什么是关联注解?

        MyBatis关联注解是在使用MyBatis进行数据库操作时,用于处理对象之间关联关系的注解。这些注解使得开发者可以更加灵活地处理数据库中的关联数据,而无需编写复杂的XML映射文件。 

二、数据库建表

1.学生表
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `Sname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `sex` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `t_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (1, '张三', '男', 18, 1);
INSERT INTO `student` VALUES (2, '李四', '女', 18, 1);
INSERT INTO `student` VALUES (3, '王五', '男', 18, 1);
INSERT INTO `student` VALUES (4, '小白', '女', 18, 1);
INSERT INTO `student` VALUES (5, '小黑', '男', 18, 1);
INSERT INTO `student` VALUES (6, '小红', '女', 20, 2);
INSERT INTO `student` VALUES (7, '小李', '男', 20, 2);
INSERT INTO `student` VALUES (8, '小张', '女', 20, 2);
INSERT INTO `student` VALUES (9, '小赵', '男', 20, 2);
INSERT INTO `student` VALUES (10, '小王', '女', 20, 2);

SET FOREIGN_KEY_CHECKS = 1;

2.教师表
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for teacher
-- ----------------------------
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `Tname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of teacher
-- ----------------------------
INSERT INTO `teacher` VALUES (1, '张老师');
INSERT INTO `teacher` VALUES (2, '李老师');

SET FOREIGN_KEY_CHECKS = 1;

三、一般查询

select student.*,teacher.* from student left join teacher on student.t_id=teacher.id 

结果如下

在idea中

(1)创建StudentTeacher类

按照表头进行变量属性设置,并设置getter&setter函数,重写toString方法

package com.qcby.entity;

public class StudentTeacher {

        private Integer id;
        private String Sname;
        private String sex;
        private Integer age;
        private Integer t_id;
        private String Tname;


        @Override
        public String toString() {
                return "StudentTeacher{" +
                        "id=" + id +
                        ", Sname='" + Sname + '\'' +
                        ", sex='" + sex + '\'' +
                        ", age=" + age +
                        ", t_id=" + t_id +
                        ", Tname='" + Tname + '\'' +
                        '}';
        }

        public Integer getId() {
                return id;
        }

        public void setId(Integer id) {
                this.id = id;
        }

        public String getSname() {
                return Sname;
        }

        public void setSname(String sname) {
                Sname = sname;
        }

        public String getSex() {
                return sex;
        }

        public void setSex(String sex) {
                this.sex = sex;
        }

        public Integer getAge() {
                return age;
        }

        public void setAge(Integer age) {
                this.age = age;
        }

        public Integer getT_id() {
                return t_id;
        }

        public void setT_id(Integer t_id) {
                this.t_id = t_id;
        }

        public String getTname() {
                return Tname;
        }

        public void setTname(String tname) {
                Tname = tname;
        }
}
(2)mapper层
<select id="findStudentTeacher" resultType="com.qcby.entity.StudentTeacher">
        SELECT  student.*,teacher.* FROM student  LEFT JOIN teacher  on student.t_id = teacher.id
    </select>
(3)Dao接口
package com.qcby.dao;

import com.qcby.entity.StudentTeacher;

import java.util.List;

public interface StudentTeacherDao {
    List<StudentTeacher> findStudentTeacher();
}
(4)Test类
package com.qcby;

import com.qcby.dao.StudentTeacherDao;
import com.qcby.entity.StudentTeacher;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class StudentTeacherTest {

    private InputStream in = null;
    private SqlSession session = null;
    private StudentTeacherDao mapper = null;

    @Before  //前置通知, 在方法执行之前执行
    public void init() throws IOException {
        //加载主配置文件,目的是为了构建SqlSessionFactory对象
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //创建SqlSessionFactory对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //通过SqlSessionFactory工厂对象创建SqlSesssion对象
        session = factory.openSession();
        //通过Session创建UserDao接口代理对象
        mapper = session.getMapper(StudentTeacherDao.class);
    }

    @After  //@After: 后置通知, 在方法执行之后执行 。
    public void destory() throws IOException {
        //释放资源
        session.close();
        in.close();
    }

    @Test
    public void findStudentTeacher(){
        List<StudentTeacher> studentTeacher=mapper.findStudentTeacher();
        for (StudentTeacher s:studentTeacher) {
            System.out.println(s.toString());
        }
    }
}
(5)测试结果

四、关联映射:一对一、多对一 

1、第一种形式 连表查询
(1)创建Student实体类

我们的目标是找到学生对应的老师:这个思路为先找到所有的学生,然后找到其所对应的老师

学生类

package com.qcby.entity;

public class Student {
    private Integer id;
    private String Sname;
    private String sex;
    private Integer age;
    private Integer t_id;
    //重要
    private Teacher teacher;

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", Sname='" + Sname + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                ", t_id=" + t_id +
//                ", teacher=" + teacher +
                '}';
    }

    public Teacher getTeacher() {
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getSname() {
        return Sname;
    }

    public void setSname(String sname) {
        Sname = sname;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getT_id() {
        return t_id;
    }

    public void setT_id(Integer t_id) {
        this.t_id = t_id;
    }
}

教师类

public class Teacher {
    private Integer id;
    private String Tname;
}

其中很重要的一行,这一行一定要加上 

private Teacher teacher;
(2)mapper层
<select id="findStudentTeacher" resultMap="StudentTeacher">
        SELECT  student.id,student.Sname,teacher.Tname FROM student  LEFT JOIN teacher  on student.t_id = teacher.id
</select>

<resultMap id="StudentTeacher" type="com.qcby.entity.Student">
        <result property="id" column="id"/>
        <result property="Sname" column="Sname"/>
        <result property="sex" column="sex"/>
        <result property="age" column="age"/>
        <result property="t_id" column="t_id"/>
        <association property="teacher" javaType="com.qcby.entity.Teacher">
            <result property="id" column="id"/>
            <result property="Tname" column="Tname"/>
        </association>
</resultMap>

resultMap是MyBatis中一个非常强大的特性,它用于定义结果映射。允许你将数据库中的列映射到Java对象的属性上,尤其是在处理复杂类型(如关联对象)时非常有用。以下是一些解释:

  1. resultMap标签
    • id="StudentTeacher":这是resultMap的唯一标识符,用于在查询语句中引用这个映射配置。
    • type="com.qcby.entity.Student":指定了这个resultMap映射到的Java类型,这里是com.qcby.entity.Student类。
  2. result标签
    • 这些标签用于定义数据库列到Java对象属性的直接映射。
    • 例如,<result property="id" column="id"/>表示将数据库中的id列映射到Student对象的id属性上。
    • 同样的,Snamesexaget_id列分别映射到Student对象的Snamesexaget_id属性上。
  3. association标签
    • <association property="teacher" javaType="com.qcby.entity.Teacher">:这个标签用于处理复杂类型的属性映射,这里表示Student对象中的teacher属性(类型为Teacher)的映射。
    • association内部,你可以定义Teacher对象的属性映射。例如,<result property="id" column="id"/><result property="Tname" column="Tname"/>表示将数据库中的idTname列映射到Teacher对象的idTname属性上。
    • 需要注意的是,这里的id列映射可能会有些混淆,因为在StudentTeacher的映射中都出现了。在实际应用中,可能需要通过别名(alias)来区分这两个id列,确保它们正确地映射到各自的对象属性上。如下:
  4.  <resultMap id="StudentTeacher1"  type="com.qcby.entity.Student">
            <id property="id" column="id"/>
            <result property="Sname" column="Sname"/>
            <result property="sex" column="sex"/>
            <result property="age" column="age"/>
            <result property="t_id" column="t_id"/>
            <!-- select="getTeacher"  :调用下一个查询语句       -->
            <!-- column="t_id" 两个表的关联字段-->
            <association property="teacher" column="t_id" javaType="com.qcby.entity.Teacher"
                         select="com.qcby.dao.TeacherDao.findTeacherById"/>
    </resultMap>
 (3)Dao接口
 List<Student> findStudentTeacher();
(4)Test类

    @Test
    public void findStudent(){
        List<Student> student=mapper.findStudentTeacher();
        for (Student s:student) {
            System.out.println(s.toString());
        }
    }
(5)运行结果

 2.第二种形式 分步查询

我们的目标是找到学生对应的老师:这个思路为先找到所有的老师,然后找到其所对应的学生

select * from student
select  * from  teacher where id = #{t_id};
(1)mapper层

StudentMapper.xml

  <select id = "findStudentTeacher1"  resultMap="StudentTeacher1">       
    select * from student;
  </select>  
  <resultMap id="StudentTeacher1"  type="com.qcby.entity.Student">
        <id property="id" column="id"/>
        <result property="Sname" column="Sname"/>
        <result property="sex" column="sex"/>
        <result property="age" column="age"/>
        <result property="t_id" column="t_id"/>
        <!-- select="getTeacher"  :调用下一个查询语句       -->
        <!-- column="t_id" 两个表的关联字段-->
        <association property="teacher" column="t_id" javaType="com.qcby.entity.Teacher"
                     select="com.qcby.dao.TeacherDao.findTeacherById"/>
   </resultMap>

TeacherMapper.xml

<select id="findTeacherById" resultType="com.qcby.entity.Teacher">
        select  * from  teacher where id = #{t_id};
</select>
(2)Dao层

StudentDao

 List<Student> findStudentTeacher1();

TeacherDao

 Teacher findTeacherById();
(3)Test类
 @Test
    public void findStudent1(){
        List<Student> student=mapper.findStudentTeacher1();
        for (Student s:student) {
            System.out.println(s.toString());
        }
    }
(4)运行结果

五、关联映射:一对多

查询每个老师有多少学生

1.第一种形式:按照结果嵌套处理
SELECT  teacher.id,teacher.name,student.name FROM teacher
 LEFT JOIN student  on student.t_id = teacher.id
(1)设置实体类

学生类

这里需要将student类当中关于teacher的字段删除

 private Integer id;
 private String Sname;
 private String sex;
 private Integer age;
 private Integer t_id;

教师类

因为要接收多个对象,这里用List<Student>

private Integer id;
private String Tname;
//这个一定要有
private List<Student> students;
(2)mapper层
 <select id="TeacherStudent" resultMap="TeacherStudent">
        SELECT  student.*,teacher.* FROM student  LEFT JOIN teacher  on student.t_id = teacher.id
</select>

 <resultMap id="TeacherStudent" type="com.qcby.entity.Teacher">
       <result property="id" column="id"/>
       <result property="Tname" column="Tname"/>

       <collection property="students" ofType="com.qcby.entity.Student">
            <result property="id" column="id"/>
            <result property="Sname" column="Sname"/>
            <result property="sex" column="sex"/>
            <result property="age" column="age"/>
            <result property="t_id" column="t_id"/>
       </collection>
</resultMap>

复杂的属性我们需要单独去处理——resultMap中接收:对象:association 集合:collection。在集合中的泛型信息,我们使用ofType获取。

(3)Dao接口
 List<Teacher> TeacherStudent();
(4)Test类
@Test
    public void TeacherStudent(){
        List<Teacher> teacher=mapper.TeacherStudent();
        for (Teacher t:teacher) {
            System.out.println(t.toString());
        }
    }
(5)运行结果

2.第二种形式:按照查询嵌套处理 
(1).设置实体类

这里的实体类不需要变动

(2)mapper层

TeacherMapper.xml

 <select id="TeacherStudent1" resultMap="TeacherStudent2">
        select * from teacher
 </select>
 <resultMap id="TeacherStudent2" type="com.qcby.entity.Teacher">
        <collection property="students" column="id" ofType="com.qcby.entity.Student"
                    select="com.qcby.dao.StudentDao.getStudentByTeacherId" />
 </resultMap>

StudentMapper.xml

<select id="getStudentByTeacherId" resultType="com.qcby.entity.Student">
        select * from student where t_id = #{t_id}
</select>
(3)Dao层

TeacherDao

 List<Teacher> TeacherStudent1();

StudentDao

Student findStudentById();
(4)Test类
@Test
    public void TeacherStudent1(){
        List<Teacher> teacher=mapper.TeacherStudent1();
        for (Teacher t:teacher) {
            System.out.println(t.toString());
        }
    }
(5)运行结果


原文地址:https://blog.csdn.net/2301_78566776/article/details/144327424

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!