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

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

  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 @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@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() NOT NULL AUTO_INCREMENT,
`bookName` varchar() DEFAULT NULL,
`bookAuthor` varchar() DEFAULT NULL,
`bookPrice` int() DEFAULT NULL,
PRIMARY KEY (`bookID`)
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8; /*Data for the table `book` */ insert into `book`(`bookID`,`bookName`,`bookAuthor`,`bookPrice`) values (,'程序员的人生','老原教育',),(,'皮的修养','郭彦',),(,'如何成为一代大牛','迟总',),(,'心想事成','孟六',),(,'心想事成','孟六',),(,'心想事成','孟七',),(,'心想事成','孟七',),(,'心想事成','孟七',); /*Table structure for table `category` */ DROP TABLE IF EXISTS `category`; CREATE TABLE `category` (
`cid` int() NOT NULL AUTO_INCREMENT,
`cname` varchar() DEFAULT NULL,
`pid` int() NOT NULL,
PRIMARY KEY (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8; /*Data for the table `category` */ insert into `category`(`cid`,`cname`,`pid`) values (,'图书',),(,'青年图书',),(,'少儿图书',),(,'我爱科学',),(,'服装',),(,'羽绒服',); /*Table structure for table `dept` */ DROP TABLE IF EXISTS `dept`; CREATE TABLE `dept` (
`deptNo` int() NOT NULL AUTO_INCREMENT,
`deptName` varchar() DEFAULT NULL,
PRIMARY KEY (`deptNo`)
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8; /*Data for the table `dept` */ insert into `dept`(`deptNo`,`deptName`) values (,'开发部'); /*Table structure for table `emp` */ DROP TABLE IF EXISTS `emp`; CREATE TABLE `emp` (
`empNo` int() NOT NULL AUTO_INCREMENT,
`empName` varchar() DEFAULT NULL,
`deptNo` int() 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= DEFAULT CHARSET=utf8; /*Data for the table `emp` */ insert into `emp`(`empNo`,`empName`,`deptNo`) values (,'孟六',),(,'孟六',); /*Table structure for table `student` */ DROP TABLE IF EXISTS `student`; CREATE TABLE `student` (
`sid` int() NOT NULL AUTO_INCREMENT,
`sname` varchar() NOT NULL,
PRIMARY KEY (`sid`)
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8; /*Data for the table `student` */ insert into `student`(`sid`,`sname`) values (,'孟六'),(,'王五'),(,'赵七'),(,'郭皮'); /*Table structure for table `teacher` */ DROP TABLE IF EXISTS `teacher`; CREATE TABLE `teacher` (
`tid` int() NOT NULL AUTO_INCREMENT,
`tname` varchar() NOT NULL,
PRIMARY KEY (`tid`)
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8; /*Data for the table `teacher` */ insert into `teacher`(`tid`,`tname`) values (,'迟老师'),(,'原老师'),(,'付老师'),(,'超哥'); /*Table structure for table `teacher_student` */ DROP TABLE IF EXISTS `teacher_student`; CREATE TABLE `teacher_student` (
`id` int() NOT NULL AUTO_INCREMENT,
`tid` int() NOT NULL,
`sid` int() NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8; /*Data for the table `teacher_student` */ insert into `teacher_student`(`id`,`tid`,`sid`) values (,,),(,,),(,,),(,,); /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_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();
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();
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();
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();
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() not null
); create table Student
(
sid int primary key not null auto_increment,
sname varchar() 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();
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();
System.out.println(lists); session.close(); }

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

本章完

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

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

    THINKPHP 中关联查询(多表查询)可以使用 table() 方法或和join方法,请看示例: 1.Table方法:定义要操作的数据表名称,可以动态改变当前操作的数据表名称,需要写数据表的全名,包 ...

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

    MyBatis:学习笔记(3)--关联查询 关联查询 理解联结 SQL最强大的功能之一在于我们可以在数据查询的执行中可以使用联结,来将多个表中的数据作为整体进行筛选. 模拟一个简单的在线商品购物系统, ...

  3. Oracle中如何查询一个表的所有字段名和数据类型

    Oracle中如何查询一个表的所有字段名和数据类型 查询语法 select A.COLUMN_NAME,A.DATA_TYPE from user_tab_columns A where TABLE_ ...

  4. 第69节:Java中数据库的多表操作

    第69节:Java中数据库的多表操作 前言 学习数据库的多表操作,去电商行业做项目吧!!! 达叔,理工男,简书作者&全栈工程师,感性理性兼备的写作者,个人独立开发者,我相信你也可以!阅读他的文 ...

  5. MyBatis:一对多关联查询

    MyBatis从入门到放弃四:一对多关联查询 前言 上篇学习了一对一关联查询,这篇我们学习一对多关联查询.一对多关联查询关键点则依然是配置resultMap,在resultMap中配置collecti ...

  6. MyBatis 实践 -动态SQL/关联查询

    MyBatis 实践 标签: Java与存储 动态SQL 动态SQL提供了对SQL语句的灵活操作,通过表达式进行判断,对SQL进行拼接/组装. if 对查询条件进行判断,如果输入参数不为空才进行查询条 ...

  7. mybatis mapper.xml 写关联查询 运用 resultmap 结果集中 用 association 关联其他表 并且 用 association 的 select 查询值 报错 java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for mybatis.map

    用mybaits 写一个关联查询 查询商品表关联商品规格表,并查询规格表中的数量.价格等,为了sql重用性,利用 association 节点 查询 结果并赋值报错 商品表的mapper文件为Gooo ...

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

    若想直接通过sql实现多级关联查询表结构得有2 个必不可少的字段:id ,parentId,levelId id:主键id, parentId:父id levelId:表示第几级(表本身关联查询的时候 ...

  9. Mybatis学习笔记(七) —— 关联查询

    一.一对多查询 需求:查询所有订单信息,关联查询下单用户信息. 注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询.如果从用户信息出发查询用户下的订单信息则 ...

随机推荐

  1. Cocos2D的OALSimpleAudio预加载音频

    在OALSimpleAudio接口中,没有委托机制和通知机制告诉你什么时候预加载完成.也不需要这样的机制. 如下代码: //Listing 11-1. Preloading a background ...

  2. Linux下的 .o、.a、.so文件

    http://blog.sina.com.cn/s/blog_656681710100qzmy.html 工程里很多函数只是有声明,找不到实现的代码.因为那些实现代码已经编译成库所以看不见,我所看见的 ...

  3. 网站开发进阶(十一)如何将一个jsp页面嵌套在另一个页面中

    如何将一个jsp页面嵌套在另一个页面中 这个在做网页中常要用到,有些通用的内容可集中放在一个页面文件中,其它要用到这些内容的页面只需要包含(引用)这个通用文件即可.这样便于维护,如果有很多网页,当通用 ...

  4. LeetCode之“数学”:Reverse Integer && Reverse Bits

    1. Reverse Integer 题目链接 题目要求: Reverse digits of an integer. Example1: x = 123, return 321 Example2:  ...

  5. MySql常用操作语句(1:启动、连接数据库及用户操作)

    下方将个人常用的MySql操作语句(Win7下)总结如下: 1. 启动与关闭数据库 “管理员”权限, MySql安装目录下bin目录//:  1.1 启动 @>net start mysql   ...

  6. WinCE系统声音定制

    作者:ARM-WinCE 2010的第一篇Blog,介绍一下WinCE系统声音的定制.说白了,就是设置注册表.WinCE系统启动的开机音乐,点击触摸屏以及键盘输入的按键音,还有系统运行过程中的各种声音 ...

  7. C++之多继承

    #include <iostream> using namespace std ; class AA { public: int a ; void Say_hello(void) { co ...

  8. 单片机PWM调制技术

    我们可以看看下图,下图就是一个典型的PWM的波形图. T是一个周期,T1就是高电平所占用的时间,T2就是低电平所占用的时间. 如上图所示T1为脉冲宽度(就是导通时间),周期为T,则输出电压的平均值为U ...

  9. 【作业2.0】HansBug的5-7次OO作业分析与小结,以及一些个人体会

    不知不觉又做了三次作业,容我在本文胡言乱语几句2333. 第五次作业 第五次作业是前面的电梯作业的多线程版本,难度也有了一些提升.(点击就送指导书) 类图 程序的类图结构如下: UML时序图 程序的逻 ...

  10. Nginx常用模块安装命令

    将目录切换至Nginx安装包目录下,使用./configure命令进行安装.一些第三方模块需要先下载过来,指定下解压后的目录即可. ./configure --prefix=/usr/local/ng ...