Mybatis的一对多映射

时间:2023-02-03 11:56:52

一、Mybatis的一对多映射

  本例讲述使用mybatis开发过程中常见的一对多映射查询案例。只抽取关键代码和mapper文件中的关键sql和配置,详细的工程搭建和Mybatis详细的流程代码可参见《Mybatis入门和简单Demo》和《Mybatis的CRUD案例

  完整的工程代码已上传至https://files.cnblogs.com/files/jiyukai/MyBatis.zip

  案例:根据一个班级名称查询所有的任课老师

  步骤1.建表脚本,创建班级表grades和教师表teachers,teachers字段tgid(所属班级id)作为grades字段id的外键

create table grades(
    gid    int(5)    primary key,
    gname varchar(10)
 );
create table teachers(
    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,'3年2班');
insert into teachers(sid,sname,sgid) values(1,'math',1);
insert into teachers(sid,sname,sgid) values(2,'english',1);
insert into teachers(sid,sname,sgid) values(2,'science',1);

  步骤2.编写班级,教师信息实体类,由于一个班级任课老师有多个,故用集合的形式来表示

package com.jyk.mybatis.oneTomore;

import java.util.ArrayList;
import java.util.List;

public class Grade {

    private int gid;                        //班级id
    private String gname;                    //班级名称
    private List<Teacher> teacherList = new ArrayList<Teacher>();    //班级拥有的老师
    
    public int getGid() {
        return gid;
    }
    public void setGid(int gid) {
        this.gid = gid;
    }
    public String getGname() {
        return gname;
    }
    public void setGname(String gname) {
        this.gname = gname;
    }
    public List<Teacher> getTeacherList() {
        return teacherList;
    }
    public void setTeacherList(List<Teacher> teacherList) {
        this.teacherList = teacherList;
    }
}
package com.jyk.mybatis.oneTomore;

public class Teacher {

    private int tid;            //老师id
    private String tname;        //老师姓名
    private Grade grade;        //老师所属班级
    
    public int getTid() {
        return tid;
    }
    public void setTid(int tid) {
        this.tid = tid;
    }
    public String getTname() {
        return tname;
    }
    public void setTname(String tname) {
        this.tname = tname;
    }
    public Grade getGrade() {
        return grade;
    }
    public void setGrade(Grade grade) {
        this.grade = grade;
    }
}

  步骤3.编写mapper文件,在GradeMapper.xml中编写班级信息和表字段的映射关系,在TeacherMapper.xml中编写教师实体和表字段的映射关系,并编写好根据一个班级名称查询所有教师信息的SQL,并将mapper文件和对应实体类的别名加入mybatis.xml(mybatis.xml的描述见Mybatis系列第一篇博客,此处由于配置type时指定了类的全路径,故无需将别名加入至mybatis.xml)

  在Grade实体中有一属性为teacherList对象,该对象为一集合,意为一个班级拥有的所有任课老师,此时在配置映射关系时,可使用<collection property="teacherList" resultMap="teacherNamespace.teacherMap"/>标签来引入,property为属性名称,resultMap关联到对应实体类的mapper配置,用名称空间.id来表示。

<?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">

<!-- 名称空间namespace必须唯一 -->
<mapper namespace="gradeNamespace">
    
    <!-- 
        resultMap标签:映射实体与表
        type属性:实体全路径名
        id属性:为实体与表的映射取一个唯一的编号
     -->
    <resultMap type="com.jyk.mybatis.oneTomore.Grade" id="gradeMap">
        <!-- 
        id标签:映射主键属性
        result标签:映射非主键属性
        property属性:实体属性名
        column属性:表的字段名
         -->
        <id property="gid" column="gid"/>
        <result property="gname" column="gname"/>
        <collection property="teacherList" resultMap="teacherNamespace.teacherMap"/>
    </resultMap>
    
    <select id="findByName" parameterType="string" resultMap="gradeMap">
        select g.gname,t.tid,t.tname 
        from grades g,teachers t
        where t.tgid = g.gid and
        t.tname = #{name}
    </select>
</mapper>
<?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">

<!-- 名称空间namespace必须唯一 -->
<mapper namespace="teacherNamespace">
    
    <!-- 
        resultMap标签:映射实体与表
        type属性:实体全路径名
        id属性:为实体与表的映射取一个唯一的编号
     -->
    <resultMap type="com.jyk.mybatis.oneTomore.Teacher" id="teacherMap">
        <!-- 
        id标签:映射主键属性
        result标签:映射非主键属性
        property属性:实体属性名
        column属性:表的字段名
         -->
        <id property="tid" column="tid"/>
        <result property="tname" column="tname"/>
        <!-- <association property="grade" resultMap="gradeNamespace.gradeMap"/> -->
    </resultMap>
    
    <select id="findAllTeacher" parameterType="string" resultMap="teacherMap">
        select t.tid,t.tname,g.gname 
        from teachers t,grades g
        where t.tgid = g.gid
        and g.gname = #{name}
    </select>
    
</mapper>
<?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>

    <!-- 加载类路径下的属性文件 -->
    <properties resource="db.properties">
    </properties>
    
    <!-- 设置类型别名 -->
    <typeAliases>
        
    </typeAliases>

    <!-- 设置一个默认的连接环境信息 -->
    <environments default="mysql_env">
        <!-- 连接环境信息,取一个唯一的编号 -->
        <environment id="mysql_env">
            <!-- mybatis使用的jdbc事务管理方式 -->
            <transactionManager type="jdbc">
            </transactionManager>
            
            <!-- mybatis使用连接池方式来获取链接 -->
            <dataSource type="pooled">
                <!-- 配置与数据库交互的四个属性 -->
                <property name="driver" value="${mysql.driver}"/>
                <property name="url" value="${mysql.url}"/>
                <property name="username" value="${mysql.username}"/>
                <property name="password" value="${mysql.password}"/>
            </dataSource>
        </environment>
    </environments>
    
    <mappers>
        <mapper resource="com/jyk/mybatis/oneTomore/TeacherMapper.xml"/>
        <mapper resource="com/jyk/mybatis/oneTomore/GradeMapper.xml"/>
    </mappers>
    
</configuration>

  步骤4.编写Java代码实现该一对多查询,需要注意的是,区分于一对一查询,此处由于查询的结果有多个,是集合的形式返回,故查询的API应使用SqlSession提供的selectList接口而不再是selectOne。

package com.jyk.mybatis.oneTomore;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.jyk.mybatis.util.MyBatisUtil;

public class GradeDao {
    
    /*
     * 根据班级name查找所有老师
     */
    public List<Teacher> findAllTeacher(String gradeName)
    {
        SqlSession sqlSession = null;
        try{
            sqlSession = MyBatisUtil.getSqlSession();
            List<Teacher> teachers = sqlSession.selectList("teacherNamespace.findAllTeacher", gradeName);
            return teachers;
        }catch(Exception e){
            e.printStackTrace();
            throw e;
        }finally{
            MyBatisUtil.closeSqlSession();
        }
    }
    
    public static void main(String[] args) {
        GradeDao gd = new GradeDao();
        List<Teacher> teachers = gd.findAllTeacher("3年2班");
        System.out.println("teachers=="+teachers);
    }
}