解決使用@ManyToMany查詢數據時的死循環問題

使用@ManyToMany查詢數據時的死循環

初學使用spring data jpa,將問題記錄

以User 和Role為例,兩者為雙向的多對多關系,即可以通過User查詢到Role信息,也可以通過Role查詢到User信息

首先要明白為什麼會出現死循環這個問題,造成這個死循環的原因是因為查詢User時,包含瞭Role屬性,Role中又需要查詢除user屬性,這個不是spring data jpa 的問題,而是隻要代碼裡互相關聯都會造成這種情況,解決這種情況的方法我大概研究出瞭兩種

一、在Role中加上@JsonIgnore註解

代碼如下

User.java

package com.example.demo.entity;
import lombok.Data;  
import javax.persistence.*;
import java.util.Set;
 
/**
 * @author lidai
 * @date 2018/10/23 13:53
 */
@Entity
@Data
@Table(name = "t_user")
public class User {
 
    @Id
    private String userId; 
    private String username; 
    private String password;
 
    @ManyToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
    @JoinTable(name = "t_user_role",
            joinColumns = @JoinColumn(name = "user_id",referencedColumnName = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "role_id",referencedColumnName = "role_id"))
    private Set<Role> roleSet;  
}

Role.java

package com.example.demo.entity; 
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data; 
import javax.persistence.*;
import java.util.Set;
 
/**
 * @author lidai
 * @date 2018/10/29 14:15
 */
@Entity
@Table(name = "t_role")
@Data
@EqualsAndHashCode(exclude = {"userSet"})
public class Role {
 
    @Id
    @GeneratedValue
    private String roleId; 
    private String roleName; 
    private String remark;
 
    @JsonIgnore
    @ManyToMany(fetch = FetchType.LAZY,mappedBy = "roleSet")
    private Set<User> userSet; 
}

很多初學者可能對@ManyToMany這個註解存在一些疑惑,下面給出我的理解僅供參考

@ManyToMany代表多對多的關聯關系

cascade 屬性

  • CascadeType.ALL:級聯包含所有持久化方法
  • CascadeType.PERSIST隻有A類新增時,會級聯B對象新增。若B對象在數據庫存(跟新)在則拋異常(讓B變為持久態)
  • CascadeType.MERGE指A類新增或者變化,會級聯B對象(新增或者變化)
  • CascadeType.REMOVE隻有A類刪除時,會級聯刪除B類;

@JoinTable關聯中間表,如User與Role的中間表為t_user_role

  • name:中間表名
  • JoinColumns:中間表與第一張表關聯的外鍵(第一張表在user中即為user表)
  • inverseJoinColumns:與JoinColumns類似,為第二張表關聯的外鍵

fetch

  • FetchType.EAGER:立即加載
  • FetchType.LAZY:懶加載

mappedBy = “roleSet”:roleSet幾位User表中的List<Role>屬性名

以上為第一種解決方法

二、將雙向關聯改為單向關聯

刪除Role表中的如下代碼即可

    @JsonIgnore
    @ManyToMany(fetch = FetchType.LAZY,mappedBy = "roleSet")
    private Set<User> userSet;

隻不過單向關聯時不能通過Role查詢到User的信息

單向多對多@ManyToMany的使用和理解

  • 單向多對多:就是一個實體類可以獲取到另外一個實體類
  • 多對多:一個員工可以擁有多個角色,一個角色可以對應多個員工
    //角色單向多對多:配置中間表
    //多對多:一個員工可以擁有多個角色,一個角色可以對應多個員工
    @ManyToMany(fetch = FetchType.LAZY)//配置懶加載
    //JoinTable是中間表表名,joinColumns指定中間表中關聯自己ID的字段,  joinColumn是列名,inverseJoinColumns表示中間表中關聯對方ID的字段。
    @JoinTable(name = "employee_role",joinColumns = @JoinColumn(name = "employee_id"),
            inverseJoinColumns = @JoinColumn(name = "role_id"))
    @JsonIgnore //生成json是忽略這個屬性(數據大多,全部拿到沒有意義,還有可能造成死循環)
    //將角色設置進來 有多個角色不能重復
    private Set<Role> roles = new HashSet<>();

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。

推薦閱讀: