Mybatis关联查询一对一和一对多的实现

Mybatis一对一关联查询

有两张表,老师表teacher和班级表class,一个class班级对应一个teacher,一个teacher对应一个class

需求是根据班级id查询班级信息(带老师的信息)

创建teacherclass表:

CREATE TABLE teacher (
        t_id INT PRIMARY KEY AUTO_INCREMENT,
        t_name VARCHAR(20)
    );
    CREATE TABLE class (
        c_id INT PRIMARY KEY AUTO_INCREMENT,
        c_name VARCHAR(20),
        teacher_id INT
    );
    ALTER TABLE class ADD CONSTRAINT fk_teacher_id FOREIGN KEY (teacher_id) REFERENCES
    teacher(t_id);
    INSERT INTO teacher(t_name) VALUES(‘LS1‘);
    INSERT INTO teacher(t_name) VALUES(‘LS2‘);
    INSERT INTO class(c_name, teacher_id) VALUES(‘bj_a‘, 1);
    INSERT INTO class(c_name, teacher_id) VALUES(‘bj_b‘, 2);

首先定义实体类 
老师Teacher

package mybatis.bean;

    public class Teacher {

        private int id;
        private String name;

        public Teacher() {

        }

        public Teacher(int id, String name) {
            super();
            this.id = id;
            this.name = name;
        }

        public int getId() {
            return id;
        }

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

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "Teacher [id=" + id + ", name=" + name + "]";
        }

    }

班级Class

package mybatis.bean;

public class Class {

    private int id;
    private String name;
    private Teacher teacher;

    public Class() {
    }

    public Class(int id, String name, Teacher teacher) {
        super();
        this.id = id;
        this.name = name;
        this.teacher = teacher;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Teacher getTeacher() {
        return teacher;
    }

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

    @Override
    public String toString() {
        return "Class [id=" + id + ", name=" + name + ", teacher=" + teacher + "]";
    }

}

要实现一对一关联查询,有两种方式

1.关联表查询

SELECT * FROM class c, teacher t WHERE c.teacher_id = t.t_id AND c.c_id = 1;

2.执行2次查询 
先查询class表,获取teacher_id,再查询teacher表,获取teacher的信息

SELECT * FROM class where c_id = 1;
SELECT * FROM teacher where t_id = 1;//使用上面得到的teacher_id

这两种查询方式就引出了2中方式

  • 嵌套结果: 使用嵌套结果映射来处理重复的联合结果的子集
  • 嵌套查询:通过执行另外一个SQL 映射语句来返回预期的复杂类型

二、一对多关联

创建表和数据

  在上面的一对一关联查询演示中,我们已经创建了班级表和教师表,因此这里再创建一张学生表

CREATE TABLE student(
    s_id INT PRIMARY KEY AUTO_INCREMENT,
    s_name VARCHAR(20),
    class_id INT
);
INSERT INTO student(s_name, class_id) VALUES(‘student_A‘, 1);
INSERT INTO student(s_name, class_id) VALUES(‘student_B‘, 1);
INSERT INTO student(s_name, class_id) VALUES(‘student_C‘, 1);
INSERT INTO student(s_name, class_id) VALUES(‘student_D‘, 2);
INSERT INTO student(s_name, class_id) VALUES(‘student_E‘, 2);
INSERT INTO student(s_name, class_id) VALUES(‘student_F‘, 2);

定义实体类

  1、Student类

package me.gacl.domain;

/**
 * @author gacl
 * 定义student表所对应的实体类
 */
public class Student {

    //定义属性,和student表中的字段对应
    private int id;            //id===>s_id
    private String name;    //name===>s_name

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student [id=" + id + ", name=" + name + "]";
    }
}

2、修改Classes类,添加一个List<Student> students属性,使用一个List<Student>集合属性表示班级拥有的学生,如下:

package me.gacl.domain;

import java.util.List;

/**
 * @author gacl
 * 定义class表对应的实体类
 */
public class Classes {

    //定义实体类的属性,与class表中的字段对应
    private int id;            //id===>c_id
    private String name;    //name===>c_name

    /**
     * class表中有一个teacher_id字段,所以在Classes类中定义一个teacher属性,
     * 用于维护teacher和class之间的一对一关系,通过这个teacher属性就可以知道这个班级是由哪个老师负责的
     */
    private Teacher teacher;
    //使用一个List<Student>集合属性表示班级拥有的学生
    private List<Student> students;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Teacher getTeacher() {
        return teacher;
    }

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

    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }

    @Override
    public String toString() {
        return "Classes [id=" + id + ", name=" + name + ", teacher=" + teacher
                + ", students=" + students + "]";
    }
}

