MyBatis學習(二)---數據表之間關聯


想要了解MyBatis基礎的朋友可以通過傳送門:

  MyBatis學習(一)---配置文件,Mapper接口和動態SQL http://www.cnblogs.com/ghq120/p/8322302.html

  本文主要介紹了用MyBatis實現數據表之間的各種關系,例如一對多,多對一,一對一和多對多。

一對多和多對一

本項目的例子為公司的部門和員工之間的關系,即一個部門對應多個員工,反過來多個員工對應一個部門即為多對一。

項目的目錄為

本項目依舊使用Oracle數據庫,對應的表為employee和department

employee表的列

department

 

表對應的實體類分別為

Employee.java

package com.ghq.model.entity; public class Employee { private Integer id; private String empName; private Department dept; public Employee(Integer id, String empName, Department dept) { super(); this.id = id; this.empName = empName; this.dept = dept; } public Employee(String empName, Department dept) { super(); this.empName = empName; this.dept = dept; } public Employee() { } //此處省略setter/getter方法
 @Override public String toString() { return "Employee [id=" + id + ", empName=" + empName + ", dept=" + dept + "]"; } }

 

Department.java

package com.ghq.model.entity; import java.util.List; public class Department { private Integer id; private String deptname; //部門下所有員工
    private List<Employee> emps; public Department(Integer id, String deptname, List<Employee> emps) { super(); this.id = id; this.deptname = deptname; this.emps = emps; } public Department(String deptname, List<Employee> emps) { super(); this.deptname = deptname; this.emps = emps; } public Department() { } //此處省略setter/getter方法
 @Override public String toString() { return "Department [id=" + id + ", deptname=" + deptname + ", emps="
                + emps + "]"; } }

 

配置文件仍為mybatis-config.xml,其中定義了別名,指定了連接池和注冊映射文件。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 加載db.properties文件 -->
    <properties resource="db.properties"></properties>
    
    <!-- 在配置文件中定義別名,可以在映射文件中使用別名 -->
    <typeAliases>
        <!-- 為該包下的實體類定義別名 -->
        <package name="com.ghq.model.entity"/>
    </typeAliases>
    
    <!-- 指定了默認的環境為development -->
  <environments default="development">
      <!-- 指出了環境的唯一標識 -->
    <environment id="development">
        <!-- 指出了事務管理器 -->
      <transactionManager type="JDBC"/>
      <!-- 指出了連接池,並指出了連接數據庫的驅動,url,用戶名,密碼 -->
      <dataSource type="POOLED">
        <property name="driver" value="${db.driver}"/>
        <property name="url" value="${db.url}"/>
        <property name="username" value="${db.username}"/>
        <property name="password" value="${db.password}"/>
      </dataSource>
    </environment>
  </environments>
  <!-- 注冊映射文件 -->
  <mappers>
    <package name="com.ghq.model.dao"/>
  </mappers>
</configuration>

 

db.properties文件中

db.driver=oracle.jdbc.driver.OracleDriver
db.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
db.username=scott
db.password=itcast

 

工具類下MybatisDb.java獲取獲取SqlSessionFactory以及SqlSession的對象,SqlSession中具有對數據表增刪改查的方法

package com.ghq.model.utils; import java.io.IOException; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class MybatisDb { private static String config = "mybatis-config.xml"; private static SqlSessionFactory sqlSessionFac; static{ try { //讀取配置文件
            InputStream inputstream = Resources.getResourceAsStream(config); //獲取SqlSessionFactory對象
            sqlSessionFac = new SqlSessionFactoryBuilder().build(inputstream); } catch (IOException e) { e.printStackTrace(); } } //獲取SqlSession對象,並且開啟了事務
    public static SqlSession getSession(){ return sqlSessionFac.openSession(); } }

 

dao組件

DeptDao主要是獲取指定部門下的員工信息

public interface DeptDao { //獲取部門下員工信息(部門信息和員工信息)
    public List<Department> getDeptEmployee(); }

 

EmpDao是獲取每個員工的部門信息

public interface EmpDao { //獲取每個員工的部門信息
    public List<Employee> getEmployeeDept(); }

 

  Department中獲取所有的員工的屬性時集合類型的,在配置文件中使用的元素是<collection>,該元素必須添加property和ofType屬性, property指出集合屬性名,ofType指出集合元素的類型

  Employee中員工對應的部門信息是實體類類型,在配置文件中使用<association>元素,該元素必須指定property和javaType,property指出的是實體的屬性名,javaType指出了該屬性的類型

