MyBatis一对一关联查询

*1,创建表和数据*
创建一张教师表和一张班级表,一个老师负责一个班级,那么他们之间的关系就是一对一的关系。

  CREATE TABLE teacher(
      t_id INT PRIMARY KEY AUTO_INCREMENT, 
      t_name VARCHAR(20)
  );
  CREATE TABLE class(
      c_id INT PRIMARY KEY AUTO_INCREMENT, 
      c_name VARCHAR(20), 
      teacher_id INT
  );
 ALTER TABLE class ADD CONSTRAINT fk_teacher_id FOREIGN KEY (teacher_id) REFERENCES teacher(t_id);    

 INSERT INTO teacher(t_name) VALUES('teacher1');
 INSERT INTO teacher(t_name) VALUES('teacher2');

 INSERT INTO class(c_name, teacher_id) VALUES('class_a', 1);
 INSERT INTO class(c_name, teacher_id) VALUES('class_b', 2);

表之间的关系就是:
这里写图片描述

2,定义实体类

package me.gacl.domain;

/**
 * @author gacl
 * 定义teacher表对应的实体类
 */
public class Teacher {
    //定义实体类的属性,与teacher表中的字段对应
    private int id;            //id===>t_id
    private String name;    //name===>t_name
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Teacher [id=" + id + ", name=" + name + "]";
    }
}
package me.gacl.domain;

import java.util.List;

/**
 * @author gacl
 * 定义class表对应的实体类
 */
public class Classes {
    //定义实体类的属性,与class表中的字段对应
     private int id;            //id===>c_id
     private String name;    //name===>c_name
    /**
     * class表中有一个teacher_id字段,所以在Classes类中定义一个teacher属性,
     * 用于维护teacher和class之间的一对一关系,通过这个teacher属性就可以知道这个班级是由哪个老师负责的
     */
    private Teacher teacher;
    private List<Student> students;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Teacher getTeacher() {
        return teacher;
    }
    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }
    public List<Student> getStudents(){
        return students;
    }
    public void setStudents(List<Student> students){
        this.students=students;
    }
    @Override
    public String toString() {
        return "Classes [id=" + id + ", name=" + name + ", teacher=" + teacher
                + ",students="+ students +"]";
    }
}

3,定义sql映射文件classMapper.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,namespace的值习惯上设置成包名+sql映射文件名,这样就能够保证namespace的值是唯一的
  例如namespace="me.gacl.mapping.classMapper"就是me.gacl.mapping(包名)+classMapper(classMapper.xml文件去除后缀)
   -->
  <mapper namespace="me.gacl.mapping.classMapper">
      <!-- 
          根据班级id查询班级信息(带老师的信息)
         ##1. 联表查询
         SELECT * FROM class c,teacher t WHERE c.teacher_id=t.t_id AND c.c_id=1;
         ##2. 执行两次查询
         SELECT * FROM class WHERE c_id=1;  //teacher_id=1
         SELECT * FROM teacher WHERE t_id=1;//使用上面得到的teacher_id-->     <!--      方式一:嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集              封装联表查询的数据(去除重复的数据)         select * from class c, teacher t where c.teacher_id=t.t_id and c.c_id=1     -->
              <select id="getClass" parameterType="int" resultMap="ClassResultMap">
         select * from class c, teacher t where c.teacher_id=t.t_id and c.c_id=#{id}
     </select>
     <!-- 使用resultMap映射实体类和字段之间的一一对应关系 -->
     <resultMap type="me.gacl.domain.Classes" id="ClassResultMap">
         <id property="id" column="c_id"/>
         <result property="name" column="c_name"/>
         <association property="teacher" javaType="me.gacl.domain.Teacher">
             <id property="id" column="t_id"/>
             <result property="name" column="t_name"/>
         </association>
     </resultMap>
     <!-- 
          方式二:嵌套查询:通过执行另外一个SQL映射语句来返回预期的复杂类型
         SELECT * FROM class WHERE c_id=1;
         SELECT * FROM teacher WHERE t_id=1   //1 是上一个查询得到的teacher_id的值     -->
      <select id="getClass2" parameterType="int" resultMap="ClassResultMap2">
         select * from class where c_id=#{id}
      </select>
      <!-- 使用resultMap映射实体类和字段之间的一一对应关系 -->
      <resultMap type="me.gacl.domain.Classes" id="ClassResultMap2">
         <id property="id" column="c_id"/>
         <result property="name" column="c_name"/>
         <association property="teacher" column="teacher_id" select="getTeacher"/>
      </resultMap>
      <select id="getTeacher" parameterType="int" resultType="me.gacl.domain.Teacher">
         SELECT t_id id, t_name name FROM teacher WHERE t_id=#{id}
      </select>
 </mapper>

在conf.xml文件中注册classMapper.xml

<mappers>
        <mapper resource="me/gacl/mapping/classMapper.xml"/>
</mappers>

4,测试类代码

package me.gacl.test;

import me.gacl.domain.Classes;
import me.gacl.test.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class Test3 {
    @Test
     public void testGetClass(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        /**
         * 映射sql的标识字符串,
         * me.gacl.mapping.classMapper是classMapper.xml文件中mapper标签的namespace属性的值,
         * getClass是select标签的id属性值,通过select标签的id属性值就可以找到要执行的SQL
         */
        String statement = "me.gacl.mapping.classMapper.getClass";//映射sql的标识字符串
        //执行查询操作,将查询结果自动封装成Classes对象返回
        Classes clazz = sqlSession.selectOne(statement,1);//查询class表中id为1的记录
        //使用SqlSession执行完SQL之后需要关闭SqlSession
        sqlSession.close();
        System.out.println(clazz);//打印结果:Classes [id=1, name=class_a, teacher=Teacher [id=1, name=teacher1]]
    }
    @Test
    public void testGetClass2(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        /**
         * 映射sql的标识字符串,
         * me.gacl.mapping.classMapper是classMapper.xml文件中mapper标签的namespace属性的值,
         * getClass2是select标签的id属性值,通过select标签的id属性值就可以找到要执行的SQL
         */
        String statement = "me.gacl.mapping.classMapper.getClass2";//映射sql的标识字符串
        //执行查询操作,将查询结果自动封装成Classes对象返回
        Classes clazz = sqlSession.selectOne(statement,1);//查询class表中id为1的记录
        //使用SqlSession执行完SQL之后需要关闭SqlSession
        sqlSession.close();
        System.out.println(clazz);//打印结果:Classes [id=1, name=class_a, teacher=Teacher [id=1, name=teacher1]]
    }
}

总结
MyBatis中使用association标签来解决一对一的关联查询,association标签可用的属性如下:
• property:对象属性的名称
• javaType:对象属性的类型
• column:所对应的外键字段名称
• select:使用另一个查询封装的结果

猜你喜欢

转载自blog.csdn.net/wwwdddlll/article/details/82593952