现实生活中实体和实体之间的关系: 一对多、多对多 、一对一

1. 关联映射作用

在现实的项目中进行数据库建模时,我们要遵循数据库设计范式的要求,会对现实中的业务模型进行拆分,封装在不同的数据表中,表与表之间存在着一对一、一对多或是多对多的对应关系。进而,我们对数据库的增删改查操作的主体,也就从单表变成了多表。那么Mybatis中是如何实现这种多表关系的映射呢?答案是使用查询结果集ResultMap (结果集映射)!

resultMap元素中,允许有以下直接子元素:

id :作用与result相同,同时可以标识出用这个字段值可以区分其他对象实例。可以理解为数据表中的主键,可以定位数据表中唯一的一笔记录

result : 将数据表中的字段注入到Java对象属性中

        column :数据库中的字段名

        property:实体类中的属性名

​association :关联,简单的讲,就是“有一个”关系,如“用户”有一个“帐号”   (一对一)

collection :集合,顾名思议,就是“有很多”关系,如“客户”有很多“订单”   (一对多或者多对多)

2. 一对多关联(重点)

一对多的关联主要体现在我们查询的时候需要关联查询多个数据表,在这里我举例查询电影类型,返回该电影类型下的所有电影的和电影信息,需要用到的两个表的信息如下:

 创建对应的数据表、实体和mapper(可以根据表的信息自行添加、所有的数据库的sql在文末)

接口查询方法的返回类型是什么?查询结果包含了两张数据表的所有信息,显然一个对象无法封装这些信息。

解决办法就是在moveType实体类里面添加扩展字段,这样我们就能用一个moveType的对象去接受返回的查询结果。同时在mapper里面使用结果集映射来区分接受的数据字段,每个字段都不要省略

public class MovieType {

    private Integer id;
    private String typeName;

    //表示在电影类型下有多个电影对象--扩展字段
    private List<Movie> movieList;
}

 同时需要给movieType的id字段名取一个别名tid,防止两张表的数据字段id重名,id重名可能会造成返回接轨时无法区分id。

<mapper namespace="com.it.mapper.MovieTypeMapper">

    <!--结果集映射-->
    <resultMap id="typeMap" type="MovieType">
        <id column="TID" property="id"/>
        <result column="TYPENAME" property="typeName"/>
        <!--关联字段:集合  has many-->
        <collection property="movieList" ofType="Movie">
            <id column="ID" property="id"/>
            <result column="TITLE" property="title"/>
            <result column="PRICE" property="price"/>
            <result column="ACTOR" property="actor"/>
            <result column="TYPE_ID" property="typeId"/>
        </collection>
    </resultMap>

    <select id="queryMovieTypeInfo" resultMap="typeMap">
        SELECT
	        tb_movietype.id AS 'tid',
            tb_movietype.typeName,
            tb_movie.*
        FROM
            tb_movietype
            INNER JOIN tb_movie ON tb_movietype.id = tb_movie.type_id
        WHERE
            tb_movietype.typename =#{typeName}
    </select>

</mapper>

MyBatis中使用collection标签来解决一对多的关联查询;

                       ofType属性指定集合中元素的对象类型。

3. 一对一关联(了解)

同样使用上面的两张数据表,查询一个电影,返回电影的信息和电影的类别。一个电影对应一个电影类别(一对一关联)

与一对多的主要区别就是添加的扩展字段和在mapper里面的配置结果集映射时候有所不同,主要区别如下图与所示:

MyBatis中使用association(有一个)标签来解决一对一的关联查询

4. 多对多关联(重点)

创建下面三张数据表,来测试实现多对多关联(人物与角色之间属于多对多的关系)

人物角色是中间表,可以不创建实体类;然后照常添加扩展字段后,配置mapper来实现多对多的关联查询。

 mapper里面需要结果集映射,以及通过给数据字段取别名的解决多个表中字段名冲突问题。

<mapper namespace="com.it.mapper.PeopleMapper">

    <resultMap id="peopleMap" type="People">
        <id column="ID" property="id"/>
        <result column="NAME" property="name"/>
        <result column="SEX" property="sex"/>
        <result column="AGE" property="age"/>
        <!--有多个集合-->
        <collection property="roleList" ofType="Roles">
            <id column="RID" property="id"/>
            <result column="RNAME" property="name"/>
            <result column="REMARK" property="remark"/>
        </collection>
    </resultMap>


    <select id="findByPeopleByName" resultMap="peopleMap">
        SELECT
            tb_people.*,
            tb_role.id as 'rid',
            tb_role.name as 'rname',
            tb_role.remark
        FROM
            tb_people
            INNER JOIN tb_people_role ON tb_people.id = tb_people_role.people_id
            INNER JOIN tb_role ON tb_people_role.role_id = tb_role.id
        WHERE
            tb_people.`name` = #{name}
    </select>

</mapper>

 5.数据库sql文件

