Mybatis【多表连接】

我们在学习Hibernate的时候,如果表涉及到两张的话,那么我们是在映射文件中使用<set>..<many-to-one>等标签将其的映射属性关联起来的...那么在我们Mybatis中又怎么做呢???

先来回顾一下我们SQL99的语法:


一)内连接(等值连接):查询客户姓名,订单编号,订单价格
---------------------------------------------------
select c.name,o.isbn,o.price
from customers c inner join orders o
where c.id = o.customers_id;
---------------------------------------------------
select c.name,o.isbn,o.price
from customers c join orders o
where c.id = o.customers_id;
---------------------------------------------------
select c.name,o.isbn,o.price
from customers c,orders o
where c.id = o.customers_id;
---------------------------------------------------
select c.name,o.isbn,o.price
from customers c join orders o
on c.id = o.customers_id;
---------------------------------------------------
注意:内连接(等值连接)只能查询出多张表中,连接字段相同的记录 二)外连接:按客户分组,查询每个客户的姓名和订单数
---------------------------------------------------
左外连接:
select c.name,count(o.isbn)
from customers c left outer join orders o
on c.id = o.customers_id
group by c.name;
---------------------------------------------------
右外连接:
select c.name,count(o.isbn)
from orders o right outer join customers c
on c.id = o.customers_id
group by c.name;
---------------------------------------------------
注意:外连接既能查询出多张表中,连接字段相同的记录;又能根据一方,将另一方不符合相同记录强行查询出来 三)自连接:求出AA的老板是EE
---------------------------------------------------
内自连接:
select users.ename,boss.ename
from emps users inner join emps boss
on users.mgr = boss.empno;
---------------------------------------------------
外自连接:
select users.ename,boss.ename
from emps users left outer join emps boss
on users.mgr = boss.empno;
---------------------------------------------------
注意:自连接是将一张表,通过别名的方式,看作多张表后,再进行连接。
这时的连接即可以采用内连接,又可以采用外连接

由于我们Mybatis中并没有像Hibernate这样全自动化的,因此我们是没有<set>..<many-to-one>等标签的,我们还是使用手写SQL语句来使我们的关联属性连接起来...

一对一

需求:

  • 学生和身份证

设计表:



--mysql

create table cards(
cid int(5) primary key,
cnum varchar(10)
); create table students(
sid int(5) primary key,
sname varchar(10),
scid int(5),
constraint scid_fk foreign key(scid) references cards(cid)
); insert into cards(cid,cnum) values(1,'111');
insert into students(sid,sname,scid) values(1,'哈哈',1); select * from cards;
select * from students;

实体

/**
* 身份证(单方)
* @author AdminTC
*/
public class Card {
private Integer id;
private String num;
public Card(){}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNum() {
return num;
}
public void setNum(String num) {
this.num = num;
}
}

/**
* 学生(单方)
* @author AdminTC
*/
public class Student {
private Integer id;
private String name;
private Card card;//关联属性
public Student(){}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Card getCard() {
return card;
}
public void setCard(Card card) {
this.card = card;
}
}

映射文件

由于我们有两个实体,因此我们会有两个映射文件

Student映射文件


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="studentNamespace"> <resultMap type="zhongfucheng2.Student" id="studentMap">
<id property="id" column="sid"/>
<result property="name" column="sname"/>
</resultMap>
</mapper>

Card映射文件



<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cardNamespace"> <resultMap type="zhongfucheng2.Card" id="cardMap">
<id property="id" column="cid"/>
<result property="num" column="cnum"/>
</resultMap> </mapper>

DAO层

现在我想根据学生的编号查询学生的信息和身份证信息

由于该查询着重是查询学生的信息,于是我们在学生的映射文件中写SQL语句

按照需求,我们写出来的SQL语句是这样子的。



select * from zhongfucheng.students s,zhongfucheng.cards c where c.cid = s.scid and sid=1;

我来看一下查询结果:

我们的实体与映射表中,Student实体是没有关联其他的字段的,仅仅是写出了该实体的自带的属性


<resultMap type="zhongfucheng2.Student" id="studentMap">
<id property="id" column="sid"/>
<result property="name" column="sname"/>
</resultMap>

明显地,我们Student是不能封装返回的结果,因此我们需要将关联属性进行关联起来!


<resultMap type="zhongfucheng2.Student" id="studentMap">
<id property="id" column="sid"/>
<result property="name" column="sname"/> <!--
property写的是在Student实体中写关联字段的属性变量名称
resultMap写的是映射文件中的命名空间.id
-->
<association property="card" resultMap="cardNamespace.cardMap"/>
</resultMap>