DeptDao的配置文件為DeptDao.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.ghq.model.dao.DeptDao">
  <resultMap type="Department" id="deptMap">
    <id column="did" property="id"/>
    <result column="deptname" property="deptname"/>
    
    <!-- 映射集合使用的元素是Collection,該元素必須添加property和ofType屬性, property指出集合屬性名,ofType指出集合元素的類型 -->
    <collection property="emps" ofType="Employee">
      <id column="eid" property="id"/>
      <result column="empname" property="empName"/>
    </collection>
  </resultMap>

    <select id="getDeptEmployee" resultMap="deptMap"> SELECT d.id did, d.deptname, e.id eid, e.empname     FROM department d LEFT JOIN employee e     ON d.id = e.deptid </select>

</mapper>

 

EmpDao的配置文件為EmpDao.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.ghq.model.dao.EmpDao">

  <!-- 用於完成查詢出的列名和相應實體屬性的映射 -->
  <resultMap type="Employee" id="empMap">
    <!-- 用於映射主鍵列 -->
    <id column="eid" property="id"/>
    <!-- 用於映射普通列 -->
    <result column="empname" property="empName"/>
    
    <!-- association元素必須指定property和javaType,property指出的是實體的屬性名,javaType指出了該屬性的類型 -->
    <association property="dept" javaType="Department">
      <id column="did" property="id"/>
      <result column="deptname" property="deptname"/>
    </association>
  </resultMap>
  
  <!-- 查詢出的列名和實體的屬性名不一致,所以應該使用resultMap -->
    <select id="getEmployeeDept" resultMap="empMap"> SELECT e.id eid, e.empname, d.id did, d.deptname     FROM employee e LEFT JOIN department d     ON d.id = e.deptid </select>

</mapper>

 

使用單元測試

public class testmybatis { //此方法對應DeptDao,為測試獲取部門下所有員工的方法
@Test public void testgetDeptEmployee(){ SqlSession session = MybatisDb.getSession(); DeptDao deptDao = session.getMapper(DeptDao.class); List<Department> depts = deptDao.getDeptEmployee(); session.close(); if (depts != null && depts.size() > 0) { for (Department d : depts) { List<Employee> emps = d.getEmps(); if (emps !=null && emps.size() > 0) { for (Employee e : emps) { System.out.println(d.getId()+" "+d.getDeptname()+" "+e.getId()+" "+e.getEmpName()); } } else{ System.out.println(d.getId()+" "+d.getDeptname()+" "+null+" "+null); } } }else { System.out.println("沒有部門"); } } }

 

//此方法對應EmpDao,為測試員工對應部門的方法
 @Test public void testgetEmployeeDept(){ SqlSession session = MybatisDb.getSession(); EmpDao empDao = session.getMapper(EmpDao.class); List<Employee> emps = empDao.getEmployeeDept(); session.close(); if (emps != null && emps.size() > 0) { for (Employee e : emps) { if (e.getDept() == null) { System.out.println(e.getId()+" "+e.getEmpName()+" "+"沒有部門"); }else{ System.out.println(e.getId()+" "+e.getEmpName()+" "+e.getDept().getId()+" "+e.getDept().getDeptname()); } } } }

 

 一對一

  本項目為公民和身份證之間的關系,即一個公民對應一張身份證

對應的表分別為citi_tb和card_tb

citi_tb

 

card_tb

 

表對應的實體類分別為

Citi.java

package com.ghq.model.entity; public class Citi { private Integer id; private String citiName; private IdCard card; public Citi(Integer id, String citiName, IdCard card) { super(); this.id = id; this.citiName = citiName; this.card = card; } public Citi(String citiName, IdCard card) { super(); this.citiName = citiName; this.card = card; } public Citi() { } //此處省略setter/getter方法
} 

 

IdCard.java

package com.ghq.model.entity; public class IdCard { private Integer id; private String cardNo; private String address; private Citi citi; public IdCard(Integer id, String cardNo, String address, Citi citi) { super(); this.id = id; this.cardNo = cardNo; this.address = address; this.citi = citi; } public IdCard(String cardNo, String address, Citi citi) { super(); this.cardNo = cardNo; this.address = address; this.citi = citi; } public IdCard() { super(); // TODO Auto-generated constructor stub
 } //此處省略setter/getter方法
}

 

