多个用户可能有多个角色,多个角色可能有多个用户。所以这种情况下就使用双向@ManyToMany进行关联(单项也可以,根据业务需求)
jpa会自动生成中间表,java的entity代码中只需要User类和Role类,无需创建中间表user_role类(sql建表语句中可以手动创建该中间表,不手动创建jpa系统也会帮忙自动创建))
注意:
不能用lombok的@EqualsAndHashCode和@ToString,否则死循环内存溢出
一、表结构
User表:
package com.cmit.oag.backend.entity.common;
@Entity
@Getter
@Setter
//@EqualsAndHashCode//不能用@EqualsAndHashCode和@ToString,否则死循环内存溢出
@Table(name = "user")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank(message = "昵称不能为空")
@Column(name = "user_name")
private String userName;
@NotBlank(message = "密码不能为空")
@Column(name = "password")
private String password;
@Column(name = "status")
private Integer status;
// @JsonIgnoreProperties("users")
@JsonIgnore
@ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE})//建议MERGE
@JoinTable(name = "user_role", joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")})
private Set<Role> roles;
}
Role表:
package com.cmit.oag.backend.entity.common;
@Entity
@Getter
@Setter
//@EqualsAndHashCode//不能用@EqualsAndHashCode和@ToString,否则死循环内存溢出
@Table(name = "role")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@Column(name = "status")
private Integer status;
@Column(name = "description")
private String description;
// @JsonIgnoreProperties(value = { "roles" })
@JsonIgnore
@ManyToMany(mappedBy = "roles",fetch = FetchType.EAGER, cascade = {CascadeType.MERGE}) //建议MERGE//mappedBy对方配置关系的属性名称,表示由对方来维护中间表关系
private Set<User> users = new HashSet<>();
}
sql:
create table user_role
(
id bigint(20) primary key AUTO_INCREMENT,
user_id bigint(20) NOT NULL,
role_id bigint(20) NOT NULL
# 这里外键可以不用设置,jpa代码中加以@ManyToMany控制就行了
# CONSTRAINT `fk_user_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
# CONSTRAINT `fk_role_id` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8;
二、cascade = {CascadeType.MERGE}
重要的事情说三遍:
建议使用cascade = {CascadeType.MERGE}
建议使用cascade = {CascadeType.MERGE}
建议使用cascade = {CascadeType.MERGE}
而不是{CascadeType.ALL}!!
务必参看:https://blog.csdn.net/HD243608836/article/details/116137170
三、有个疑问:
双向@ManyToMany时,查询user的时候,role中包含着user,user中又包含着role...如此无限循环为什么jvm内存没有溢出???还请路过的大神评论区帮忙讲解一下。