我们关联了以后,Student实体就能够封装返回的结果了


<resultMap type="zhongfucheng2.Student" id="studentMap">
<id property="id" column="sid"/>
<result property="name" column="sname"/> <!--
property写的是在Student实体中写关联字段的属性变量名称
resultMap写的是映射文件中的命名空间.id
-->
<association property="card" resultMap="cardNamespace.cardMap"/>
</resultMap> <select id="findById" parameterType="int" resultMap="studentMap">
select * from zhongfucheng.students s,zhongfucheng.cards c where c.cid = s.scid and sid=#{id};
</select>

查询编号为1的学生信息【包括身份证编号】



    public Student findById(int id) throws Exception {
//得到连接对象
SqlSession sqlSession = MybatisUtil.getSqlSession();
try{ return sqlSession.selectOne("studentNamespace.findById", id); /* sqlSession.commit();*/
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
throw e;
}finally{
MybatisUtil.closeSqlSession();
}
} public static void main(String[] args) throws Exception {
StudentDao studentDao = new StudentDao();
Student student = studentDao.findById(1); System.out.println(student.getId() + "----" + student.getName() + "----" + student.getCard().getNum()); }


一对多

需求:

  • 一个班级有多个学生,查询java学科有哪些学生信息

设计数据库表



create table grades(
gid int(5) primary key,
gname varchar(10)
); create table students(
sid int(5) primary key,
sname varchar(10),
sgid int(5),
constraint sgid_fk foreign key(sgid) references grades(gid)
); insert into grades(gid,gname) values(1,'java'); insert into students(sid,sname,sgid) values(1,'哈哈',1);
insert into students(sid,sname,sgid) values(2,'呵呵',1); select * from grades;
select * from students;

实体


package zhongfucheng2; import java.util.ArrayList;
import java.util.List; /**
* 学科(单方)
* @author AdminTC
*/
public class Grade {
private Integer id;
private String name;
private List<Student> studentList = new ArrayList<Student>();//关联属性
public Grade(){}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Student> getStudentList() {
return studentList;
}
public void setStudentList(List<Student> studentList) {
this.studentList = studentList;
}
}

package zhongfucheng2; /**
* 学生(多方)
* @author AdminTC
*/
public class Student {
private Integer id;
private String name;
private Grade grade;//关联属性
public Student(){}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Grade getGrade() {
return grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
}

映射文件SQL语句



<mapper namespace="studentNamespace">

	<resultMap type="zhongfucheng2.Student" id="studentMap">
<id property="id" column="sid"/>
<result property="name" column="sname"/>
</resultMap> <!--查询选修的java学科有多少位学生--> <!--由于我们只要查询学生的名字,而我们的实体studentMap可以封装学生的名字,那么我们返回studentMap即可,并不需要再关联到学科表-->
<select id="findByGrade" parameterType="string" resultMap="studentMap"> select s.sname,s.sid from zhongfucheng.students s,zhongfucheng.grades g WHERE s.sgid=g.gid and g.gname=#{name}; </select> </mapper> <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="gradeNamespace"> <resultMap type="zhongfucheng2.Grade" id="gradeMap">
<id property="id" column="gid"/>
<result property="name" column="gname"/>
</resultMap>
</mapper>

DAO


public List<Student> findByGrade(String grade) throws Exception {
//得到连接对象
SqlSession sqlSession = MybatisUtil.getSqlSession();
try{ return sqlSession.selectList("studentNamespace.findByGrade", grade);
/* sqlSession.commit();*/
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
throw e;
}finally{
MybatisUtil.closeSqlSession();
}
} public static void main(String[] args) throws Exception {
StudentDao studentDao = new StudentDao();
List<Student> student = studentDao.findByGrade("java"); for (Student student1 : student) {
System.out.println(student1.getName());
}
}

多对多

需求:

