实体关系是指实体与实体之间的关系,从方向上分为单向关联和双向关联,从实体数量上分为一对一、一对多、多对多等。对于任何两个实体,都要从这两个方面区分它们之间的关系。
一对多
表结构设计
banner表(一方)
-- ----------------------------
-- Table structure for banner
-- ----------------------------
DROP TABLE IF EXISTS `banner`;
CREATE TABLE `banner` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '部分banner可能有标题图片',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
banner_item表(多方)
-- ----------------------------
-- Table structure for banner_item
-- ----------------------------
DROP TABLE IF EXISTS `banner_item`;
CREATE TABLE `banner_item` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`keyword` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`type` smallint(5) unsigned NOT NULL DEFAULT '0',
`banner_id` int(10) unsigned NOT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
单向一对多
一方Banner实体类
@Entity
@Getter
@Setter
public class Banner {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String description;
private String title;
private String img;
@OneToMany(fetch = FetchType.LAZY) //fetch = FetchType.LAZY设置为懒加载
@JoinColumn(name="bannerId") //指定外键名称
private List<BannerItem> items;
}
多方BannerItem实体类
@Entity
@Getter
@Setter
public class BannerItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String img;
private String keyword;
private short type;
private String name;
private Long bannerId;
}
双向一对多
@Entity
@Table(name = "banner")
public class Banner {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String name;
private String description;
private String img;
private String title;
@OneToMany(mappedBy = "banner",fetch = FetchType.EAGER)
private List<BannerItem> items;
}
@Entity
public class BannerItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String img;
private String keyword;
private Short type;
private String name;
@ManyToOne
@JoinColumn(name="bannerId")
private Banner banner;
}
总结
双向一对多关系中
1.在一方打上@OneToMany,在多方打上@ManyToOne
2.需要指明关联的外键@JoinColumn打在多方也就是关系维护方上
3.在关系的被维护方也就是一方的@OneToMany增加一个参数mappedBy,值是多方中的导航属性的名字
双向一对多的外键配置问题
我们原来在banner中手动添加的banner就没有实际的业务意义了,banner只是表明两个表的关系。在双向关系中bannerId是会自动生成的。这里不能显示的声明bannerId,自动创建表的时候会自动生成banner_id。如果一定想让bannerId显示的表达出来要么就使用单向一对多,或者使用双向一对多但是要在@JoinColumn中添加两个参数
@ManyToOne
@JoinColumn(insertable = false,updatable = false,name="bannerId")
private Banner banner;
多对多
表结构设计
-- ----------------------------
-- Table structure for theme
-- ----------------------------
DROP TABLE IF EXISTS `theme`;
CREATE TABLE `theme` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Table structure for spu
-- ----------------------------
DROP TABLE IF EXISTS `spu`;
CREATE TABLE `spu` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`subtitle` varchar(800) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Table structure for theme_spu
-- ----------------------------
DROP TABLE IF EXISTS `theme_spu`;
CREATE TABLE `theme_spu` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`theme_id` int(10) unsigned NOT NULL,
`spu_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
单向多对多
在有些业务中我们是不需要双向多对多的。
默认规则为我们生成的第三张表的命名存在一些问题,我们需要去指定第三张表的名称和第三张表中外键的名称。
使用@JoinTable,参数name指定第三表的表名;joinColumns 和inverseJoinColumns 用于定义外键的名称。
package com.lin.missyou.model;
import javax.persistence.*;
import java.util.List;
@Entity
public class Theme {
@Id
private Long id;
private String title;
private String name;
@ManyToMany
@JoinTable(name="theme_spu",
joinColumns = @JoinColumn(name="theme_id"),
inverseJoinColumns = @JoinColumn(name="spu_id"))
private List<Spu> spuList;
}
@Entity
public class Spu {
@Id
private Long id;
private String title;
private String subtitle;
}
双向多对多
用@ManyToMany(mappedBy = “spuList”)声明关系的被维护端。此处双向多对多与双向一对多就有所区别,双向多对多维护端与被维护端是可以调换的,而双向一对多的维护端与被维护端是不可以调换的。
@Entity
public class Theme {
@Id
private Long id;
private String title;
private String name;
@ManyToMany
@JoinTable(name="theme_spu",
joinColumns = @JoinColumn(name="theme_id"),
inverseJoinColumns = @JoinColumn(name="spu_id"))
private List<Spu> spuList;
}
@Entity
public class Spu {
@Id
private Long id;
private String title;
private String subtitle;
@ManyToMany(mappedBy = "spuList")
private List<Theme> themeList;
}