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项目,可参考我之前编写的Maven项目的创建

2.导入相关依赖包

<!-- Mybatis核心 -->
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.5.7</version>
</dependency>
<!-- junit测试 -->
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
  <scope>test</scope>
</dependency>
<!-- MySQL驱动 -->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.3</version>
</dependency>
<!-- lombok插件 -->
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.18.10</version>
</dependency>

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配置实体类,可以通过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<Student> 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">

    <!--这里resultMap自定义名称,和下方的resultMap对应即可-->
    <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,集合用collection-->
        <!--这里column填的是student的外键,也是teacher的主键,javaType绑定我们另一个对象teacher类型,select绑定另一个语句,也就是我们下方的语句-->
        <association property="teacher" column="tid" javaType="com.chen.mybatis.pojo.Teacher" select="teacherInfo" />
    </resultMap>
    <!--不难看出,我们这里的tid也就是上方所传递过来的-->
    <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<Student> studentList = studentMapper.getStudent();
        for(Student student:studentList){
            System.out.println(student);
        }
        sqlSession.close();
    }

}

一对多

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

1.创建实体类

该地方我们使用的是Lombok配置实体类,可以通过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<Student> 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,ofType代表集合里的类型-->
        <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" />
        <!--复杂属性处理,对象用association,集合用collection
            注意这里使用的是ofType不是javaType
        -->
        <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

posted @ 2022-03-26 01:58  RFAA  阅读(109)  评论(0编辑  收藏  举报