普歌+MyBatis处理多表查询问题

对于多表查询的看法

今日刚学习多表查询,学习完之后自己的看法:
对于一个MyBatis的初学者来说,我对于多表查询来看,其实就是一次性查询多张表。并且这些表有着很大的联系。
1)对于多表查询:就是Collection和Association标签的应用!
2)其中会遇到的问题:多表查询,查出来的信息不完全

多表查询

多表查询分为两大类:多对一、一对多。

处理多对一问题

多对一问题,这里是一种关联的关系。
举例:一个老师、多名学生。

搭建必要环境

数据库的搭建:

-- 创建一个教师表
CREATE TABLE `teacher` (
	`id` INT(10) NOT NULL,
	`name` VARCHAR(30) DEFAULT NULL,
	PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
-- 添加数据
INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老师');
-- 创建一个学生表
CREATE TABLE `student` (
	`id` INT(10) NOT NULL,
	`name` VARCHAR(30) DEFAULT NULL,
	`tid` INT(10) DEFAULT NULL,
	PRIMARY KEY (`id`),
	KEY `fktid` (`tid`),
	CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
-- 向其中添加数据
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小红', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小张', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');

MyBatis框架的搭建

pom文件:
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com</groupId>
  <artifactId>mybatis-06</artifactId>
  <version>1.0-SNAPSHOT</version>


  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
    <!--  mysql的驱动  -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.47</version>
    </dependency>
    <!-- junit测试   -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!--mybatis依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.2</version>
    </dependency>
<!--  这个就是简化实体类书写的Lombok  -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.10</version>
    </dependency>
  </dependencies>
  <build>
    <resources>

      <resource>
        <directory>src/main/java</directory><!--所在的目录-->
        <includes>
          <!--包括目录下的.properties,.xml 文件都会扫描到-->
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>

      <resource>
        <directory>src/main/resources</directory><!--所在的目录-->
        <includes>
          <!--包括目录下的.properties,.xml 文件都会扫描到-->
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>

    </resources>
  </build>
</project>
核心配置文件(记得加上自己的数据库配置文件):
<?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"/>
<!--  设置日志工厂为Log4j  -->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
<!-- 给sql语句返回的类型起别名   -->
    <typeAliases >
        <typeAlias type="com.pojo.Teacher" alias="Teacher"/>
        <typeAlias type="com.pojo.Student" alias="Student"/>
    </typeAliases>
<!-- 进行核心配置文件的环境配置   -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>

        </environment>
    </environments>
<!--引入接口注解配置-->
    <mappers>
      <mapper class="com.Dao.TeacherMapper"/>
        <mapper class="com.Dao.StudentMapper"/>
    </mappers>
</configuration>

编写代码

实体类的编写:根据自己所搭建的数据库来编写!
接口的编写:对应实体类的接口的编写
.xml文件:接口对应的.xml文件的编写

其中关键的问题是.xml文件的编写:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.Dao.StudentMapper">
<!-- 按照结果集查询  -->
    <select id="getStudent2" resultMap="StudentTeacher2">
        select s.id sid,s.name sname,t.name tname
        from student s,teacher t
        where s.tid =t.id
    </select>
<!-- 使用结果集对象resultMap,直接完成多对一查询 -->
    <resultMap id="StudentTeacher2" type="Student" >
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <association property="teacher" javaType="Teacher">
            <result property="name" column="tname"/>
        </association>
    </resultMap>



<!-- 思路:
        1.查询所有的学生信息
        2.根据查询出来的学生的tid,寻找对应的老师!  子查询
-->
<!-- 对于CRUD标签中的resultType属性来说,
        1)如果没有在核心配置文件mybatis-config.xml中,配置起别名设置(typeAliases)
            那么对于此时的resultType属性来说,所写的值是————:com.pogo.Student
        2)如果在核心配置文件中,配置了别名的设置(typeAliases)
            那么对于此时的resultType属性来说,所写的是————:在配置时,所起的别名。
   -->
    <select id="getStudent" resultMap="StudentTeacher">
        select * from student
    </select>
    <resultMap id="StudentTeacher" type="Student">
<!-- 复杂的属性,我们需要单独处理。
        对象:association
        集合:collection
-->
       <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
    </resultMap>
    <select id="getTeacher" resultType="Teacher">
        select * from teacher where id = #{id}
    </select>
</mapper>
测试类的编写

测试类的编写总是千篇一律,但是我对其的书写,还是爱如初恋!

package com.Dao;