修改sql映射文件classMapper.xml

  添加如下的SQL映射信息

<!--
        根据classId查询对应的班级信息,包括学生,老师
     -->
    <!--
    方式一: 嵌套结果: 使用嵌套结果映射来处理重复的联合结果的子集
    SELECT * FROM class c, teacher t,student s WHERE c.teacher_id=t.t_id AND c.C_id=s.class_id AND  c.c_id=1
     -->
    <select id="getClass3" parameterType="int" resultMap="ClassResultMap3">
        select * from class c, teacher t,student s where c.teacher_id=t.t_id and c.C_id=s.class_id and  c.c_id=#{id}
    </select>
    <resultMap type="me.gacl.domain.Classes" id="ClassResultMap3">
        <id property="id" column="c_id"/>
        <result property="name" column="c_name"/>
        <association property="teacher" column="teacher_id" javaType="me.gacl.domain.Teacher">
            <id property="id" column="t_id"/>
            <result property="name" column="t_name"/>
        </association>
        <!-- ofType指定students集合中的对象类型 -->
        <collection property="students" ofType="me.gacl.domain.Student">
            <id property="id" column="s_id"/>
            <result property="name" column="s_name"/>
        </collection>
    </resultMap>

    <!--
        方式二:嵌套查询:通过执行另外一个SQL映射语句来返回预期的复杂类型
            SELECT * FROM class WHERE c_id=1;
            SELECT * FROM teacher WHERE t_id=1   //1 是上一个查询得到的teacher_id的值
            SELECT * FROM student WHERE class_id=1  //1是第一个查询得到的c_id字段的值
     -->
     <select id="getClass4" parameterType="int" resultMap="ClassResultMap4">
        select * from class where c_id=#{id}
     </select>
     <resultMap type="me.gacl.domain.Classes" id="ClassResultMap4">
        <id property="id" column="c_id"/>
        <result property="name" column="c_name"/>
        <association property="teacher" column="teacher_id" javaType="me.gacl.domain.Teacher" select="getTeacher2"></association>
        <collection property="students" ofType="me.gacl.domain.Student" column="c_id" select="getStudent"></collection>
     </resultMap>

     <select id="getTeacher2" parameterType="int" resultType="me.gacl.domain.Teacher">
        SELECT t_id id, t_name name FROM teacher WHERE t_id=#{id}
     </select>

     <select id="getStudent" parameterType="int" resultType="me.gacl.domain.Student">
        SELECT s_id id, s_name name FROM student WHERE class_id=#{id}
     </select>

编写单元测试代码

package me.gacl.test;

import me.gacl.domain.Classes;
import me.gacl.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class Test4 {

    @Test
    public void testGetClass3(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        /**
         * 映射sql的标识字符串,
         * me.gacl.mapping.classMapper是classMapper.xml文件中mapper标签的namespace属性的值,
         * getClass3是select标签的id属性值,通过select标签的id属性值就可以找到要执行的SQL
         */
        String statement = "me.gacl.mapping.classMapper.getClass3";//映射sql的标识字符串
        //执行查询操作,将查询结果自动封装成Classes对象返回
        Classes clazz = sqlSession.selectOne(statement,1);//查询class表中id为1的记录
        //使用SqlSession执行完SQL之后需要关闭SqlSession
        sqlSession.close();
        //打印结果:Classes [id=1, name=class_a, teacher=Teacher [id=1, name=teacher1], students=[Student [id=1, name=student_A], Student [id=2, name=student_B], Student [id=3, name=student_C]]]
        System.out.println(clazz);
    }

    @Test
    public void testGetClass4(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        /**
         * 映射sql的标识字符串,
         * me.gacl.mapping.classMapper是classMapper.xml文件中mapper标签的namespace属性的值,
         * getClass4是select标签的id属性值,通过select标签的id属性值就可以找到要执行的SQL
         */
        String statement = "me.gacl.mapping.classMapper.getClass4";//映射sql的标识字符串
        //执行查询操作,将查询结果自动封装成Classes对象返回
        Classes clazz = sqlSession.selectOne(statement,1);//查询class表中id为1的记录
        //使用SqlSession执行完SQL之后需要关闭SqlSession
        sqlSession.close();
        //打印结果:Classes [id=1, name=class_a, teacher=Teacher [id=1, name=teacher1], students=[Student [id=1, name=student_A], Student [id=2, name=student_B], Student [id=3, name=student_C]]]
        System.out.println(clazz);
    }
}

原文地址:https://www.cnblogs.com/wuqi2328857945/p/9621760.html

时间: 2024-08-05 16:12:55

Mybatis关联查询一对一和一对多的实现的相关文章

