Mybatis關聯映射


  Mybatis是半自動化的ORM框架,相比於Hibernate具有更好的靈活性,更容易進行性能優化,當然Hibernate和Mybatis各具特點,並不存在技術的優劣問題,只是應用場景不同,對於一個優秀的開發人員來說最好二者的技術都能掌握。Mybatis需要程序員完成實體類屬性和數據庫表字段之間的映射設計,並可以定制化返回類型,因此具有更高的靈活性,設計數據庫表間的關聯映射是Mybatis的核心,本文主要描述Mybatis進行表間關聯映射設計的基本內容,包括完成一對一、一對多、多對多常見關聯關系的映射。

一 案例數據模型

    采用案例驅動的方式去描述、驗證問題往往可以加深技術原理和機制的理解。現模擬日常生活中最常見的學生-課程-選課關聯關系,為更好的描述一對一關聯再添加學生與學生證一對一關聯,其中學生與課程之間為多對多關系,學生與選課之間為一對多關系,課程與選課之間為多對一關聯,具體的數據模型關系圖如下:

  需要注意的是,上圖標注學生選課表與課程之間為一對一關聯可能會令人困惑,但其表示當學生ID和課程ID確定時,課程也隨之唯一確定,所以選課和課程之間為一對一關聯,反之為多對一關聯

二 一對一關聯

  一對一是最簡單的關聯關系,本例中學生和學生證即為一對一的關系,一個學生唯一對應一個學生證,反之由學生證也能唯一確定一個學生。創建Student、StudentSelfCard實體類

package com.learn.mybatis.entity;
import java.util.List;
/**
 * 學生POJO
 * Created by lfq on 2017/5/15.
 */
public class Student {
    private int id;
    private String name;
    private String sex;
    private String note;
    private StudentSelfCard studentSelfCard;//與學生證建立一對一關聯
....省略Setter/Getter方法........
}
package com.learn.mybatis.entity;
import java.util.Date;
/**
 * 學生證POJO
 * Created by wyh on 2017/7/23.
 */
public class StudentSelfCard {
    private Integer id;//主鍵ID
    private String studentId;//與學生表建立一對一關聯
    private String province;//籍貫
    private Date issueDate;//發證日期
    private Date endDate;//結束日期
    private String note;//備注
....省略Setter/Getter方法.....
}
  • Mapper接口

  Mybatis-Spring中為開發者提供了SqlSessionTempate,其封裝了大量的CRUD方法,使數據的持久化操作變得更加簡單,但本着面向接口編程的原則,我們采用定義映射器接口,並由Mybatis根據動態代理機制生成代理類完成相應操作,創建映射器非常簡單,僅需提供一個接口即可,接口中包含數據持久化的方法,方法名對應配置文件中的SQL語句唯一標識。

package com.learn.mybatis.mapper;
import com.learn.mybatis.entity.Student;
/**
 * Created by lfq on 2017/5/15.
 */
public interface StudentDAO {
    Student getStudent(int id);
}
  •   XML映射配置文件

  本例中學生表為核心主表,以其為主,與其他表建立關聯關系,其中Student表的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.learn.mybatis.mapper.StudentDAO">
    <!--嵌套結果查詢-->
    <resultMap id="studentResult" type="com.learn.mybatis.entity.Student">
        <id property="id" column="student_id"/>
        <result property="name" column="student_name"/>
        <result property="sex" column="sex"/>
        <result property="note" column="student_note"/>
        <!--與學生證建立一對一關聯-->
        <association property="studentSelfCard" column="student_id" javaType="com.learn.mybatis.entity.StudentSelfCard">
            <id property="id" column="card_id"/>
            <result property="province" column="native"/>
            <result property="issueDate" javaType="java.util.Date" jdbcType="DATE" column="issue_date"/>
            <result property="endDate" javaType="java.util.Date" jdbcType="DATE" column="end_date"/>
            <result property="note" column="card_note"/>
            <result property="studentId" column="student_id"/>
        </association>
