Mybatis多对一、一对多处理


前提环境搭建

1.在数据库中创建表

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

此时我们的数据就是多个学生对应一个老师,一个老师对应多个学生

然后我们需要先创建一个Maven项目,可参考我之前编写的

2.导入相关依赖包



  org.mybatis
  mybatis
  3.5.7



  junit
  junit
  4.12
  test



  mysql
  mysql-connector-java
  5.1.3



  org.projectlombok
  lombok
  1.18.10

3.创建MyBatis的核心配置文件

先配置一个数据库配置文件db.properties,配置文件存放的位置是src/main/resources目录下

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.111.131:3306/mybatis?characterEncoding=UTF-8
username=root
password=123456

然后创建MyBatis核心配置文件,习惯上命名为mybatis-config.xml,核心配置文件存放的位置是src/main/resources目录下

<?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="mapUnderscoreToCamelCase" value="true"/>
    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 resource="mappers/StudentMapper.xml"/>
      <mapper resource="mappers/TeacherMapper.xml"/>
    mappers> 
configuration>

4.编写Mybatis工具类

public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            //读取MyBatis的核心配置文件
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            //创建SqlSessionFactoryBuilder对象
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            //通过核心配置文件所对应的字节输入流创建工厂类SqlSessionFactory,生产SqlSession对象
            sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession(){
        //参数true为设置自动提交
        return sqlSessionFactory.openSession(true);
    }
}

多对一

查询多个学生信息及对应老师信息

1.创建实体类

该地方我们使用的是Lombok配置实体类,可以通过对其进行了解

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

2.创建Mapper接口

MyBatis中的mapper接口相当于以前的dao。但是区别在于,mapper仅仅是接口,我们不需要提供实现类。

public interface StudentMapper {

    //查询所有学生信息和对应老师信息
    public List getStudent();
    
}
public interface TeacherMapper {

    //Teacher在此不需要定义方法

}

3.创建MyBatis的映射文件

注:mapper接口的全类名和映射文件中的命名空间(namespace)保持一致。

方式一:按照查询嵌套处理(子查询)

该方式比较麻烦的就是需要写两个sql语句,将表A查询sql的结果赋给表B的查询sql,理解下来就是类似于子查询

StudentMapper.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.chen.mybatis.mapper.StudentMapper">

    
    <select id="getStudent" resultMap="StudentTeacher">
        select * from student
    select>
    <resultMap id="StudentTeacher" type="com.chen.mybatis.pojo.Student">
        <result property="id" column="id" />
        <result property="name" column="name" />
        
        
        <association property="teacher" column="tid" javaType="com.chen.mybatis.pojo.Teacher" select="teacherInfo" />
    resultMap>
    
    <select id="teacherInfo" resultType="com.chen.mybatis.pojo.Teacher">
        select * from teacher where id = #{tid}
    select>
    
mapper>

方式二:按照结果嵌套处理(联表查询)简单点

该方式虽然不用写多个sql语句,但是需要给查出来的字段都设置别名,个人感觉的话,可能方式二更容易写一点,当然,不用写多个sql的话其实就是联表查询

StudentMapper.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.chen.mybatis.mapper.StudentMapper">

    
    <select id="getStudent" resultMap="StudentTeacher">
        select s.id sid,s.name sname,t.name tname
        from student s,teacher t
        where s.tid = t.id
    select>
    
    <resultMap id="StudentTeacher" type="com.chen.mybatis.pojo.Student">
        <result property="id" column="sid" />
        <result property="name" column="sname" />
        
        <association property="teacher" javaType="com.chen.mybatis.pojo.Teacher">
            <result property="name" column="tname" />
        association>
    resultMap>
    
mapper>

4.测试

public class MybatisTest {

    @Test
    public void testMybatis() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        StudentMapper studentMapper= sqlSession.getMapper(StudentMapper.class);

        List studentList = studentMapper.getStudent();
        for(Student student:studentList){
            System.out.println(student);
        }
        sqlSession.close();
    }

}

一对多

查询一个老师及对应的多个学生信息

1.创建实体类

该地方我们使用的是Lombok配置实体类,可以通过对其进行了解

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

2.创建Mapper接口

MyBatis中的mapper接口相当于以前的dao。但是区别在于,mapper仅仅是接口,我们不需要提供实现类。

public interface StudentMapper {

    //Student在此不需要定义方法

}
public interface TeacherMapper {

    //获取指定老师的信息及对应的多个学生的信息
    Teacher getTeacher(int id);

}

3.创建MyBatis的映射文件

注:mapper接口的全类名和映射文件中的命名空间(namespace)保持一致。

方式一:按照查询嵌套处理(子查询)

该方式比较麻烦的就是需要写两个sql语句,将表A查询sql的结果赋给表B的查询sql,理解下来就是类似于子查询

TeacherMapper.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.chen.mybatis.mapper.TeacherMapper">

    <select id="getTeacher" parameterType="int" resultMap="TeacherStudent">
        select * from teacher where id = #{id}
    select>
    <resultMap id="TeacherStudent" type="com.chen.mybatis.pojo.Teacher">
        
        <collection property="students" column="id" ofType="com.chen.mybatis.pojo.Student" select="StudentInfo"/>
    resultMap>
    <select id="StudentInfo" resultType="com.chen.mybatis.pojo.Student">
        select * from student where tid = #{id}
    select>
    
mapper>

方式二:按照结果嵌套处理(联表查询)简单点

该方式虽然不用写多个sql语句,但是需要给查出来的字段都设置别名,个人感觉的话,可能方式二更容易写一点,当然,不用写多个sql的话其实就是联表查询了

TeacherMapper.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.chen.mybatis.mapper.TeacherMapper">

    <select id="getTeacher" parameterType="int" resultMap="TeacherStudent">
        select t.id teid,t.name tename,s.id sid,s.name sname
        from teacher t,student s
        where t.id=s.tid and t.id = #{id};
    select>
    <resultMap id="TeacherStudent" type="com.chen.mybatis.pojo.Teacher">
        <result property="id" column="teid" />
        <result property="name" column="tename" />
        
        <collection property="students" ofType="com.chen.mybatis.pojo.Student">
            <result property="id" column="sid" />
            <result property="name" column="sname" />
        collection>
    resultMap>

mapper>

4.测试

public class MybatisTest {
@Test
public void testMybatis() { SqlSession sqlSession = MybatisUtils.getSqlSession(); TeacherMapper teacherMapper = sqlSession.getMapper(TeacherMapper.class); Teacher teacher = teacherMapper.getTeacher(1); System.out.println(teacher); sqlSession.close(); }
}

小结

关联 - association  多对一

集合 - collection     一对多

javaType               用来指定我们实体类中属性的类型

ofType                  用来指定集合中的类型


该文档来自狂神说Java

b站视频链接https://www.bilibili.com/video/BV1NE411Q7Nx?p=22&spm_id_from=pageDriver