SSM-MyBatis-15:Mybatis中关联查询(多表操作)

------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥-------------

先简单提及一下关联查询的分类

  1.一对多

    1.1单条SQL操作的

    1.2多条SQL操作的

  2.多对一

    2.1单条SQL操作的

    2.1多条SQL操作的

  3.多对多(类似一对多)

  4.自关联(也有点类似一对多)

下面是具体实现,用真实代码带入进去(数据表和实体类和测试方法都给发出来,更多的要关注到xml中的使用)

  我先把用到的数据库的脚本发一下,里面有测试数据,我折起来,需要使用的可以自行提取

/*
SQLyog v10.2
MySQL - 5.6.24 : Database - s2228
*********************************************************************
*/

/*!40101 SET NAMES utf8 */;

/*!40101 SET SQL_MODE=‘‘*/;

/*!40014 SET @[email protected]@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @[email protected]@SQL_MODE, SQL_MODE=‘NO_AUTO_VALUE_ON_ZERO‘ */;
/*!40111 SET @[email protected]@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`s2228` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `s2228`;

/*Table structure for table `book` */

DROP TABLE IF EXISTS `book`;

CREATE TABLE `book` (
  `bookID` int(11) NOT NULL AUTO_INCREMENT,
  `bookName` varchar(32) DEFAULT NULL,
  `bookAuthor` varchar(32) DEFAULT NULL,
  `bookPrice` int(11) DEFAULT NULL,
  PRIMARY KEY (`bookID`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

/*Data for the table `book` */

insert  into `book`(`bookID`,`bookName`,`bookAuthor`,`bookPrice`) values (1,‘程序员的人生‘,‘老原教育‘,500),(2,‘皮的修养‘,‘郭彦‘,999),(3,‘如何成为一代大牛‘,‘迟总‘,500),(4,‘心想事成‘,‘孟六‘,999),(5,‘心想事成‘,‘孟六‘,999),(6,‘心想事成‘,‘孟七‘,999),(7,‘心想事成‘,‘孟七‘,999),(8,‘心想事成‘,‘孟七‘,999);

/*Table structure for table `category` */

DROP TABLE IF EXISTS `category`;

CREATE TABLE `category` (
  `cid` int(11) NOT NULL AUTO_INCREMENT,
  `cname` varchar(32) DEFAULT NULL,
  `pid` int(11) NOT NULL,
  PRIMARY KEY (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

/*Data for the table `category` */

insert  into `category`(`cid`,`cname`,`pid`) values (1,‘图书‘,0),(2,‘青年图书‘,1),(3,‘少儿图书‘,1),(4,‘我爱科学‘,3),(5,‘服装‘,0),(6,‘羽绒服‘,5);

/*Table structure for table `dept` */

DROP TABLE IF EXISTS `dept`;

CREATE TABLE `dept` (
  `deptNo` int(8) NOT NULL AUTO_INCREMENT,
  `deptName` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`deptNo`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

/*Data for the table `dept` */

insert  into `dept`(`deptNo`,`deptName`) values (1,‘开发部‘);

/*Table structure for table `emp` */

DROP TABLE IF EXISTS `emp`;

CREATE TABLE `emp` (
  `empNo` int(8) NOT NULL AUTO_INCREMENT,
  `empName` varchar(32) DEFAULT NULL,
  `deptNo` int(8) NOT NULL,
  PRIMARY KEY (`empNo`),
  KEY `emp_deptNo_Fk_dept_deptNo_pk` (`deptNo`),
  CONSTRAINT `emp_deptNo_Fk_dept_deptNo_pk` FOREIGN KEY (`deptNo`) REFERENCES `dept` (`deptNo`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

/*Data for the table `emp` */

insert  into `emp`(`empNo`,`empName`,`deptNo`) values (1,‘孟六‘,1),(2,‘孟六‘,1);

/*Table structure for table `student` */

DROP TABLE IF EXISTS `student`;

CREATE TABLE `student` (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `sname` varchar(32) NOT NULL,
  PRIMARY KEY (`sid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

/*Data for the table `student` */

insert  into `student`(`sid`,`sname`) values (1,‘孟六‘),(2,‘王五‘),(3,‘赵七‘),(4,‘郭皮‘);

/*Table structure for table `teacher` */

DROP TABLE IF EXISTS `teacher`;

CREATE TABLE `teacher` (
  `tid` int(11) NOT NULL AUTO_INCREMENT,
  `tname` varchar(32) NOT NULL,
  PRIMARY KEY (`tid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

/*Data for the table `teacher` */

insert  into `teacher`(`tid`,`tname`) values (1,‘迟老师‘),(2,‘原老师‘),(3,‘付老师‘),(4,‘超哥‘);

/*Table structure for table `teacher_student` */

DROP TABLE IF EXISTS `teacher_student`;

CREATE TABLE `teacher_student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `tid` int(11) NOT NULL,
  `sid` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

/*Data for the table `teacher_student` */

insert  into `teacher_student`(`id`,`tid`,`sid`) values (1,1,1),(2,1,3),(3,2,1),(4,4,1);

/*!40101 SET [email protected]_SQL_MODE */;
/*!40014 SET [email protected]_FOREIGN_KEY_CHECKS */;
/*!40014 SET [email protected]_UNIQUE_CHECKS */;
/*!40111 SET [email protected]_SQL_NOTES */;

数据库sql脚本

  一对多,多对一用的是同样的两张表,实体类就发一次

  1.一对多(单条多条操作一块发出来,对应上看即可)

    实体类

//第一个实体类
package cn.dawn.demo03.entity;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Dawn on 2018/2/26.
 */
public class Dept {
    private Integer deptNo;
    private String deptName;
    private List<Emp> emps=new ArrayList<Emp>();

    public Integer getDeptNo() {
        return deptNo;
    }

    public void setDeptNo(Integer deptNo) {
        this.deptNo = deptNo;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public List<Emp> getEmps() {
        return emps;
    }

    public void setEmps(List<Emp> emps) {
        this.emps = emps;
    }
}
//第二个实体类
package cn.dawn.demo03.entity;

/**
 * Created by Dawn on 2018/2/26.
 */
public class Emp {
    private Integer empNo;
    private String empName;
    private Integer deptNo;
    private Dept dept;

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public Integer getEmpNo() {
        return empNo;
    }

    public void setEmpNo(Integer empNo) {
        this.empNo = empNo;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public Integer getDeptNo() {
        return deptNo;
    }

    public void setDeptNo(Integer deptNo) {
        this.deptNo = deptNo;
    }
}

    接口中的方法

    /*一对多单挑sql*/
    public Dept findDeptnoALLEmps(Integer deptNo);
    /*一对多多条sql*/
    public Dept findDeptnoALLEmpsMoreSql(Integer deptNo);

    接口同名的xml文件中

<!--一对多单条sql-->
    <resultMap id="DeptMapper" type="Dept">
        <id column="deptNo" property="deptNo"></id>
        <result column="deptName" property="deptName"></result>
        <collection property="emps" ofType="Emp">
            <id column="empNo" property="empNo"></id>
            <result column="empName" property="empName"></result>
        </collection>
    </resultMap>
    <!--一对多多条sql-->
    <resultMap id="DeptMoreSqlMapper" type="Dept">
        <id column="deptNo" property="deptNo"></id>
        <result column="deptName" property="deptName"></result>
        <collection property="emps" ofType="Emp" select="findDeptnoALLEmpsMoreSqlEmps" column="deptNo">
            <id column="empNo" property="empNo"></id>
            <result column="empName" property="empName"></result>
        </collection>
    </resultMap>
    <!--一对多单条sql-->
    <select id="findDeptnoALLEmps" resultMap="DeptMapper">
        SELECT d.deptNo,empNo,deptName,empName FROM dept d,emp e WHERE d.deptNo=e.DeptNo AND d.deptNo=#{deptNo}
    </select>
    <!--一对多多条sql-->
    <select id="findDeptnoALLEmpsMoreSql" resultMap="DeptMoreSqlMapper">
        SELECT deptNo,deptName FROM dept WHERE deptNo=#{deptNo}
    </select>
    <select id="findDeptnoALLEmpsMoreSqlEmps" resultType="Emp">
        SELECT * FROM emp where deptNo=#{deptNo}
    </select>

    测试方法

    /*一对多多条sql*/
    @Test
    public void t2OnePkMoreMoreSQL(){
        SqlSession session= MyBatisUtils.getSession();

        IDeptDAO mapper = session.getMapper(IDeptDAO.class);
        Dept depts = mapper.findDeptnoALLEmpsMoreSql(1);
        System.out.println(depts.getDeptName()+"================"+depts.getDeptNo());
        for (Emp item:depts.getEmps()) {
            System.out.println(item.getEmpName());
        }

        session.close();

    }

    /*一对多单条sql*/
    @Test
    public void t1OnePkMoreOneSQL(){
        SqlSession session= MyBatisUtils.getSession();

        IDeptDAO mapper = session.getMapper(IDeptDAO.class);
        Dept depts = mapper.findDeptnoALLEmps(1);
        System.out.println(depts.getDeptName()+"================"+depts.getDeptNo());
        for (Emp item:depts.getEmps()) {
            System.out.println(item.getEmpName());
        }

        session.close();

    }

  2.多对一

    接口中的方法

    /*多对一单挑sql*/
    public Emp findempnoALLDept(Integer empNo);
    /*多对一多条sql*/
    public Emp findempnoALLDeptMoreSQL(Integer empNo);

    同名xml中的Mapper中的内容

    <!--多对一单条sql-->
    <resultMap id="EmpMapper" type="Emp">
        <id column="empNo" property="empNo"></id>
        <result column="empName" property="empName"></result>
        <association property="dept" javaType="Dept">
            <result column="deptName" property="deptName"></result>

        </association>
    </resultMap>
    <!--多对一多条sql-->
    <resultMap id="EmpMapperMulti" type="Emp">
        <id column="empNo" property="empNo"></id>
        <result column="empName" property="empName"></result>
        <association property="dept" javaType="Dept" column="deptNo" select="EmpMapperMultiMore">

        </association>
    </resultMap>
    <!--多对一单条sql-->
    <select id="findempnoALLDept" resultMap="EmpMapper">
        SELECT * FROM dept d,emp e WHERE d.deptNo=e.DeptNo AND empNo=#{empNo}
    </select>
    <!--多对一多条sql-->
    <select id="findempnoALLDeptMoreSQL" resultMap="EmpMapperMulti">
        SELECT * FROM emp e WHERE empNo=#{empNo}
    </select>
    <select id="EmpMapperMultiMore" resultType="Dept">
        SELECT * FROM dept WHERE deptNo=#{deptNo}
    </select>

    测试类中的方法

    /*多对一多条sql*/
    @Test
    public void t4MorePkOneMoreSQL(){
        SqlSession session= MyBatisUtils.getSession();

        IEmpDAO mapper = session.getMapper(IEmpDAO.class);
        Emp emp = mapper.findempnoALLDeptMoreSQL(1);
        System.out.println("员工姓名==================="+emp.getEmpName());
        System.out.println("员工部门名称==================="+emp.getDept().getDeptName());

        session.close();

    }

    /*多对一单条sql*/
    @Test
    public void t3MorePkOneOneSQL(){
        SqlSession session= MyBatisUtils.getSession();

        IEmpDAO mapper = session.getMapper(IEmpDAO.class);
        Emp emp = mapper.findempnoALLDept(1);
        System.out.println("员工姓名==================="+emp.getEmpName());
//        System.out.println("员工部门名称==================="+emp.getDept().getDeptName());

        session.close();

    }

  一对多和多对一,他们一个是用ofType,一个是javaType

  3.多对多

    简单解释一下,学生和老师,一个学生可以有多个老师,一个老师可以教多个学生, 怎么表示映射关系,提出了中间表,

    我简单把三张表的脚本再拎出来,看一下,哦,原来是这样

create table Teacher
(
  tid int primary key not null auto_increment,
  tname varchar(32) not null
);

create table Student
(
  sid int primary key not null auto_increment,
  sname varchar(32) not null
);

create table Teacher_Student
(
  id int primary key not null auto_increment,
  tid int not null,
  sid int not null
);

    中间表Teacher_Student有一列流水号主键ID,老师id,学生id,这样一对应,就可以解释清除什么是多对多

    说一下实体类

//第一个学生类
package cn.dawn.demo03.entity;

/**
 * Created by Dawn on 2018/2/26.
 */
public class Student {
    private Integer sid;
    private String sname;

    public Integer getSid() {
        return sid;
    }

    public void setSid(Integer sid) {
        this.sid = sid;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }
}
//第二个老师类
package cn.dawn.demo03.entity;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Dawn on 2018/2/26.
 */
public class Teacher {
    private Integer tid;
    private String tname;
    //植入学生集合
    private List<Student> stus=new ArrayList<Student>();

    public Integer getTid() {
        return tid;
    }

    public void setTid(Integer tid) {
        this.tid = tid;
    }

    public String getTname() {
        return tname;
    }

    public void setTname(String tname) {
        this.tname = tname;
    }

    public List<Student> getStus() {
        return stus;
    }

    public void setStus(List<Student> stus) {
        this.stus = stus;
    }
}

    下来看接口中的方法,我写的是一个根据传进去的老师ID查看该老师教的所有学生的方法

    /*多对多*/
    /*根据老师id查询他的全部学生*/
    public Teacher findAllStudentsByTid(Integer tid);

    接口同名的xml小配置中的mapper内

    <!--多对多-->
    <resultMap id="TeacherMapper" type="Teacher">
        <id property="tid" column="tid"></id>
        <result column="tname" property="tname"></result>
        <collection property="stus" ofType="Student">
            <id property="sid" column="sid"></id>
            <result column="sname" property="sname"></result>
        </collection>
    </resultMap>
    <!--多对多-->
    <select id="findAllStudentsByTid" resultMap="TeacherMapper">
        SELECT * FROM teacher t,student s,teacher_student ts WHERE t.tid=ts.tid AND s.sid=ts.sid AND t.tid=#{tid}
    </select>

    测试方法

    /*多对多*/
    @Test
    public void t5MorePkMore(){
        SqlSession session= MyBatisUtils.getSession();

        ITeacherDAO mapper = session.getMapper(ITeacherDAO.class);
        Teacher teacher = mapper.findAllStudentsByTid(1);
        System.out.println(teacher.getTname());
        for (Student item:teacher.getStus()) {
            System.out.println(item.getSname());
        }

        session.close();

    }

  4.自关联,自关联是什么啊?就是自己里面有自己的集合,打个比方,衣服---》羽绒服----》男款羽绒服,常见的分类对吧,他们都算作分类,但是还有包含关系,就用到了自关联

    它的思想很棒,笔者第一次见到数据表的时候懵了,但是看到实体类的时候,豁然开朗,哦,原来是这样,我明白了,然后就知道怎么处理了

    (当然,那会是没接触框架的时候,框架还需要更深一点的套路)

    

      由于这儿第一次接触有点难理解,我把表的截图放上来

    

    他的pid为0的时候代表的他的父分类没有,他就是一级分类,他的pid(父id)对应的是别的cid的时候,表示他是此cid的子分类,很拗口,看了实体类就懂了

      实体类

package cn.dawn.demo03.entity;

import java.util.Set;

/**
 * Created by Dawn on 2018/2/26.
 */
public class Category {
    private Integer cid;
    private String cname;
    private Set<Category> cates;

    @Override
    public String toString() {
        return "Category{" +
                "cid=" + cid +
                ", cname=‘" + cname + ‘\‘‘ +
                ", cates=" + cates +
                ‘}‘;
    }

    public Integer getCid() {
        return cid;
    }

    public void setCid(Integer cid) {
        this.cid = cid;
    }

    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }

    public Set<Category> getCates() {
        return cates;
    }

    public void setCates(Set<Category> cates) {
        this.cates = cates;
    }
}

    这儿重写了toString方法,方便展示所有数据

    接口中的方法为

    /*自关联*/
    /*根据父id查全部子分类*/
    public List<Category> findAllCategorySetBypid(Integer pid);

    接口同名的xml小配置中的mapper中的节点

    <!--自关联-->
    <resultMap id="CategoryMapper" type="Category">
        <id column="cid" property="cid"></id>
        <result property="cname" column="cname"></result>
        <collection property="cates" column="cid" ofType="Category" select="findAllCategorySetBypid"></collection>
    </resultMap>
    <!--多对多-->
    <select id="findAllCategorySetBypid" resultMap="CategoryMapper">
        SELECT * FROM category WHERE pid=#{pid}
    </select>

    测试方法

    /*自关联*/
    @Test
    public void t6selfPk(){
        SqlSession session= MyBatisUtils.getSession();

        ICategoryDAO mapper = session.getMapper(ICategoryDAO.class);
        List<Category> lists = mapper.findAllCategorySetBypid(0);
        System.out.println(lists);

        session.close();

    }

  这里看完之后,就有我说的自关联和多对多都与一对多有点相似的味道

本章完

原文地址:https://www.cnblogs.com/DawnCHENXI/p/8474742.html

时间: 2024-11-09 00:14:47

SSM-MyBatis-15:Mybatis中关联查询(多表操作)的相关文章

THINKPHP 中关联查询(多表查询)

THINKPHP 中关联查询(多表查询)可以使用 table() 方法或和join方法,请看示例: 1.Table方法:定义要操作的数据表名称,可以动态改变当前操作的数据表名称,需要写数据表的全名,包含前缀,可以使用别名,例如: $Model->Table('think_user user') ->where('status>1') ->select(); $Model->table('think_blog blog,think_type type')->where('

MyBatis:学习笔记(3)——关联查询

MyBatis:学习笔记(3)--关联查询 关联查询 理解联结 SQL最强大的功能之一在于我们可以在数据查询的执行中可以使用联结,来将多个表中的数据作为整体进行筛选. 模拟一个简单的在线商品购物系统,如果我们将用户信息和订单信息都保存在user表中,这样就不存在联结关系,因为我们仅仅操作一张表就好. 但是这是非常不明智的选择,举例来说,一个用户可以拥有多个订单,如果保存在一个表中,势必会导致用户信息的多次出现,因为每个订单绑定的用户信息都是相同的. 所以我们尽量要将不同的信息存储与不同的表中,但

cakephp 中连接查询多表 或group by

$options = array( 'conditions' => $conditions, 'fields'=>array('Category.*','COUNT(`Entity`.`id`) as `entity_count`'), 'joins' => array('LEFT JOIN `entities` AS Entity ON `Entity`.`category_id` = `Category`.`id`'), 'group' => '`Category`.`id`'

mybatis collection 一对多关联查询,单边分页的问题总结!

若想直接通过sql实现多级关联查询表结构得有2 个必不可少的字段:id ,parentId,levelId id:主键id, parentId:父id levelId:表示第几级(表本身关联查询的时候需要用到,不然会有重复数据) 利用mybatis collection 实现一对多关联查询 Dto:(一级) public class ProvinceInfoDTO implements Serializable { private String id; private String name;

mybatis映射文件select_resultMap_关联查询_collection定义关联集合

知识点:查询一个实体类,并查出这个类下面的集合 Employee.java实体类 package com.hand.mybatis.bean;public class Employee {    private Integer eId;    private String eName;    private Integer gender;    private String email;    private Department dept;        public Employee() {

Mongoose中关联查询populate的使用

MongoDB中没有join的特性,因此无法使用join进行表的连接和关联查询,在Mongoose中封装了populate方法,在定义一个 Schema 的时候可以指定了其中的字段(属性)是另一个Schema的引用,在查询文档时就可以使用 populate 方法通过引用 Schema 和 id 找到关联的另一个文档或文档的指定字段值.下面是一个简单的栗子: [场景]: 通过学生ID找到学生所在的班级,对应集合: 学生students. 班级clazzs 1 var mongoose = requ

yii2中关联查询

yii2 ActiveRecord多表关联以及多表关联搜索的实现 一个老生常谈的问题.最近通过群里的反馈,觉得很多人还是没有去理解这个问题.今天把这个问题讲明白了,看看yii2 ActiveRecord是怎么个多表关联以及如何去优化这个关联. 场景需求: 假设我们有一张用户表user和一张用户渠道表auth,两张数据表通过user.id和auth.uid进行一对一关联.现需要在user列表展示auth表的来源渠道source,且该渠道可搜索. 首先我们先通过gii生成user和auth系列相关的

oracle中关联查询、分组查询

高级查询 1.关联查询作用:可以跨越多表查询 --查询出员工的名字和他所在部门的的名字//古老的写法select first_name,name from s_emp,s_dept where s_emp.dept_id = s_dept.id;//现在的写法select e.first_name,s.name from s_emp e join s_dept s on e.dept_id = s.id;语法:select 列,列,列 from 表1 join 表2on 表1外键=表2主键 案例

左关联查询多表

第一次使用左关联进行多表查询,从懵逼到大致i理解,记录以提醒自己. 三张表. sec_user 表 sec_loginUser表 sec_role表 需求:将三张表关联查询,判断登录者,loginUser 表中数据对应的user,的所拥有的角色role,以便后续使用 shiro进行RBAC控制 sql如下: 运行结果如下: