MyBatis:多表聯合查詢

在這篇文章裏面主要講解如何在mybatis裏面使用一對一、一對多、多表聯合查詢(類似視圖)操作的例子。

  注:閱讀本文前請先大概看一下之前兩篇文章。

  一、表結構

  班級表class,學生表student,班級學生關係表ClassStudent。

  這裏一個學生只會在一個班級裏面,也就是一對一的關係;一個班級有多個學生,也就是一對多的關係。

  結構如下:

CREATE TABLE [dbo].[Class](
    [class_id] [int] NOT NULL,
    [class_name] [varchar](50) NOT NULL,
 CONSTRAINT [PK_Class] PRIMARY KEY CLUSTERED 
(
    [class_id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [dbo].[ClassStudent](
    [class_id] [int] NOT NULL,
    [student_id] [int] NOT NULL
) ON [PRIMARY]

CREATE TABLE [dbo].[Student](
    [s_id] [int] NOT NULL,
    [s_name] [varchar](50) NOT NULL,
 CONSTRAINT [PK_Student] PRIMARY KEY CLUSTERED 
(
    [s_id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

 

    3張表的數據如下:

 

insert into Class values(1,'三(1)班')
insert into Class values(2,'三(2)班')
insert into Class values(3,'三(3)班')
insert into Class values(4,'三(4)班')

insert into Student values(1001,'張三')
insert into Student values(1002,'李四')
insert into Student values(1003,'趙五')
insert into Student values(1004,'王二麻子')

insert into ClassStudent values(1,1001)
insert into ClassStudent values(1,1003)
insert into ClassStudent values(4,1002)
insert into ClassStudent values(3,1004)

 

  

  二、在原項目下新建一個包com.mybatis.sqljoinrelation,在包裏面新建一個sqlMapper.xml的映射文件,在項目的mybatis的配置文件conf.xml中對這個sqlMapper.xml進行註冊,註冊片段如下:

<!-- 註冊映射文件 -->
    <mappers>
        <mapper resource="com/mybatis/sqljoinrelation/sqlMapper.xml" />
    </mappers>

  緊接着在原項目下再新建一個包com.mybatis.bean,在裏面新建實體類

  學生:

 

package com.mybatis.bean;

/**
 * 學生(臨時)
 */
public class StudentTemp {
    private int studentid;
    private String studentname;
    private Class tempClass;
    
    public Class getTempClass() {
        return tempClass;
    }
    public void setTempClass(Class tempClass) {
        this.tempClass = tempClass;
    }
    public int getStudentid() {
        return studentid;
    }
    public void setStudentid(int studentid) {
        this.studentid = studentid;
    }
    public String getStudentname() {
        return studentname;
    }
    public void setStudentname(String studentname) {
        this.studentname = studentname;
    }
    
    @Override
    public String toString() {
        return "StudentTemp [studentid=" + studentid + ", studentname="
                + studentname + ", tempClass=" + tempClass + "]";
    }
    
}

 

  班級:

 

package com.mybatis.bean;

/**
 * 班級
 */
public class Class {
    private int classid;
    private String classname;
    
    public int getClassid() {
        return classid;
    }
    public void setClassid(int classid) {
        this.classid = classid;
    }
    public String getClassname() {
        return classname;
    }
    public void setClassname(String classname) {
        this.classname = classname;
    }
    
    @Override
    public String toString() {
        return "Class [classid=" + classid + ", classname=" + classname + "]";
    }
}

 

  學生班級視圖類:

 

package com.mybatis.bean;

public class studentclass {
    private int s_id;
    private String s_name;
    private int class_id;
    private String class_name;
    public int getS_id() {
        return s_id;
    }
    public void setS_id(int s_id) {
        this.s_id = s_id;
    }
    public String getS_name() {
        return s_name;
    }
    public void setS_name(String s_name) {
        this.s_name = s_name;
    }
    public int getClass_id() {
        return class_id;
    }
    public void setClass_id(int class_id) {
        this.class_id = class_id;
    }
    public String getClass_name() {
        return class_name;
    }
    public void setClass_name(String class_name) {
        this.class_name = class_name;
    }
    @Override
    public String toString() {
        return "studentclass [s_id=" + s_id + ", s_name=" + s_name
                + ", class_id=" + class_id + ", class_name=" + class_name + "]";
    }
    
    
}

 

 

  三、查詢操作

  1、 一對一,查詢學生編號等於1001且他所在班級信息

  2、一對多,查詢班級編號等於1且包含所有學生信息

  3、類似視圖查詢學生編號等於1001且他所在班級信息

  sqlMapper.xml如下:

 

<?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="com.mybatis.sqljoinrelation.sqlMapper">

    <!-- 1、 獲取某學生以及該學生所在班級的信息 -->
    <!-- 可以顯示指出c.class_id,c.class_name,s.s_id,s.s_name列明,
        如果用"*"代替,則mybatis會自動匹配resultMap中提供的列名 -->
    <select id="getStudentAndClass" parameterType="int" resultMap="studentClassMap">
        select c.class_id,c.class_name,s.s_id,s.s_name
        from Class c left join ClassStudent cs
                on c.class_id = cs.class_id
            left join Student s
                on cs.student_id = s.s_id
        where s.s_id = #{id}
    </select>

    <!-- resultMap中的type表示返回什麼類型的對象 -->
    <resultMap type="com.mybatis.bean.StudentTemp" id="studentClassMap">
        <!-- property 表示com.mybatis.bean.StudentTemp中的屬性; column 表示表中的列名 -->
        <id property="studentid" column="s_id" />
        <result property="studentname" column="s_name" />

        <!-- association字面意思關聯,這裏只專門做一對一關聯; property表示是com.mybatis.bean.StudentTemp中的屬性名稱; 
            javaType表示該屬性是什麼類型對象 -->
        <association property="tempClass" javaType="com.mybatis.bean.Class">
            <!-- property 表示com.mybatis.bean.Class中的屬性; column 表示表中的列名 -->
            <id property="classid" column="class_id" />
            <result property="classname" column="class_name" />
        </association>
    </resultMap>

    <!-- 2、獲取某學生以及該學生所在班級的信息,類似視圖實現方式 -->
    <!-- resultType 對應簡單類型,也就是實體中的屬性名稱與數據庫表字段名稱一模一樣;
         resultMap 對應複雜類型,屬性名稱與字段名稱不一樣可以通過resultMap中property,column進行映射 -->
    <select id="getStudentAndClassView" parameterType="int" resultType="com.mybatis.bean.studentclass">
        select c.class_id,c.class_name,s.s_id,s.s_name
        from Class c left join ClassStudent cs
                on c.class_id = cs.class_id
            left join Student s
                on cs.student_id = s.s_id
        where s.s_id = #{id}
    </select>

    <!-- 3、獲取某班級以及班級裏面所有學生的信息 -->
    <select id="getClassStudents" parameterType="int" resultMap="classStudentsMap">
        select * 
        from Class c left join ClassStudent cs
                on c.class_id = cs.class_id
            left join Student s
                on cs.student_id = s.s_id
        where c.class_id = #{id}
    </select>
    <resultMap type="com.mybatis.bean.ClassTemp" id="classStudentsMap">
        <id property="classid" column="class_id"/>
        <result property="classname" column="class_name"/>
        
        <!-- property表示集合類型屬性名稱,ofType表示集合中的對象是什麼類型 -->
        <collection property="students" ofType="com.mybatis.bean.Student">
            <id property="studentid" column="s_id"/>
        <result property="studentname" column="s_name"/>
        </collection>
    </resultMap>
</mapper>

 

  測試代碼如下:

  一對一與類似視圖查詢的代碼在一起,如下:

 

package com.mybatis.sqljoinrelation;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import com.mybatis.util.MybatisUtils;

/**
 * 一對一
 */
public class testonetoone {
    public static void main(String[] args) {
        SqlSessionFactory factory = MybatisUtils.getFactory();
        SqlSession session = null;
        try {
            session = factory.openSession(true);
            
            //1、StudentTemp
            String statement1 = "com.mybatis.sqljoinrelation.sqlMapper.getStudentAndClass";
            System.out.println(session.selectOne(statement1, 1001)); 
            
            //2、用model類型接收數據
            String statement2 = "com.mybatis.sqljoinrelation.sqlMapper.getStudentAndClassView";
            System.out.println(session.selectOne(statement2, 1001)); 
            
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            session.close();
        }
    }
}

  一對多測試代碼如下:

 

package com.mybatis.sqljoinrelation;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import com.mybatis.util.MybatisUtils;

/**
 * 一對多
 */
public class testonetomany {
    public static void main(String[] args) {
        SqlSessionFactory factory = MybatisUtils.getFactory();
        SqlSession session = null;
        try {
            session = factory.openSession(true);
            
            //1、StudentTemp
            String statement = "com.mybatis.sqljoinrelation.sqlMapper.getClassStudents";
            System.out.println(session.selectOne(statement, 1)); 
            
            
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            session.close();
        }
    }
}

 

 

  四、sqlMapper.xml需要說明的問題

  1、一對一:<association property="tempClass" javaType="com.mybatis.bean.Class">

    association字面意思關聯,這裏只專門做一對一關聯; property表示是com.mybatis.bean.StudentTemp中的屬性名稱; javaType表示該屬性是什麼類型對象

    2、類似視圖查詢: <select id="getStudentAndClassView" parameterType="int" resultType="com.mybatis.bean.studentclass"> 

    resultType 對應簡單類型,也就是實體中的屬性名稱與數據庫表字段名稱一模一樣;
    resultMap 對應複雜類型,屬性名稱與字段名稱不一樣可以通過resultMap中property,column進行映射,其中一對一與一對多都是用resultMap來映射

  3、一對多:<collection property="students" ofType="com.mybatis.bean.Student">

   collection字面意思是集合,這裏專門做一對多關聯 ,property表示集合類型屬性名稱,ofType表示集合中的對象是什麼類型

  4、<select>select * from ...</student>與<select>select 字段1,字段2,字段3... from ...</student>

   可以顯示指出c.class_id,c.class_name,s.s_id,s.s_name列明,如果用"*"代替,則mybatis會自動匹配resultMap或者resultType中提供的列名,

     如果某對象存在列映射的屬性,但是在select 後面找不到這個列,則在返回結果中,該列多映射的值爲null。

 

  至此,對於一對一、一對多、視圖查詢都能很好的解決,主要還是要重點關注第四點說明。

本文轉載地址:https://www.cnblogs.com/wucj/p/5148813.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章