休眠多对多关系无限循环?

时间:2018-07-15 08:46:59

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

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注释,则会收到堆栈溢出错误。

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

有解决方案吗?

1 个答案:

答案 0 :(得分:1)

FetchType设置为LAZY

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

现在,即使数据库中存在数据,也将其检索为null。如果希望将它们返回,则只需调用此属性的getter即可,休眠将进入并从数据库中选择它们。

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

更新

将发生递归循环,因为当spring将对象序列化为JSON时,杰克逊将使用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<UserDTO>,则可以创建一个基于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;
    }

}