<select id="getStudent" parameterType="int" resultMap="studentResultMap"> SELECT id,cname as name,sex,note FROM t_student WHERE id=#{id} </select> </mapper>

   由上當我們通過映射器調用getStudent方法是,便會執行select查詢,並返回結果集,需要注意的是<association>表示有一個的意思,property表示實體類的屬性,column表示查詢關聯的字段,當映射studentSelftCard屬性時,會傳入student_id作為參數去查詢Student_SelfCard並返回結果集映射。

三 一對多關聯

   一個學生可以擁有多個選課結果,則學生與選課表間為一對多關聯,當學生和選課確定時,課程也隨之確定,則選課與課程之間為一對一關聯,新增StudentLecture和Lecture實體類

package com.learn.mybatis.entity;
/**
 * 學生選課POJO
 * Created by wyh on 2017/5/15.
 */
public class StudentLecture {
    private int id;
    private int studentId;//學生ID
    private Lecture lecture;//與課程表建立關聯
    private String note;//備注
    private double score;//分數
.....省略Setter/Getter方法
}
package com.learn.mybatis.entity;
/**
 * 學生課程POJO
 * Created by wyh on 2017/5/15.
 */
public class Lecture {
    private int id;//主鍵ID
    private String lectureName;//課程名
    private String note;//備注
......省略Setter/Getter方法
}

  此時Student實體類中需要加上 private List<StudentLecture> studentLectureList; 與選課表建立一對多關聯,此時XML映射配置文件對應需要<Collection>建立一對多關聯,即配置文件需要添加集合映射,其中ofType表示集合中的元素類型。

 <!--與課程成績表建立一對多關聯-->
        <collection property="studentLectureList" column="student_id" ofType="com.learn.mybatis.entity.StudentLecture">
            <id property="id" column="stu_lecture_id"/>
            <result property="studentId" column="student_id"/>
            <result property="score" column="grade"/>
            <result property="note" column="stu_lecture_note"/>
            <!--與課程建立一對一關聯-->
            <association property="lecture" javaType="com.learn.mybatis.entity.Lecture" column="lecture_id">
                <id property="id" column="lecture_id"/>
                <result property="lectureName" column="lecture_name"/>
                <result property="note" column="lecture_note"/>
            </association>
        </collection>

   多對多關聯其實是雙向的一對多關聯,本質上可以分解為一對多關聯,因此掌握一對多即可。

三 執行復雜查詢映射

   Mybatis中支持復雜的查詢結果集映射,這是其靈活性的重要體現,在進行結果集映射時具有嵌套語句和嵌套結果兩種,前者會產生N+1的性能問題,故一般都采用嵌套結果的方式執行查詢。嵌套結果時,盡量對SQL語句進行關聯優化,因為過多的關聯會降低查詢性能,本例中展示查詢所有學生的選課及課程信息,設計到Student、Student_SelfCard、Student_Lecture、Lecture四張表的關聯查詢,連接方式均為左外連接,則SQL語句配置如下:

  <select id="queryAllStudent" parameterType="Integer" resultMap="studentResult">
    SELECT
        stu.id AS student_id,
        stu.cname AS student_name,
        stu.sex,
        stu.note AS student_note,
        card.id AS card_id,
        native,
        issue_date,
        end_date,
        card.note AS card_note,
        stu_lec.id AS stu_lecture_id,
        stu_lec.grade,
        stu_lec.note AS stu_lecture_note,
        lec.id AS lecture_id,
        lec.lecture_name,
        lec.note AS lecture_note
    FROM
        t_student stu
    INNER JOIN t_student_selfcard card ON stu.id = card.student_id
    INNER JOIN t_student_lecture stu_lec ON stu_lec.student_id = stu.id
    INNER JOIN t_lecture lec ON lec.id = stu_lec.lecture_id
    WHERE stu.id =#{id};
    </select>

  注意當多表關聯查詢時,對於相同字段的列需要設置別名便於區分,通過執行以上SQL便可返回目標結果集。Mybaits通過設計SQL及結果集便可大大提高程序的靈活性,這也是廣受開發者青睞的原因之一,因此需要熟練掌握。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM