Mybatis——复杂查询环境的搭建(多对一的处理&一对多的处理)

多对一的处理

多对一:
在这里插入图片描述

  • 多个学生,对应一个老师
  • 对于学生而言,多个学生关联一个老师(关联关系,多对一,association)
  • 对于老师而言,一个老师集合了多个学生(集合关系,一对多,collection)
    在这里插入图片描述

SQL:

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');

在这里插入图片描述
在这里插入图片描述

  • 查询所有的学生信息,以及对应的老师信息
select s.id,s.name,t.name from student s,teacher t where s.tid=t.id

按照查询嵌套处理

<!--
            id:当前命名空间中的一个唯一标识,用于标识一个结果映射。
            type:类的完全限定名, 或者一个类型别名
-->
<!--        复杂的属性,我们需要单独处理
            对象:association
            集合:collection
-->
<!--
            老师是一个对象,我们用association
            property:映射到列结果的字段或属性
            column:数据库中的列名。我们根据的是学生的tid查询老师的id,因此用到的是student表中的tid
            javaType:一个 Java 类的完全限定名,或一个类型别名。我们写的是老师这个对象的全限定名
            select:用于加载复杂类型属性的映射语句的 ID,它会从 column 属性指定的列中检索数据,作为参数传递给目标 select 语句

-->
<select id="getStudent" resultMap="StudentTeacher">
        select * from student
    </select>

    <resultMap id="StudentTeacher" type="com.kuang.pojo.Student">

        <association  property="teacher" column="tid" javaType="com.kuang.pojo.Teacher" select="getTeacher" />
    </resultMap>

    <select id="getTeacher" resultType="com.kuang.pojo.Teacher">
        select * from teacher where id = #{id}
    </select>
<!--
       思路:
            1.查询所有的学生信息
            2.根据查询出来的学生的tid,寻找对应的老师

-->

    <select id="getStudent" resultMap="StudentTeacher">
        select * from student
    </select>
<!--
            id:当前命名空间中的一个唯一标识,用于标识一个结果映射。
            type:类的完全限定名, 或者一个类型别名
-->
    <resultMap id="StudentTeacher" type="com.kuang.pojo.Student">
<!--        复杂的属性,我们需要单独处理
            对象:association
            集合:collection
-->
<!--
            老师是一个对象,我们用association
            property:映射到列结果的字段或属性
            column:数据库中的列名。我们根据的是学生的tid查询老师的id,因此用到的是student表中的tid
            javaType:一个 Java 类的完全限定名,或一个类型别名。我们写的是老师这个对象的全限定名
            select:用于加载复杂类型属性的映射语句的 ID,它会从 column 属性指定的列中检索数据,作为参数传递给目标 select 语句

-->
        <association  property="teacher" column="tid" javaType="com.kuang.pojo.Teacher" select="getTeacher" />
    </resultMap>

    <select id="getTeacher" resultType="com.kuang.pojo.Teacher">
        select * from teacher where id = #{id}
    </select>

在这里插入图片描述
在这里插入图片描述

按照结果嵌套处理

<!--  按照结果嵌套处理  -->
<!--
       思路:
            1.查询所有的学生信息
            2.根据查询出来的学生的tid,寻找对应的老师
-->
    <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 id="StudentTeacher2" type="com.kuang.pojo.Student">
        <result property="id" column="sid" />
        <result property="name" column="sname" />
        <association property="teacher" javaType="com.kuang.pojo.Teacher">
            <result property="name" column="tname" />
        </association>
    </resultMap>

在这里插入图片描述

在这里插入图片描述

代码流程

1.创建模板mybatis-06

2.创建数据库配置信息——db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useEncoding=false&characterEncoding=UTF-8&serverTimezone=GMT
username=root
password=root

3.创建mybatis配置信息——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>
   <properties resource="db.properties"/>
    <settings>
        <!--标准的日志工厂实现-->
<!--        <setting name="logImpl" value="STDOUT_LOGGING"/>-->
<!--        配置log4j为日志的实现-->
        <setting name="logImpl" value="LOG4J" />
    </settings>

    <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.kuang.dao.StudentMapper" />
    </mappers>
</configuration>

4.创建mybatis工具类——MybatisUtils

package com.kuang.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

//sqlSessionFactory用来构建sqlSession
public class MybatisUtils {

    //提升SqlSessionFactory的作用域
    private static SqlSessionFactory sqlSessionFactory;

    static{
        try {
//            使用Mybatis第一步获取sqlSessionFactory对象
            String resource = "mybatis-config.xml";
//            通过Resources读取配置文件
            InputStream inputStream = Resources.getResourceAsStream(resource);
//          通过SqlSessionFactoryBuilder加载一个流,构建一个sqlSession工厂
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        }catch (IOException e){
            e.printStackTrace();
        }
    }
    //    既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
//    SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
    public static SqlSession getSqlSession(){

        return sqlSessionFactory.openSession(true);

    }
}

