spring-data-jpa 惰性加载Hibernate的问题

ffvjumwh  于 2022-11-10  发布在  Spring
关注(0)|答案(1)|浏览(224)

我有两个实体(组和用户),它们具有一对多和多对多关系,我已将它们标记为获取类型惰性,但在仅检索单个组实体时,我将获取组类中存在的所有实体,这导致StackOverflow错误。
Group.java

package com.bezkoder.springjwt.models;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Entity
@Table(name = "grp")
public class Group {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String groupName;

    @Column
    private String createdBy;

    public Group(String groupName, String createdBy ) {
        this.groupName = groupName;
        this.createdBy = createdBy;
    }

    public Group() {

    }

    public String getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(String createdBy) {
        this.createdBy = createdBy;
    }

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "user_group",
            joinColumns = @JoinColumn(name = "user_id",referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "group_id",referencedColumnName = "id")
    )
    private Set<User> users = new HashSet<>();

    @OneToMany(
            cascade = CascadeType.ALL,
            orphanRemoval = true
    ,fetch = FetchType.LAZY,mappedBy="group")
    private List<Post> postList =  new ArrayList<>();

    public List<Post> getPostList() {
        return postList;
    }

    public void setPostList(List<Post> postList) {
        this.postList = postList;
    }

    public Set<User> getUsers() {
        return users;
    }

    public void setUsers(Set<User> users) {
        this.users = users;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getGroupName() {
        return groupName;
    }

    public void setGroupName(String groupName) {
        this.groupName = groupName;
    }

    public Long getId() {
        return id;
    }
}

User.java

package com.bezkoder.springjwt.models;

import com.fasterxml.jackson.annotation.JsonIgnore;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

@Entity
@Table(name = "users", 
    uniqueConstraints = { 
      @UniqueConstraint(columnNames = "username"),
      @UniqueConstraint(columnNames = "email") 
    })
public class User {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @ManyToMany(fetch = FetchType.LAZY)
  @JoinTable(  name = "user_roles", 
        joinColumns = @JoinColumn(name = "user_id"), 
        inverseJoinColumns = @JoinColumn(name = "role_id"))
  private Set<Role> roles = new HashSet<>();

  @ManyToMany(fetch = FetchType.LAZY,
          cascade = {
                  CascadeType.PERSIST,
                  CascadeType.MERGE
          },
          mappedBy = "users")
  @JsonIgnore
  private Set<Group> groups = new HashSet<>();

  public Set<Group> getGroups() {
    return groups;
  }

  public void setGroups(Set<Group> groups) {
    this.groups = groups;
  }
  @NotBlank
  @Size(max = 20)
  private String username;

  @NotBlank
  @Size(max = 50)
  @Email
  private String email;

  @NotBlank
  @Size(max = 120)
  private String password;
  public User() {
  }

  public User(String username, String email, String password) {
    this.username = username;
    this.email = email;
    this.password = password;
  }

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getUsername() {
    return username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public String getEmail() {
    return email;
  }

  public void setEmail(String email) {
    this.email = email;
  }

  public String getPassword() {
    return password;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  public Set<Role> getRoles() {
    return roles;
  }

  public void setRoles(Set<Role> roles) {
    this.roles = roles;
  }
}

错误

java.lang.StackOverflowError: null
    at java.base/jdk.internal.misc.Unsafe.allocateUninitializedArray(Unsafe.java:1380) ~[na:na]
    at java.base/java.lang.StringConcatHelper.newArray(StringConcatHelper.java:494) ~[na:na]
    at java.base/java.lang.StringConcatHelper.simpleConcat(StringConcatHelper.java:421) ~[na:na]
    at java.base/java.lang.String.concat(String.java:2768) ~[na:na]
    at java.base/java.net.URLStreamHandler.parseURL(URLStreamHandler.java:265) ~[na:na]
    at java.base/sun.net.www.protocol.file.Handler.parseURL(Handler.java:67) ~[na:na]
    at java.base/java.net.URL.<init>(URL.java:703) ~[na:na]
    at java.base/java.net.URL.<init>(URL.java:569) ~[na:na]
    at java.base/jdk.internal.loader.URLClassPath$FileLoader.getResource(URLClassPath.java:1246) ~[na:na]
    at java.base/jdk.internal.loader.URLClassPath.getResource(URLClassPath.java:322) ~[na:na]
    at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:757) ~[na:na]
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681) ~[na:na]
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639) ~[na:na]
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na]
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
    at com.fasterxml.jackson.databind.JsonMappingException.prependPath(JsonMappingException.java:445) ~[jackson-databind-2.13.3.jar:2.13.3]

控制器类调试(组具有无限多个用户,并且由于用户具有组,因此会发生一些递归)

agxfikkp

agxfikkp1#

您所看到的并没有任何迹象表明正在进行急切加载。@Jhilton很接近,尽管它不是加载所有引用的ResponseEntity,而是您的调试器。惰性加载是为了在需要时透明地加载实体而构建的,这正是当您试图在调试器中显示实体时所发生的情况。
另请注意,用户或组的数量不是无限的,而是同一个用户和同一个组一次又一次地出现。
当您将实体序列化为Json或以其他方式呈现它时,也可能发生同样的情况。

相关问题