MyBatis 第四天 多表操作

123 阅读5分钟

这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战

概述数据库表关系

我们用的Mysql是一个关系型数据库,数据库中的表不都是独立存在的,数据库中的表存在着多种关系,一对一,一对多,多对多,拿出之前气门在SpringDataJpa里边的那张图。

image.png 通常在创建表的时候我们已经实现了这些关系

一对一关系:

  1. 可以共用主键,主键值是一样的
  2. 要不就是在一张表里有一个外键来确定他们的关系 一对多关系:在多的一方建立外键与一的一方的主键关联

多对多关系:通常是有一张中间表存储他们的主键来表示他们之间的。

Mybatis多表查询

数据准备

我们一共使用5张表来实现

Grade:班级表

role: 角色表

student:学生表

studentRole:学生角色表

stuInfo :学生详情表

image.png

一对一查询

一对一查询模型

学生和学生详情之间的关系,一个学生只有一个详情,这就是一对一的关系,之间共用主键,我们现在要实现查询学生信息查到他的详情信息

image.png

代码实现

实体类 Student

@Data
public class Student {
    private Integer id;
    private String studentName;
    private Integer age;
    private String address;
    private Integer gradeId;
    private StuInfo stuInfo;
}

实体类StuInfo


@Data
public class StuInfo {
    private Integer infoid;
    private String infoName;
}

实体类Grade

@Data
public class Grade {

    private Integer gradeid;
    private String gradeName;

    private List<Student> student;

}

GradeMapper