  • 学生和课程

数据库表


create table students(
sid int(5) primary key,
sname varchar(10)
); create table courses(
cid int(5) primary key,
cname varchar(10)
); create table middles(
msid int(5),
mcid int(5),
primary key(msid,mcid)
); insert into students(sid,sname) values(1,'哈哈');
insert into students(sid,sname) values(2,'呵呵'); insert into courses(cid,cname) values(1,'java');
insert into courses(cid,cname) values(2,'android'); insert into middles(msid,mcid) values(1,1);
insert into middles(msid,mcid) values(1,2);
insert into middles(msid,mcid) values(2,1);
insert into middles(msid,mcid) values(2,2); select * from students;
select * from courses;
select * from middles;

实体

package cn.itcast.javaee.mybatis.many2many;

import java.util.ArrayList;
import java.util.List; /**
* 课程(多方)
* @author AdminTC
*/
public class Course {
private Integer id;
private String name;
private List<Student> studentList = new ArrayList<Student>();//关联属性
public Course(){}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Student> getStudentList() {
return studentList;
}
public void setStudentList(List<Student> studentList) {
this.studentList = studentList;
}
}

package cn.itcast.javaee.mybatis.many2many; import java.util.ArrayList;
import java.util.List; /**
* 学生(多方)
* @author AdminTC
*/
public class Student {
private Integer id;
private String name;
private List<Course> courseList = new ArrayList<Course>();//关联属性
public Student(){}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Course> getCourseList() {
return courseList;
}
public void setCourseList(List<Course> courseList) {
this.courseList = courseList;
}
}

映射文件


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="courseNamespace"> <resultMap type="cn.itcast.javaee.mybatis.many2many.Course" id="courseMap">
<id property="id" column="cid"/>
<result property="name" column="cname"/>
</resultMap> <!-- 查询哈哈选学了哪些课程 -->
<select id="findAllByName" parameterType="string" resultMap="courseMap">
select c.cid,c.cname
from students s inner join middles m
on s.sid = m.msid
inner join courses c
on m.mcid = c.cid
and s.sname = #{name}
</select> </mapper>

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="studentNamespace"> <resultMap type="cn.itcast.javaee.mybatis.many2many.Student" id="studentMap">
<id property="id" column="sid"/>
<result property="name" column="sname"/>
</resultMap> <select id="findAllByCourseName" parameterType="string" resultMap="studentMap">
select s.sname
from students s inner join middles m
on s.sid = m.msid
inner join courses c
on m.mcid = c.cid
and c.cname = #{name}
</select> </mapper>

DAO



package cn.itcast.javaee.mybatis.many2many;

import java.util.List;
import org.apache.ibatis.session.SqlSession;
import cn.itcast.javaee.mybatis.util.MybatisUtil; /**
* 持久层
* @author AdminTC
*/
public class StudentCourseDao {
/**
* 查询哈哈选学了哪些课程
* @param name 表示学生的姓名
*/
public List<Course> findAllByName(String name) throws Exception{
SqlSession sqlSession = null;
try{
sqlSession = MybatisUtil.getSqlSession();
return sqlSession.selectList("courseNamespace.findAllByName",name);
}catch(Exception e){
e.printStackTrace();
throw e;
}finally{
MybatisUtil.closeSqlSession();
}
}
/**
* 查询java课程有哪些学生选修
* @param name 表示学生的课程
*/
public List<Student> findAllByCourseName(String name) throws Exception{
SqlSession sqlSession = null;
try{
sqlSession = MybatisUtil.getSqlSession();
return sqlSession.selectList("studentNamespace.findAllByCourseName",name);
}catch(Exception e){
e.printStackTrace();
throw e;
}finally{
MybatisUtil.closeSqlSession();
}
} public static void main(String[] args) throws Exception{
StudentCourseDao dao = new StudentCourseDao();
List<Course> courseList = dao.findAllByName("哈哈");
System.out.print("哈哈选学了" + courseList.size()+"个课程,分别是:");
for(Course c : courseList){
System.out.print(c.getName()+" ");
}
System.out.println("\n-----------------------------------------------------");
List<Student> studentList = dao.findAllByCourseName("android");
System.out.println("选修了android课程的学生有"+studentList.size()+"个,分别是:");
for(Student s : studentList){
System.out.print(s.getName()+" ");
}
}
}

总结

对于Mybatis的多表连接就非常简单了,由于SQL语句全是由我们自己写,如果我们返回的数据类型在当前的实体中是不够封装的话,那么我们只要再关联对应的映射属性就行了


如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y

Mybatis【一对多、多对一、多对多】知识要点的更多相关文章