/*
 Navicat Premium Data Transfer

 Source Server         : mysql
 Source Server Type    : MySQL
 Source Server Version : 80029
 Source Host           : localhost:3306
 Source Schema         : mybatis-db-1

 Target Server Type    : MySQL
 Target Server Version : 80029
 File Encoding         : 65001

 Date: 28/04/2023 14:51:15
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for tb_car
-- ----------------------------
DROP TABLE IF EXISTS `tb_car`;
CREATE TABLE `tb_car`  (
  `id` int(0) NOT NULL,
  `brand` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  `color` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  `price` decimal(10, 2) NULL DEFAULT NULL,
  `size` double NULL DEFAULT NULL,
  `card_id` int(0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `uq_card_id`(`card_id`) USING BTREE,
  CONSTRAINT `fk_card_id` FOREIGN KEY (`card_id`) REFERENCES `tb_card` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tb_car
-- ----------------------------
INSERT INTO `tb_car` VALUES (1, '玛莎拉蒂', '白色', 90.00, 2, 2);
INSERT INTO `tb_car` VALUES (2, '迈巴赫', '黑色', 120.00, 2.5, 1);

-- ----------------------------
-- Table structure for tb_card
-- ----------------------------
DROP TABLE IF EXISTS `tb_card`;
CREATE TABLE `tb_card`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `num` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  `color` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tb_card
-- ----------------------------
INSERT INTO `tb_card` VALUES (1, '川A5678J', '蓝牌');
INSERT INTO `tb_card` VALUES (2, '川A4545X', '蓝牌');

-- ----------------------------
-- Table structure for tb_movie
-- ----------------------------
DROP TABLE IF EXISTS `tb_movie`;
CREATE TABLE `tb_movie`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  `price` double(10, 2) NULL DEFAULT NULL,
  `actor` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  `type_id` int(0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `fk_type_id`(`type_id`) USING BTREE,
  CONSTRAINT `fk_type_id` FOREIGN KEY (`type_id`) REFERENCES `tb_movietype` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tb_movie
-- ----------------------------
INSERT INTO `tb_movie` VALUES (1, '山村老尸', 50.00, '吴镇宇', 3);
INSERT INTO `tb_movie` VALUES (2, '一眉道长', 60.00, '林正英', 3);
INSERT INTO `tb_movie` VALUES (3, '午夜凶铃', 60.00, '贞子', 3);

-- ----------------------------
-- Table structure for tb_movietype
-- ----------------------------
DROP TABLE IF EXISTS `tb_movietype`;
CREATE TABLE `tb_movietype`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `typename` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tb_movietype
-- ----------------------------
INSERT INTO `tb_movietype` VALUES (1, '动作片');
INSERT INTO `tb_movietype` VALUES (2, '爱情片');
INSERT INTO `tb_movietype` VALUES (3, '恐怖片');
INSERT INTO `tb_movietype` VALUES (4, '科幻片');

-- ----------------------------
-- Table structure for tb_people
-- ----------------------------
DROP TABLE IF EXISTS `tb_people`;
CREATE TABLE `tb_people`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  `sex` char(1) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  `age` int(0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tb_people
-- ----------------------------
INSERT INTO `tb_people` VALUES (1, '苍老师', '女', 18);
INSERT INTO `tb_people` VALUES (2, '波多老师', '女', 28);
INSERT INTO `tb_people` VALUES (3, '小泽老师', '女', 23);

-- ----------------------------
-- Table structure for tb_people_role
-- ----------------------------
DROP TABLE IF EXISTS `tb_people_role`;
CREATE TABLE `tb_people_role`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `people_id` int(0) NULL DEFAULT NULL,
  `role_id` int(0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `fk_people_id`(`people_id`) USING BTREE,
  INDEX `fk_role_id`(`role_id`) USING BTREE,
  CONSTRAINT `fk_people_id` FOREIGN KEY (`people_id`) REFERENCES `tb_people` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
  CONSTRAINT `fk_role_id` FOREIGN KEY (`role_id`) REFERENCES `tb_role` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tb_people_role
-- ----------------------------
INSERT INTO `tb_people_role` VALUES (1, 1, 1);
INSERT INTO `tb_people_role` VALUES (2, 1, 2);
INSERT INTO `tb_people_role` VALUES (3, 1, 3);
INSERT INTO `tb_people_role` VALUES (4, 2, 1);
INSERT INTO `tb_people_role` VALUES (5, 3, 1);

-- ----------------------------
-- Table structure for tb_role
-- ----------------------------
DROP TABLE IF EXISTS `tb_role`;
CREATE TABLE `tb_role`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  `remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tb_role
-- ----------------------------
INSERT INTO `tb_role` VALUES (1, '秘书', '老板秘书');
INSERT INTO `tb_role` VALUES (2, '护士', '医院护士');
INSERT INTO `tb_role` VALUES (3, '售票员', '公交车售票员');
INSERT INTO `tb_role` VALUES (4, '家教', '家庭教育');

SET FOREIGN_KEY_CHECKS = 1;
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