5.创建实体类

  • Student
package com.kuang.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
public class Student {
    private int id;
    private String name;

    //学生需要关联一个老师,因此不能直接写tid这个字段
    private Teacher teacher;
}

  • Teacher
package com.kuang.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
public class Teacher {
    private int id;
    private String name;
}

6.创建接口——StudentMapper

package com.kuang.dao;

import com.kuang.pojo.Student;

import java.util.List;

public interface StudentMapper {

    //查询所有的学生信息,以及对应的老师信息
    public List<Student> getStudent();

    public List<Student> getStudent2();

}

7.创建接口配置类——StudentMapper.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.kuang.dao.StudentMapper">

<!--
       思路:
            1.查询所有的学生信息
            2.根据查询出来的学生的tid,寻找对应的老师

-->

    <select id="getStudent" resultMap="StudentTeacher">
        select * from student
    </select>
<!--
            id:当前命名空间中的一个唯一标识,用于标识一个结果映射。
            type:类的完全限定名, 或者一个类型别名
-->
    <resultMap id="StudentTeacher" type="com.kuang.pojo.Student">
<!--        复杂的属性,我们需要单独处理
            对象:association
            集合:collection
-->
<!--
            老师是一个对象,我们用association
            property:映射到列结果的字段或属性,学生对象的属性名
            column:数据库中的列名,学生表中的字段名。我们根据的是学生的tid查询老师的id,因此用到的是student表中的tid
            javaType:一个 Java 类的完全限定名,或一个类型别名。我们写的是老师这个对象的全限定名
            select:用于加载复杂类型属性的映射语句的 ID,它会从 column 属性指定的列中检索数据,作为参数传递给目标 select 语句

-->
        <association  property="teacher" column="tid" javaType="com.kuang.pojo.Teacher" select="getTeacher" />
    </resultMap>

    <select id="getTeacher" resultType="com.kuang.pojo.Teacher">
        select * from teacher where id = #{tid}
    </select>


<!--  按照结果嵌套处理  -->
<!--
       思路:
            1.查询所有的学生信息
            2.根据查询出来的学生的tid,寻找对应的老师
-->
    <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 id="StudentTeacher2" type="com.kuang.pojo.Student">
        <result property="id" column="sid" />
        <result property="name" column="sname" />
        <association property="teacher" javaType="com.kuang.pojo.Teacher">
            <result property="name" column="tname" />
        </association>
    </resultMap>




</mapper>

8.创建测试类——StudentMapperTest

package com.kuang.dao;

import com.kuang.pojo.Student;
import com.kuang.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

import java.util.List;

public class StudentMapperTest {

    static Logger logger = Logger.getLogger(StudentMapperTest.class);

    @Test
    public void getStudent(){
        SqlSession session = MybatisUtils.getSqlSession();

        StudentMapper mapper = session.getMapper(StudentMapper.class);
        List<Student> student = mapper.getStudent();

        for (Student s:student) {
            System.out.println(s);
        }

        session.close();
    }

    @Test
    public void getStudent2(){
        SqlSession session = MybatisUtils.getSqlSession();

        StudentMapper mapper = session.getMapper(StudentMapper.class);
        List<Student> student = mapper.getStudent2();

        for (Student s:student) {
            System.out.println(s);
        }

        session.close();
    }
}

9.各文件位置

在这里插入图片描述

一对多处理

比如:一个老师拥有多个学生
对于老师而言,就是一对多的关系

SQL:

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=#{tid}

按照查询嵌套处理

<select id="getTeacher2" resultMap="TeacherStudent2">
        select * from teacher where id=#{tid}
    </select>
    <resultMap id="TeacherStudent2" type="com.kuang.pojo.Teacher">
        <collection property="students" select="getStudents" javaType="ArrayList" column="id"/>
    </resultMap>
    <select id="getStudents" resultType="com.kuang.pojo.Student">
        select * from student where tid=#{tid}
    </select>

在这里插入图片描述

按照结果嵌套处理

<!--    按结果嵌套查询-->
    <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=#{tid}
    </select>
    <resultMap id="TeacherStudent" type="com.kuang.pojo.Teacher">
       <result property="id" column="tid"/>
        <result property="name" column="tname" />
<!--
        javaType:指定的属性类型
        集合中的泛型信息,我们使用ofType获取
-->
        <collection property="students" ofType="com.kuang.pojo.Student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="tid"/>
        </collection>
    </resultMap>

在这里插入图片描述
在这里插入图片描述

代码流程

1.创建模板mybatis-07

