springboot jpa外键 (user role)双向多对多@ManyToMany(原创)

多个用户可能有多个角色,多个角色可能有多个用户。所以这种情况下就使用双向@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 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 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内存没有溢出???还请路过的大神评论区帮忙讲解一下。

你可能感兴趣的:(jpa,大厂任性挑,jpa,ManyToMany,多对多,user,role)