【Mybatis】Mybatis关联查询一对一和一对多的实现

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 本文主要讲了使用Mybatis实现关联查询,分为一对一和一对多两种情况,最后并对ResultMap进行一个简要说明. 一.创建表.分析 下面是两表,一个是顾客表,一个是车票表.一个顾客可以对应多张车票,但是一张车票只能对应一个顾客 t_customer:顾客表,一个顾客可以对应多张车票 t_ticket:车票表,一张车票只能对应一个顾客 1.创建数据表及插入初始数据 创建数据表 use te

MyBatis 级联查询一对一与一对多

mybatis是通过映射sql语句把关系模型(数据库中的表)与领域模型(java中的实体类)关联起的  简单分析级联查询:       关系模型中:表与表只有主外键关联       领域模型中:实体类与实体类这间关联,只有一和多的关系.                            一是指别一个实体类以对象属性存在当前实体类中.                            多是指别一个实体类以集合对象属性存在当前实体类中 下面我以例子的形式给大家说明:数据库脚本如下:drop

MyBatis关联查询,一对多关联查询

实体关系图,一个国家对应多个城市 一对多关联查询可用三种方式实现: 单步查询,利用collection标签为级联属性赋值: 分步查询: 利用association标签进行分步查询: 利用collection标签进行分步查询 单步查询 利用collection标签实现一对多单步关联查询: 指定进行关联查询的Java Bean字段,即collection标签的 property 属性: 指定集合中的Java Bean类型,即collection标签的 ofType属性: 实体类 public cla

mybatis关联查询问题(一对多、多对一)

mybatis 提供了高级的关联查询功能,可以很方便地将数据库获取的结果集映射到定义的Java Bean 中.下面通过一个实例,来展示一下Mybatis对于常见的一对多和多对一关系复杂映射是怎样处理的. 设计一个简单的博客系统,一个用户可以开多个博客,在博客中可以发表文章,允许发表评论,可以为文章加标签.博客系统主要有以下几张表构成: Author表:作者信息表,记录作者的信息,用户名和密码,邮箱等. Blog表   :  博客表,一个作者可以开多个博客,即Author和Blog的关系是一对多.

mybatis关联查询,一对一,一对多

注:这篇文章的代码有部分删减,不能直接使用,不过关键代码都存在  应用场景: 想用mybatis做关联查询,并且把查询出的数据自动组装成对象可以使用关联查询. 1.一对一实现 例如:一部小说,属于一个分类,查询小说的时候想同时查询出所属分类. 1)实体定义: public class Book { private static final long serialVersionUID = 1L; /** *小说ID */ private Integer bookId; /** *作者 */ pri

7.MyBatis 关联查询(一对一)

1 关联查询映射     1.1 分析数据模型         思路 : 每张表记录的数据内容 每张表重要的字段(主键,外键,非空字段) 表与表之间的关系(外键关系) 表与表之间的业务关系(建立在某个业务意义基础上去分析) 如图:     1.2 一对一查询 有三种实现方法: resultType resultMap中的association嵌套查询 resultMap中的嵌套结果 需求: 进行订单查询,包括用户的姓名和地址信息  SQL语句: SELECT orders.id,orders.u

MyBatis关联查询、多条件查询

1.一对一查询 任务需求; 根据班级的信息查询出教师的相关信息 1.数据库表的设计 班级表: 教师表: 2.实体类的设计 班级表: public class Classes { 9     //定义实体类的属性,与class表中的字段对应 10     private int id;            //id===>c_id 11     private String name;    //name===>c_name 13     /** 14      * class表中有一个tea

myBatis --关联查询

业务需求,需要查询到的结果集如下 结构分析 1.查询出所有的评论,即data[]里面是一个list 2.查出list中每个评论id(即userObjectCmmtId)下面所有的子评论,即一对多的关系. 实现方法如下 1.接口层文件如下 2.实现层文件如下 3.返回第一层bean如下 返回第二层bean 4.xml文件如下(第一层)    <resultMap type="com.zhiji.caren.VO.CmmtRel" id="cmmtListMap"

Spring+SpringMVC+MyBatis深入学习及搭建(六)——MyBatis关联查询(转发同上)

原地址:http://www.cnblogs.com/shanheyongmu/p/7122520.html 1.商品订单数据模型 1.1数据模型分析思路 (1)每张表记录的数据内容 分模块对每张表记录的内容进行熟悉,相当于你学习系统需求(功能)的过程. (2)每张表重要的字段设置 非空字段.外键字段 (3)数据库级别表与表之间的关系 外键关系 (4)表与表之间的业务关系 在分析表与表之间的业务关系时,一定要建立在某个业务意义基础上去分析. 1.2属性模型分析 2.一对一查询 2.1需求 查询订