【问题标题】:Hibernate Many to Many relationship Infinity loop?休眠多对多关系无限循环?
【发布时间】:2018-12-23 02:41:29
【问题描述】:

Project Entity's Method

@JsonIgnore
@ManyToMany(mappedBy = "projects")
private List<User> users = new ArrayList<>();

public List<User> getUsers(){
    return users;
}
public void setUsers(List<User> users){
    this.users =users;
}

User Entity's Method

 many to many relationships between users and project...

@ManyToMany(fetch = FetchType.EAGER,cascade = {CascadeType.ALL})
@JoinTable(
        name = "user_project",
        joinColumns = {@JoinColumn(name = "userid")},
        inverseJoinColumns = {@JoinColumn(name="projectid")}
)
private List<Project> projects = new ArrayList<>();

public List<Project> getProjects(){
    return this.projects;
}

public void setProjects(List<Project> projects){
    this.projects = projects;
}

我想在项目实体和用户实体之间创建多对多关系。

当我的控制器调用项目控制器的方法时,我想获取与项目关联的所有用户。同样,当我想获取用户时,我想获取与该用户关联的所有项目。我正在构建一个 REST Web 应用程序。

如果我不使用 @JsonIgnor 注释,则会收到堆栈溢出错误。

但是,如果我在“项目实体”中使用它,那么我不会得到与之关联的所有用户。

有什么解决办法吗?

【问题讨论】:

  • 第一个(首选)解决方案:不要将持久性模型用作 API 模型。设计特定对象 (DTO),其中包含您想要作为对 REST 请求的响应而返回的内容,并将其发送回而不是您的实体。将您的实体转换为控制器中的这些对象。第二种解决方案:使用 Jackson 视图。
  • 如果我创建一个 DTO 并返回 @JSONIgnore 的对象,它会返回到客户端吗?

标签: hibernate spring-mvc spring-boot spring-data-jpa


【解决方案1】:

FetchType 设置为LAZY

@ManyToMany(fetch = FetchType.LAZY ,cascade = {CascadeType.ALL})

现在,即使数据库中存在数据,它也会被检索为 null。如果你想返回它们,那么只需调用这个属性的 getter,这样 hibernate 就会从你的数据库中选择它们。

这对于在从数据库检索数据时防止无限递归很有用。

更新

会发生递归循环,因为当 spring 将对象序列化为 JSON 时,jackson 将使用 getter 和 setter 来检索数据。 这样,即使FetchType 等于LAZY,hibernate 也会从数据库中检索数据。

一种解决方法是让 DTO 类包含您想要返回的内容。

例如:

User.java

public class User {

    private Long id;
    private String name;
    private Date birthDate;
    private List<Post> posts;

    public User() {}

    public User(Long id, String name, Date birthDate) {
        this.id = id;
        this.name = name;
        this.birthDate = birthDate;
        this.posts = new ArrayList < >();
    }

    // getters and setters..

}

Post.java

public class Post {

    private Long id;
    private String title;
    private String content;
    private User owner;

    public Post() {}

    public Post(Long id, String title, String content, User owner) {
        this.id = id;
        this.title = title;
        this.content = content;
        this.owner = owner;
    }

    // getters and setters..

}

UserDTO.java

public class UserDTO {

    private Long id;
    private String name;
    private Date birthDate;

    public UserDTO(User user) {
        this.id = user.getId();
        this.name = user.getName();
        this.birthDate = user.getBirthDate();
    }

    // getters and setters..

}

PostDTO.java

public class PostDTO {

    private Long id;
    private String title;
    private String content;

    public PostDTO(Post post) {
        this.id = post.getId();
        this.title = post.getTitle();
        this.content = post.getContent();
    }

    // getters and setters..

}

UserService.java

@Service
public class UserService {

    @Autowired
    UserRepository userRepository;

    public List<UserDTO> retrieveAll() {
        List <UserDTO> users = userRepository.findAll().stream().map(user -> new UserDTO(user)).collect(Collectors.toList());

        return users;
    }
}

这不会进入无限递归,因为不会渲染用户帖子。

现在,如果您不想返回 ListUserDTO (List&lt;UserDTO&gt;),您可以创建一个帮助程序类,该类根据 UserDTO 信息返回用户。

类似的东西:

Helper.java

public class Helper {

    public static User userFromDTO(UserDTO userDTO) {
        return new User(userDTO.getId(), userDTO.getName(), userDTO.getBirthDate());
    }
}

现在为您服务:

@Service
public class UserService {

    @Autowired
    UserRepository userRepository;

    public List<User> retrieveAll() {
        List<User> users = userRepository.findAll();
        users = users.stream().map(user -> userFromDTO(new UserDTO(user))).collect(Collectors.toList());

        return users;
    }

}

【讨论】:

  • 当通过调用 getter 方法返回实体对象时,它会进入无限递归并显示 StackOverflow 错误。
  • @forhadmethun 解决方案是,如果您不想使用@JsonIgnore,则使用包含您要返回的内容的 DTO
猜你喜欢
  • 1970-01-01
  • 2021-12-23
  • 2015-12-22
  • 1970-01-01
  • 2015-07-21
  • 1970-01-01
相关资源
最近更新 更多