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

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

  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. iOS监听模式系列之iOS开发证书、秘钥

    补充--iOS开发证书.秘钥 iOS开发过程中如果需要进行真机调试.发布需要注册申请很多证书,对于初学者往往迷惑不解,再加上今天的文章中会牵扯到一些特殊配置,这里就简单的对iOS开发的常用证书和秘钥等 ...

  2. zookeeper 应用开发

    由于zookeeper的client只有zookeeper一个对象,使用也比较简单,所以就不许要文字说明了,在代码中注释下就ok 了. 1.测试用的main方法 package ClientExamp ...

  3. C语言高级应用---操作linux下V4L2摄像头应用程序

    我们都知道,想要驱动linux下的摄像头,其实很简单,照着V4L2的手册一步步来写,很快就可以写出来,但是在写之前我们要注意改变系统的一些配置,使系统支持framebuffer,在dev下产生fb0这 ...

  4. SDWebimage的原理和使用机制

    对于ASIHttp请求和AFNetworking请求都有关于图片缓存机制的使用,但是相对于专注运用在图片使用的SDWebimage来说,又有不一样的使用效果,最主要的体现在缓存数据的转换. SDWeb ...

  5. ubuntu 输入用户名密码又回到登陆界面

    问题描述: 输入正确的用户名密码,登陆后又返回登陆界面,重复出现. 问题解决: 环境变量出错,重新配置环境变量. 1.进入命令行模式Ctrl+Alt+F*,然后输入用户名密码: 2.登进去之后,以管理 ...

  6. How to configure ODBC DSN in Client to access remote DB2 for Windows

      How to configure ODBC DSN in Client to access remote DB2 for Windows MA Gen feng (Guangdong Unito ...

  7. vicoapp使用备忘

    vico是一个模式编辑器,意味着没用过vi之类编辑器的童鞋用起来肯定觉得很不习惯. 模式切换 i:切至编辑模式,在光标前插入 a:切至编辑模式,在在光标后插入 I:类似于i,不过在行首插入 esc键: ...

  8. OOP的基本原则

    OOP的基本原则 点击打开链接

  9. Day5_协程函数_面向过程

    def func(count): while True: yield count count +=1 #这是一个生成器,需要利用next()来执行. func(10) #yield: #1.把函数的执 ...

  10. 最全的 Swift 4 新特性解析

    转自: http://www.jianshu.com/p/f35514ae9c1a WWDC 2017 带来了很多惊喜.Swift 4 也伴随着 Xcode 9 测试版来到了我们的面前,很多强大的新特 ...