快速入门mybatis关联映射(详解)

目录

零、建表

1、学生表

2、老师表

一、多对一的关联映射

1、实体类、接口、mapper

2、连表查询 注意看下column不同情况下作用

3、分步查询

二、一对多的关联映射

1、实体类、接口、mapper

2、连表查询

3、分步查询

三、真正的分布查询


零、建表

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;

一、多对一的关联映射

1、实体类、接口、mapper

Teacher类

package com.qcby.entity;

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


}

Student类

public class Student {

    private Integer id;
    private String Sname;
    private String sex;
    private Integer age;
    private Integer t_id;
    
    //这个是重点
    private Teacher teacher;
}

注意哈,Student类里有一个Teacher类

接口

public interface StudentDao
{
    public List<Student> getStudentAndTeacher1();
    public List<Student> getStudentAndTeacher2();

}

Test

package com.qcby;

import com.qcby.dao.StudentDao;
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;

public class StudentTest {
    private InputStream in = null;//输入流
    private SqlSession session = null;//数据库会话
    private StudentDao mapper = null;//mapper-->映射

    @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(StudentDao.class);
    }

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


   @Test
    public void getStudentAndTeacher1(){
        mapper.getStudentAndTeacher1();

    }

    @Test
    public void getStudentAndTeacher2(){
        mapper.getStudentAndTeacher2();
}

2、连表查询 注意看下column不同情况下作用

首先认识一下子标签:

resultMap与resultType只能存在一个,而resultmap是映射

在select写完后,下面写resultmap的标签 id要与select中的一致。

type映射类型

result返回标签,
property实体类的对象
columnn查询数据库所返回的标签

当在association里的时候是向下传参的意思

association用于处理特殊类型如实体类,集合的标签
collection处理集合
javaType  java类后面是包名

上代码:


    <select id="getStudentAndTeacher1" resultMap="StudentTeacher1">
        select student.id,student.Sname,teacher.Tname
        from student left join teacher
        on student.t_id =teacher.id
    </select>
    <resultMap id="StudentTeacher1" type="com.qcby.entity.Student">
<!--        column:数据库查询返回的字段-->
        <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>
<!--    复杂属性 对象:association   集合:collection -->
    <!-- property="teacher" student类当中的关联字段 -->
    <!-- javaType="com.javen.model.Teacher" 为复杂属性设置类类型-->
<!--    此处的column向下传参-->

我们为什么要在association下有两个result呢?这是为了查询到sql语句中的teacher表的内容

3、分步查询

<select id="getStudentAndTeacher2" resultMap="st">
       select * from student
   </select>
    <resultMap id="st" 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" column="t_id" select="chaxun" javaType="com.qcby.entity.Teacher">
        </association>
    </resultMap>
    <select id="chaxun" resultType="com.qcby.entity.Teacher">
        select * from teacher where id =#{suibian};
    </select>

对比一下分布查询和连表查询代码的区别。

运行流程:查表往下走直到teacher类,调用select,把t_id传到下面的select,select#{}随便填。反正是接受上面的内容

如果对向下传参有疑惑,那就把t_id改为id

 现在懂了吧。

二、一对多的关联映射

1、实体类、接口、mapper

Student

public class Student {

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

Teacher

public class Teacher {
    private Integer id;
    private String Tname;
    private List<Student> students;
}

我们删除了Student类的Teacher而是在Teacher中加一个Student集合

每个类有自己该有的。

2、连表查询

<!--按照结果进行查询-->
<select id="getTeacher" resultMap="TeacherStudent">
    SELECT  teacher.id,teacher.Tname,student.Sname FROM teacher
        LEFT JOIN student  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"/>
    <!-- 复杂的属性我么需要单独去处理 对象:association   集合:collection
      在集合中的泛型信息,我们使用ofType获取
      -->
    <collection property="students" ofType="com.qcby.entity.Student">
        <result property="Sname" column="Sname"/>
    </collection>
</resultMap>

因为是集合类型,所以不用association而是用collection 类型是ofType类型

注意这点即可。

3、分步查询

<!--按照查询嵌套处理-->
<select id="getTeacher" resultMap="TeacherStudent2">
    select * from teacher
</select>
<resultMap id="TeacherStudent2" type="com.qcby.entity.Teacher">
    <collection property="students" column="id" javaType="ArrayList"
                ofType="com.qcby.entity.Student" select="getStudentByTeacherId" />
</resultMap>
<select id="getStudentByTeacherId" resultType="com.qcby.entity.Student">
    select * from student where t_id = #{t_id}
</select>

上面懂了 这个也就懂了。

三、真正的分布查询

不知道你有没有注意到分布查询查询teahcer的语句放入student类里,查询student同理。

这样其实还不算分布查询

我们应该讲查询老师的语句放在老师的mapper里。

现在我们来修改下多对一的

studentDao.xml

<select id = "getStudent"  resultMap="StudentTeacher">
    select * from student;
</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" column="t_id" javaType="com.qcby.entity.Teacher" 
                 select="com.qcby.dao.TeacherDao.getTeacher" />
</resultMap>

TeacherDao.xml

<select id="getTeacher" resultType="com.qcby.entity.Teacher" parameterType="java.lang.Integer">
    select  * from  teacher where id = #{t_id};
</select>

TeacherDao

Teacher getTeacher(Integer id);

可能出现的错误:

主配置文件没有对应mapper

调用select方法名与select的id不一致

自己完成真正的一对多的分布查询知之后,可以接着这个学习延迟加载

 MyBatis延迟加载策略(看了就会)_何妨徐行的博客-优快云博客

之后你就会了解我们为什么要使用分布查询以及如何设置延迟加载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值