资讯专栏INFORMATION COLUMN

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

JerryWangSAP / 2020人阅读

摘要:我来看一下查询结果我们的实体与映射表中,实体是没有关联其他的字段的,仅仅是写出了该实体的自带的属性。

Mybatis【多表连接】

我们在学习Hibernate的时候,如果表涉及到两张的话,那么我们是在映射文件中使用..等标签将其的映射属性关联起来的...那么在我们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这样全自动化的,因此我们是没有..等标签的,我们还是使用手写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映射文件





    
    
        
        
    

Card映射文件






    
    
        
        
        
    

DAO层

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

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

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


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

我来看一下查询结果:

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

    
        
        
    

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

    
        
        

        
        
    

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

    
        
        

        
        
    

    

查询编号为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 studentList = new ArrayList();//关联属性
    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 getStudentList() {
        return studentList;
    }
    public void setStudentList(List 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语句



    
    
        
        
    


    

    
    









    
    
        
        
    


DAO
public List 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 = 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 studentList = new ArrayList();//关联属性
    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 getStudentList() {
        return studentList;
    }
    public void setStudentList(List 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 courseList = new ArrayList();//关联属性
    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 getCourseList() {
        return courseList;
    }
    public void setCourseList(List courseList) {
        this.courseList = courseList;
    }
}
映射文件




    
    
        
        
        
    
    
    
    
    
    







    
    
        
        
        

    
    
    



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 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 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 courseList = dao.findAllByName("哈哈");
        System.out.print("哈哈选学了" + courseList.size()+"个课程,分别是:");
        for(Course c : courseList){
            System.out.print(c.getName()+" ");
        }
        System.out.println("
-----------------------------------------------------");
        List studentList = dao.findAllByCourseName("android");
        System.out.println("选修了android课程的学生有"+studentList.size()+"个,分别是:");
        for(Student s : studentList){
            System.out.print(s.getName()+" ");
        }
    }
}

总结

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

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/68777.html

相关文章

  • 通过项目逐步深入了解Mybatis<三>

    摘要:场合常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用将每一条记录映射到中,在前端页面遍历中是即可。作用将关联查询信息映射到一个对象中。 相关阅读: 1、通过项目逐步深入了解Mybatis 2、 通过项目逐步深入了解Mybatis 本项目所有代码及文档都托管在 Github地址:https://github.com/zhisheng17/myb...

    khlbat 评论0 收藏0
  • Yii2中hasOne、hasMany以及关联查询的用法

    摘要:前言是特有的用于多表关联查询的函数,平时在使用多表关联查询的时候建议使用它们。需求分析使用一条查询语句就能把列表的数据全部展现出来,列表包含一对一,一对多,以及多对多的关系。不能破坏自有的表头排序功能,以及中的存值。相关资料中多表关联查询 前言 hasOne、hasMany是Yii2特有的用于多表关联查询的函数,平时在使用多表关联查询的时候建议使用它们。为什么?因为这种方式关联查询出来...

    qc1iu 评论0 收藏0
  • Yii2中hasOne、hasMany以及关联查询的用法

    摘要:前言是特有的用于多表关联查询的函数,平时在使用多表关联查询的时候建议使用它们。需求分析使用一条查询语句就能把列表的数据全部展现出来,列表包含一对一,一对多,以及多对多的关系。不能破坏自有的表头排序功能,以及中的存值。相关资料中多表关联查询 前言 hasOne、hasMany是Yii2特有的用于多表关联查询的函数,平时在使用多表关联查询的时候建议使用它们。为什么?因为这种方式关联查询出来...

    lmxdawn 评论0 收藏0
  • Yii2中hasOne、hasMany以及关联查询的用法

    摘要:前言是特有的用于多表关联查询的函数,平时在使用多表关联查询的时候建议使用它们。需求分析使用一条查询语句就能把列表的数据全部展现出来,列表包含一对一,一对多,以及多对多的关系。不能破坏自有的表头排序功能,以及中的存值。相关资料中多表关联查询 前言 hasOne、hasMany是Yii2特有的用于多表关联查询的函数,平时在使用多表关联查询的时候建议使用它们。为什么?因为这种方式关联查询出来...

    BDEEFE 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<