2.创建数据库配置信息——db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useEncoding=false&characterEncoding=UTF-8&serverTimezone=GMT
username=root
password=root

3.创建mybatis配置信息——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>
   <properties resource="db.properties"/>
    <settings>
        <!--标准的日志工厂实现-->
<!--        <setting name="logImpl" value="STDOUT_LOGGING"/>-->
<!--        配置log4j为日志的实现-->
        <setting name="logImpl" value="LOG4J" />
    </settings>

    <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.kuang.dao.TeacherMapper" />
    </mappers>
</configuration>

4.创建mybatis工具类——MybatisUtils

package com.kuang.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

//sqlSessionFactory用来构建sqlSession
public class MybatisUtils {

    //提升SqlSessionFactory的作用域
    private static SqlSessionFactory sqlSessionFactory;

    static{
        try {
//            使用Mybatis第一步获取sqlSessionFactory对象
            String resource = "mybatis-config.xml";
//            通过Resources读取配置文件
            InputStream inputStream = Resources.getResourceAsStream(resource);
//          通过SqlSessionFactoryBuilder加载一个流,构建一个sqlSession工厂
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        }catch (IOException e){
            e.printStackTrace();
        }
    }
    //    既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
//    SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
    public static SqlSession getSqlSession(){

        return sqlSessionFactory.openSession(true);

    }
}

5.创建实体类

  • Student
package com.kuang.pojo;

import lombok.Data;

@Data
public class Student {
    private int id;
    private String name;
   private  int tid;
}


  • Teacher
package com.kuang.pojo;

import lombok.Data;

import java.util.List;

@Data
public class Teacher {
    private int id;
    private String name;

    //一个老师拥有多个学生
    private List<Student> students;
}


6.创建接口——TeacherMapper

package com.kuang.dao;

import com.kuang.pojo.Teacher;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface TeacherMapper {

    //获取老师
//    List<Teacher> getTeacher();

    //获取指定老师下所有学生及老师的信息
    Teacher getTeacher(@Param("tid") int id);

    Teacher getTeacher2(@Param("tid") int id);
}

7.创建接口配置类——TeacherMapper.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.kuang.dao.TeacherMapper">

<!--    按结果嵌套查询-->
    <select id="getTeacher" resultMap="TeacherStudent" >
        select s.id sid,s.name sname, t.name tname,t.id tida from student s,teacher t
        where s.tid=t.id and t.id=#{tid}
    </select>
    <resultMap id="TeacherStudent" type="com.kuang.pojo.Teacher">
       <result property="id" column="tida"/>
        <result property="name" column="tname" />
<!--
        javaType:指定的属性类型
        集合中的泛型信息,我们使用ofType获取
-->
        <collection property="students" ofType="com.kuang.pojo.Student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="tid"/>
        </collection>
    </resultMap>


    <select id="getTeacher2" resultMap="TeacherStudent2">
        select * from teacher where id=#{tid}
    </select>
    <resultMap id="TeacherStudent2" type="com.kuang.pojo.Teacher">
        <collection property="students" select="getStudents" javaType="ArrayList" column="id"/>
    </resultMap>
    <select id="getStudents" resultType="com.kuang.pojo.Student">
        select * from student where tid=#{tid}
    </select>
</mapper>

8.创建测试类——TeacherMapperTest

package dao;

import com.kuang.dao.TeacherMapper;
import com.kuang.pojo.Teacher;
import com.kuang.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

import java.util.List;

public class TeacherMapperTest {

    static Logger logger = Logger.getLogger(TeacherMapperTest.class);

    @Test
    public  void getTeacher(){
        SqlSession session = MybatisUtils.getSqlSession();
        TeacherMapper t = (TeacherMapper)session.getMapper(TeacherMapper.class);
        Teacher teacher = t.getTeacher(1);
        System.out.println(teacher);

        session.close();
    }

    @Test
    public  void getTeacher2(){
        SqlSession session = MybatisUtils.getSqlSession();
        TeacherMapper t = (TeacherMapper)session.getMapper(TeacherMapper.class);
        Teacher teacher = t.getTeacher2(1);
        System.out.println(teacher);

        session.close();
    }

}


9.各文件位置

在这里插入图片描述

小结

1.关联-association
2.集合-collection
3.javaType&ofType
javaType:用来指定实体类中属性的类型
ofType:用来指定映射到List或者集合中的pojo类型,泛型中的约束类型
在这里插入图片描述

在这里插入图片描述

注意点

  • 保证SQL的可读性,尽量保证通俗易懂
  • 注意一对多和多对一中,属性名和字段的问题
  • 如果问题不好排查错误,建议使用log4j

参考:

Mybatis——配置解析
Invalid bound statement (not found)解决方法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值