工具類和配置文件都沒有發生改變

dao組件中CitiDao

public interface CitiDao { //獲取每個公民的身份證信息
    public List<Citi> getCitiIdCard(); }

 

CitiDao的配置文件CitiDao.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.ghq.model.dao.CitiDao">

  <resultMap type="Citi" id="citiMap">
    <id column="citiid" property="id"/>
    <result column="citi_name" property="citiName"/>
    
    <association property="card" javaType="IdCard">
      <id column="cardid" property="id"/>
      <result column="card_no" property="cardNo"/>
      <result column="address" property="address"/>
    </association>
  </resultMap>
  
    <select id="getCitiIdCard" resultMap="citiMap"> SELECT citi.id citiid, citi.citi_name, card.id cardid, card.card_no, card.address     FROM citi_tb citi LEFT JOIN card_tb card     ON citi.id = card.id </select>

</mapper>

 

單元測試的方法

public class testmybatis { @Test public void testgetCitiIdCard(){ SqlSession session = MybatisDb.getSession(); CitiDao citiDao = session.getMapper(CitiDao.class); List<Citi> citis = citiDao.getCitiIdCard(); session.close(); if (citis != null && citis.size() > 0) { for (Citi c : citis) { System.out.println(c.getId()+" "+c.getCitiName()+" "+c.getCard().getId()+" "+c.getCard().getCardNo()+" "+c.getCard().getAddress()); } } } }

 

多對多

本項目為學生信息表,選課表,選課成績表之間的關系,即每一個學生可以選多門課,一門課對應多個學生。

項目的目錄結構

Oracle中對應的表為

學生表stu_tbl2

 

課程表cour_tbl2

 

學生選課表stu_cour_tbl2

 

表所對應的實體類為

Stu.java

//學生實體類
public class Stu { //標識屬性
    private Integer id; //學生名
    private String stuName; //選修的課程
    private List<StuCource> stuCources; //省略有參構造和無參構造函數,setter/getter方法
}

 

Course.java

//課程實體類
public class Cource { //標識屬性
    private Integer id; //課程名字
    private String courceName; //對應的選課記錄
    private  List<StuCource> stuCources; //省略有參構造和無參構造函數,setter/getter方法
}

StuCource.java

//選課實體
public class StuCource { //標識屬性
    private Integer id; //對應的學生
    private Stu stu; //對應的課程
    private Cource cource; //對應的成績
    private double score; //省略有參構造和無參構造函數,setter/getter方法
}

 

dao組件中

public interface StuDao { //獲取每個學生選修課程信息以及成績 包含了學生信息 課程信息 成績信息
    public List<Stu> getStuCource(); }

 

StuDao的配置文件StuDao.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.ghq.model.dao.StuDao">

  <resultMap type="Stu" id="stuMap">
    <id column="sid" property="id"/>
    <result column="stu_name" property="stuName"/>
    <collection property="stuCources" ofType="StuCource">
      <id column="scid" property="id"/>
      <result column="score" property="score"/>
      <association property="cource" javaType="Cource">
        <id column="cid" property="id"/>
        <result column="cour_name" property="courceName"/>
      </association>
    </collection>
   
  </resultMap>
  
    <select id="getStuCource" resultMap="stuMap"> SELECT s.id SID,s.stu_name,c.id cid,c.cour_name,sc.id scid,sc.score FROM stu_cour_tbl2 sc,stu_tbl2 s, cour_tbl2 c WHERE sc.stu_id(+) = s.id AND sc.cour_id = c.id(+) </select>

</mapper>

 

單元測試中的方法

public class testmybatis { @Test public void testgetStuCource(){ SqlSession session = MybatisDb.getSession(); StuDao studao = session.getMapper(StuDao.class); List<Stu> stus = studao.getStuCource(); session.close(); if (stus != null && stus.size() > 0) { for (Stu stu : stus) { List<StuCource> stuCources = stu.getStuCources(); if (stuCources !=null && stuCources.size() > 0) { for (StuCource stuCource : stuCources) { System.out.println(stu.getId()+" "+stu.getStuName()+" "+stuCource.getId()+" "+stuCource.getScore() +" "+stuCource.getCource().getId()+" "+stuCource.getCource().getCourceName()); } }else { System.out.println(stu.getId()+" "+stu.getStuName()+" 該學生沒有選課"); } } }else { System.out.println("沒有學生"); } } }

 

 

 


免責聲明!

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



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