import com.pojo.Student;
import com.pojo.Teacher;
import com.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class MyTest {
    /**
     * 测试查询老师的信息,并且测试整体的MyBatis框架是否搭建成功。
     */
    @Test
    public  void getTeacherMapper(){
        //通过创建的工具类,来获取sqlSession对象。其中的sqlSession对象是由核心配置文件,创建sqlSessionFactory工厂,在解析流文件,之后创建sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSession();
        //通过sqlSession对象获取,TeacherMapper接口中的方法,从而获取mapper对象
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        //调用接口中的方法,进行测试
        Teacher teacher = mapper.getTeacher(1);
        //处理结果
        System.out.println(teacher);
        //关闭资源
        sqlSession.close();
    }

    /**
     * 使用子查询:
     *      相当于:sql=select sid,sname,teacher from student where id=(select tid from teacher)
     * 测试查询学生表,运用在MyBatis框架中的sql语句查询出student和teacher表中联系,实现多对一的查询。
     */
    @Test
    public void getStudentTest(){
        //通过创建的工具类,来获取sqlSession对象。其中的sqlSession对象是由核心配置文件,创建sqlSessionFactory工厂,在解析流文件,之后创建sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSession();
        //通过sqlSession对象获取,TeacherMapper接口中的方法,从而获取mapper对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        //调用接口中的方法,进行测试
        List<Student> students = mapper.getStudent();
        //处理结果
        for (Student student : students) {
            System.out.println(student);
        }
        //关闭资源
        sqlSession.close();
    }
    /**
     * 使用结果集查询:
     * 测试查询学生表,运用在MyBatis框架中的sql语句查询出student和teacher表中联系,实现多对一的查询。
     */
    @Test
    public void getStudentTest2(){
        //通过创建的工具类,来获取sqlSession对象。其中的sqlSession对象是由核心配置文件,创建sqlSessionFactory工厂,在解析流文件,之后创建sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSession();
        //通过sqlSession对象获取,TeacherMapper接口中的方法,从而获取mapper对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        //调用接口中的方法,进行测试
        List<Student> students = mapper.getStudent2();
        //处理结果
        for (Student student : students) {
            System.out.println(student);
        }
        //关闭资源
        sqlSession.close();
    }
}

做到这些,那么相信你对于使用MyBatis来处理多表查询,有着一定的了解了!
那么下面让我们做些练习,来巩固一下吧!

对于每个步骤,书写成自己脑海中的语言
把每一步的代码,都加上自己的注释
把每一行代码都敲一遍

处理一对多问题

处理一对多的问题,其实和多对一差不多。这里是一种集合的关系。
举例:一个老师,多个学生。

搭建必要环境同上

编写代码

实体类的编写:根据自己所搭建的数据库来编写!
接口的编写:对应实体类的接口的编写
.xml文件:接口对应的.xml文件的编写

其中,实体类的编写和**.xml文件有着变化**。
实体类的编写

教师表的编写
package com.pojo;
import lombok.Data;

import java.util.List;

//使用Lombok中的注解来完成实体类的写法
@Data
public class Teacher {
    private int id;
    private String name;
    //一个老师有很多个学生,这些学生可以放到一个集合中。可以使用复杂标签Collection来完成一对多的关系。
    private List<Student> students;
}

学生表的编写
package com.pojo;

import lombok.Data;

//使用Lombok中的注解来完成实体类的写法
@Data
public class Student {
    private int id;
    private String name;
    private  int tid;

    public static void main(String[] args) {
        System.out.println();
    }
}

.xml文件的编写
<?xml version="1.0" encoding="UTF-8" ?>
<!--TeacherMapper.xml文件是位了绑定到TeacherMapper接口。就像JDBC中的sql语句的编写的过程。即便是使用注解开发,但是与接口相对应的.xml文件不可或缺 -->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--其中mapper的标签的作用:
        在核心配置文件中:是为了绑定接口信息
        在接口对应的.xml文件中:是为了绑定接口,从而书写对应的sql语句(使用注解开发另说)
-->
<mapper namespace="com.Dao.TeacherMapper">
    <!--
  思路:
      1. 从学生表和老师表中查出学生id,学生姓名,老师姓名
      2. 对查询出来的操作做结果集映射
          1. 集合的话,使用collection!
              JavaType和ofType都是用来指定对象类型的
              JavaType是用来指定pojo中属性的类型
              ofType指定的是映射到list集合属性中pojo的类型。
  -->
    <select id="getTeacher" resultMap="TeacherStudent">
        select s.id sid, s.name sname , t.name tname, t.id tid
        from student s,teacher t
        where s.tid = t.id and t.id=#{id}
    </select>

    <resultMap id="TeacherStudent" type="Teacher">
        <result  property="name" column="tname"/>
        <collection property="students" ofType="Student">
            <result property="id" column="sid" />
            <result property="name" column="sname" />
            <result property="tid" column="tid" />
        </collection>
    </resultMap>
</mapper>
测试类的编写
package com.Dao;

import com.pojo.Teacher;
import com.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class MyTest {
//    @Test
//    public void getTeacherTest(){
//        //首先通过工具类,获取sqlSession对象
//        SqlSession sqlSession = MybatisUtils.getSession();
//        //再通过sqlSession对象,获取其中的TeacherMapper接口
//        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
//        //通过mapper对象,调用接口中的方法
//        List<Teacher> teacher = mapper.getTeacher();
//        for (Teacher teacher1 : teacher) {
//            System.out.println(teacher1);
//        }
//        //关闭sqlSession对象资源
//        sqlSession.close();
//    }
    @Test
    public void  getTeacherTest2(){
        SqlSession session = MybatisUtils.getSession();
        TeacherMapper mapper = session.getMapper(TeacherMapper.class);
        Teacher teacher = mapper.getTeacher(1);
        System.out.println(teacher);
        session.close();
    }
}

做到这些,那么相信你对于使用MyBatis来处理多表查询,有着一定的了解了!
那么下面让我们做些练习,来巩固一下吧!

对于每个步骤,书写成自己脑海中的语言
把每一步的代码,都加上自己的注释
把每一行代码都敲一遍

每时每刻的都在进步的你,还怕有什么解决不了的那?
加油!每一个努力的程序猿!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值