Mybatis【一对多、多对1、多对多】知识要点

Mybatis【多表链接】

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

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

一)内链接(等值链接):查询客户姓名,订单编号,订单价格
    ---------------------------------------------------
    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

一对一

需求:android

  • 学生和身份证

这里写图片描述

设计表:

--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;
	}
}

复制代码

映射文件

因为咱们有两个实体,所以咱们会有两个映射文件sql

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映射文件apache

<?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语句session

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

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

相关文章
相关标签/搜索