• 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("没有学生");
            }
            
        }
        
    }

     

     

  • 相关阅读:
    Oracle 常用的十大 DDL 对象
    Oracle DML
    Oracle 的常用概念
    Spring 4 : 整合 SSH
    Spring3 (事务管理)
    Spring2
    Spring 学习笔记一
    Xpath helper下载
    爬取链家北京市二手房的单个房源页信息
    爬取链家北京市二手房的链家编号
  • 原文地址:https://www.cnblogs.com/ghq120/p/8323918.html
Copyright © 2020-2023  润新知