  1. mybatis 一对多,(多对一,一对一

    多对一,和一对一是同一种写法,每种写法又分在数据库关联和在mybatis关联 1,多对一,一对一数据库关联 2,多对一,一对一mybatis关联 3,一对多,数据库关联,注意,Java type改of ...

  2. mybatis 一对多和多对一关联查询

    首先  数据库量表之间字段关系(没有主外键) studentmajor表的id字段对应student表里major字段 两个实体类 package com.model; import java.uti ...

  3. mybatis 一对多的注入 指的是连表查询时候 将不同的查询结果以列表存储对象形式 注入进去 多对一指的是 查询多条结果但都是一样的 只需注入一条

    mybatis 一对多的注入 指的是连表查询时候 将不同的查询结果以列表存储对象形式 注入进去 多对一指的是 查询多条结果但都是一样的 只需注入一条

  4. Java基础-SSM之mybatis一对多和多对一关系映射

    Java基础-SSM之mybatis一对多和多对一关系映射 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.准备测试环境(创建数据库表)  1>.创建customers表: ...

  5. MyBatis一对多和多对多xml配置

    MyBatis一对多和多对多xml配置 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ma ...

  6. mybatis 一对多和多对一 简单案例笔记

    以案例说明(以下案例代码都敲过验证过) 多对一(多个学生对一个老师  即学生集合中都存一个老师对象) Mybatis多对一实现方式1: //定义Student 和 Teacher 实体 @Data p ...

  7. MyBatis加强(1)~myBatis对象关系映射(多对一关系、一对多关系)、延迟/懒加载

    一.myBatis对象关系映射(多对一关系.一对多关系) 1.多对一关系: ---例子:多个员工同属于一个部门. (1)myBatis发送 额外SQL: ■ 案例:员工表通过 dept_id 关联 部 ...

  8. 【Jpa hibernate】一对多@OneToMany,多对一@ManyToOne的使用

    项目中使用实体之间存在一对多@OneToMany,多对一@ManyToOne的映射关系,怎么设置呢? GitHub地址:https://github.com/AngelSXD/myagenorderd ...

  9. Mybatis中使用collection进行多对多双向关联示例(含XML版与注解版)

    Mybatis中使用collection进行多对多双向关联示例(含XML版与注解版) XML版本: 实体类: @Data @NoArgsConstructor public class Course ...

  10. mybatis一对多关联关系映射

    mybatis一对多关联关系映射 一对多关联关系只需要在多的一方引入少的一方的主键作为外键即可.在实体类中就是反过来,在少的一方添加多的一方,声明一个List 属性名 作为少的一方的属性. 用户和订单 ...

随机推荐

  1. spring boot学习资源

    http://blog.csdn.net/u014695188/article/details/52226134 http://www.jianshu.com/p/887c22723e43 Sprin ...

  2. phpstudy如何安装景安ssl证书 window下apache服务器网站https访问

    1. 下载景安免费证书 https://www.zzidc.com/help/helpDetail?id=555 2.文件解压上传至服务器,位置自己决定 3. 调整apache配置 景安原文链接:ht ...

  3. springboot入门_模板

    springboot中已经不推荐使用jsp,而是推荐使用模板,如freemarker,thymeleaf等,本文记录在sprigboot中使用模板. 创建一个maven的springboot工程, f ...

  4. 项目构建工具Maven

  5. Ubuntu14.04上搭建FTP服务器

    Ubuntu上常用的Ftp服务器是vsFTPd.安装前检查下是否已经装好了.用 sudo service vsftpd restart,如果提示重启成功之类的信息,说明此服务器已经安装好了vsFTPd ...

  6. PHP动态编译出现Cannot find autoconf的解决方法

    wget http://ftp.gnu.org/gnu/m4/m4-1.4.9.tar.gz tar -zvxf m4-.tar.gz cd m4-/ ./configure && m ...

  7. 《android开发艺术探索》读书笔记(七)--动画

    接上篇<android开发艺术探索>读书笔记(六)--Drawable No1: 自定义动画:派生一种新动画只需要继承Animation这个抽象类,然后重写它的initialize和app ...

  8. UVA - 1220 Party at Hali-Bula 树的最大独立集

    题意:  给定n个人,存在上下级关系,每个人只有一个上级,求最大独立集.并判断最大独立集是否唯一 思路:d[i][0]表示以i为根的子树中,不选择第i个节点的最大独立集,f[i][0]表示以i为根的子 ...

  9. 第II篇PCI Express体系结构概述

    虽然PCI总线取得了巨大的成功,但是随着处理器主频的不断提高,PCI总线提供的带宽愈发显得捉襟见肘.PCI总线也在不断地进行升级,其位宽和频率从最初的32位/33MHz扩展到64位/66MHz,而PC ...

  10. Flex中的FusionCharts 3D柱形图

    1.3D柱形图源码 <?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:f ...