<mapper namespace="com.study.mapper.GradeMapper">

    <insert id="insertGrade" useGeneratedKeys="true" keyProperty="gradeid">
        INSERT INTO mybatis_test.grade
            ( grade_name)
        VALUES( #{gradeName});

    </insert>
</mapper>

StudentMapper

<mapper namespace="com.study.mapper.StudentMapper">

<insert id="insert" useGeneratedKeys="true" keyProperty="id" >
    INSERT INTO student
        (  studentname,age,address,gradeId)
    VALUES( #{studentName}, #{age}, #{address},#{gradeId});
</insert>
</mapper>

StuInfoMapper

<mapper namespace="com.study.mapper.StuInfoMapper">

<insert id="insert">
    INSERT INTO stuinfo
        (infoid, info_name)
    VALUES(#{infoid}, #{infoName});

</insert>
</mapper>

先给表里边塞点数据,把Gradeid也一块加上,添加班级的时候,添加学生,添加学生详情

@Test
public void test3(){
    //获取sqlsession
    SqlSession session = MybatisUtils.getSession();
    GradeMapper mapper = session.getMapper(GradeMapper.class);
    Grade grade = new Grade();
    grade.setGradeName("一年级");
    mapper.insertGrade(grade);
    if (grade.getGradeid() != null){
        StudentMapper mapper1 = session.getMapper(StudentMapper.class);

        Student student = new Student();
        student.setStudentName("张三");
        student.setAge(22);
        student.setGradeId(grade.getGradeid());
        student.setAddress("科技城");
        mapper1.insert(student);
        if (student.getId() != null)
        {
            StuInfoMapper mapper2 = session.getMapper(StuInfoMapper.class);
            StuInfo stuInfo1 = new StuInfo();
            stuInfo1.setInfoName("银行卡");
            stuInfo1.setInfoid(student.getId());
            mapper2.insert(stuInfo1);
        }

        Student student1 = new Student();
        student1.setStudentName("李四");
        student1.setAge(22);
        student1.setGradeId(grade.getGradeid());
        student1.setAddress("科技城");
        mapper1.insert(student1);

        if (student1.getId() != null)
        {
            StuInfoMapper mapper2 = session.getMapper(StuInfoMapper.class);
            StuInfo stuInfo1 = new StuInfo();
            stuInfo1.setInfoName("暂住证");
            stuInfo1.setInfoid(student1.getId());
            mapper2.insert(stuInfo1);
        }


    }
    session.commit();
    session.close();
}

数据如下

image.png

现在开始写一对一查询,查询所有学生时查到学生详情信息,一对一使用三种方法实现

public interface StudentMapper {

    void insert(Student student);
    List<Student> findStudentAll();
    List<Student> findStudentAll1();
    List<Student> findStudentAll2();
}
第一种实现

sql语句实现功能

select * from student  inner join stuinfo   where  student.id=stuinfo.infoid

我们想要是一个这样的结果 image.png 再给学生详情赋值时我们选择使用Student的stuInfo点相应的属性来赋值

<resultMap id="StudentInfo" type="com.study.pojo.Student">
<!--手动指定 表和属性之间的关系
    column : 数据库字段名称
    property :实体类属性名
-->
    <id column="id" property="id"></id>
    <result column="address" property="address"></result>
    <result column="age" property="age"></result>
    <result column="studentName" property="studentName"></result>
    <result column="infoid" property="stuInfo.infoid"></result>
    <result column="info_name" property="stuInfo.infoName"></result>
</resultMap>
<select id="findStudentAll" resultMap="StudentInfo">
    select * from student  inner join stuinfo   where  student.id=stuinfo.infoid
</select>

测试类(第二三种放发实体类同)

@Test
public void test2(){
    //获取sqlsession
    SqlSession session = MybatisUtils.getSession();
    StudentMapper mapper = session.getMapper(StudentMapper.class);
    List<Student> studentAll = mapper.findStudentAll();
    for (Student student : studentAll) {
        System.out.println(student);
    }
}

输出结果

image.png

第二种是实现

第二种我们使用association标签来实现属性的赋值,association本来就是关联的意思,通过property和javaType来指定试题中的属性名,和实体中的数据类型,查询结果是一样的

<resultMap id="StudentInfo1" type="com.study.pojo.Student">
    <id column="id" property="id"></id>
    <result column="address" property="address"></result>
    <result column="age" property="age"></result>
    <result column="studentName" property="studentName"></result>
<!--
    association:用俩关联属性
    property:当前实体中的属性名称
    javaType:当前实体中属性的类型
 -->
    <association property="stuInfo" javaType="com.study.pojo.StuInfo">
        <id column="infoid" property="infoid"></id>
        <result column="info_name" property="infoName"></result>
    </association>
</resultMap>
<select id="findStudentAll1" resultMap="StudentInfo1">
    select * from student  inner join stuinfo   where  student.id=stuinfo.infoid
</select>
第三种实现

第三种我们也是使用association标签使用子查询来实现,我们查询学生详情就是把学生id给到学生详情来查到详情信息

select * from student;

select * from stuinfo where infoid =#{id};

StuentMappe

<resultMap id="StudentInfo2" type="com.study.pojo.Student">
    <id column="id" property="id"></id>
    <result column="address" property="address"></result>
    <result column="age" property="age"></result>
    <result column="studentName" property="studentName"></result>
    <association property="stuInfo" select="com.study.mapper.StuInfoMapper.findAllStuInfo" column="id" ></association>
</resultMap>

<select id="findStudentAll2" resultMap="StudentInfo2">
    select * from student
</select>

stuInfoMapper

<resultMap id="StuInfo" type="com.study.pojo.StuInfo">
    <id column="infoid" property="infoid"></id>
    <result column="info_name" property="infoName"></result>
</resultMap>
<select id="findAllStuInfo" resultMap="StuInfo">
    select * from stuinfo where infoid = #{value}
</select>

这里我们使用association 来建立子查询,property表示要塞值的对象,select表示关联的Mapper文件的方法,column表示关联方法的入参,查询到结果包装成对象返回给主查询,在子查询中我们已经指定了属性和列之间的关系。直接返回一个对象回去,查询结果是跟之前一样的。

一对多查询

一对多查询模型

一个班有多个学生,我们在查询班级信息的时候把班里学生信息查询出来,我这里把学生详情也查出来了

image.png sql实现

select * from student ,grade,stuinfo where student.gradeId= grade.gradeId and student.id =stuinfo.infoid

实现一个这样的效果

image.png

public interface GradeMapper {
    void insertGrade(Grade grade);

    List<Grade> findGradeStudent();
}
<resultMap id="GradeStudent" type="com.study.pojo.Grade">
    <id column="gradeid" property="gradeid"></id>
    <result column="grade_name" property="gradeName"></result>
<!--配置集合信息
    property:配制集合名称
    ofType:集合中的数据类型
-->
    <collection property="student" ofType="com.study.pojo.Student">
        <id column="id" property="id"></id>
        <result column="address" property="address"></result>
        <result column="age" property="age"></result>
        <result column="studentName" property="studentName"></result>
        <result column="gradeId" property="gradeId"></result>
        <collection property="stuInfo" ofType="com.study.pojo.StuInfo">
            <id column="infoid" property="infoid"></id>
            <result column="info_name" property="infoName"></result>
        </collection>
    </collection>
</resultMap>
<select id="findGradeStudent" resultMap="GradeStudent">
    select * from student ,grade,stuinfo where student.gradeId= grade.gradeId and student.id =stuinfo.infoid
</select>

我们使用collection标签来配置集合信息,property配置集合名称,ofType配置集合中的数据类型,然后是集合中的数据的一一对应关系。

@Test
public void test4(){
    //获取sqlsession
    SqlSession session = MybatisUtils.getSession();
    GradeMapper mapper = session.getMapper(GradeMapper.class);
    List<Grade> gradeStudent = mapper.findGradeStudent();
    for (Grade grade : gradeStudent) {
        System.out.println(grade);
    }
}

运行结果,我在算是实现了一对多和一对一一块实现了

image.png

多对多查询

多对多查询模型

学生可以有很多个角色,班长,学委,团支书,一个角色可以被多个人拥有,就需要一张中间表来实现功能

image.png 数据如下 image.png

代码实现

Role类

@Data
public class Role {
    private Integer RoleId;
    private String RoleName;
    private String desc;
}

在student中加上List Role

@Data
public class Student {
    private Integer id;
    private String studentName;
    private Integer age;
    private String address;
    private Integer gradeId;

    private StuInfo stuInfo;

    private List<Role> roleList;

}

sql实现

select * from Student s,role r,StudentRole sr where s.id=sr.StudentId and r.RoleId = sr.RoleId

image.png

mapper

<resultMap id="StudentRole" type="com.study.pojo.Student">
    <id column="id" property="id"></id>
    <result column="address" property="address"></result>
    <result column="age" property="age"></result>
    <result column="studentName" property="studentName"></result>
    <result column="gradeId" property="gradeId"></result>
    <collection property="roleList" ofType="com.study.pojo.Role">
        <id column="RoleId" property="RoleId"></id>
        <result column="RoleName" property="RoleName"></result>
        <result column="desc" property="desc"></result>
    </collection>
</resultMap>
    <select id="findStudentRole" resultMap="StudentRole">
        select * from Student s,role r,StudentRole sr where s.id=sr.StudentId and r.RoleId = sr.RoleId
    </select>

代码实现

@Test
public void test5(){
    //获取sqlsession
    SqlSession session = MybatisUtils.getSession();
    StudentMapper mapper = session.getMapper(StudentMapper.class);
    List<Student> studentRole = mapper.findStudentRole();
    for (Student student : studentRole) {
        for (Role role : student.getRoleList()) {
            System.out.println(student.getStudentName() + "的角色有"+ role.getRoleName() +",负责"+role.getDesc());
        }
    }

}

image.png

Mybatis注解开发

常用注解

Mybatis也支持注解开发,减少些Mapper文件,简化开发,我们就看一些简单的crud,还是多使用xml的方式开发

image.png

public interface UserMapper {
    @Select("select * from user")
    List<User> selectUser();
    //根据id查询
    @Select("select * from user where id = #{id}")
    User findUserById(Integer id);
    //新增一个用户
    @Insert("insert into user (name,pwd) values #{name},#{pwd})")
    void InserUser(User user);
    //更新用户信息
    @Update(" update user set name=#{name},pwd=#{pwd} where  id = #{id}")
    void updateUser(User user);
    // 删除用户信息
    @Delete("delete from user where id=#{id}")
    void deleteUserById(Integer id);
}