Spring Data JPA @OneToMany无限循环异常

时间:2018-02-22 15:56:37

标签: json hibernate spring-data-jpa infinite-loop

OneToMany关系导致无限循环使用 Spring Data JPA 以hibernate作为提供程序

这里的问题不是异常的类型,而是导致此异常的无限循环

Infinite loop

我试过@JsonIgnoreProperties,这给了我另一个错误=> '无法编写JSON:没有为类org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer找到序列化程序,也没有发现创建BeanSerializer的属性'

引用该解决方案的帖子没有解决我问题的解决方案。

一个表示使用@JsonManagedReference和@JsonBackReference会停止递归,但会从我需要的结果中排除对象(' myUser'实体中的UserGroup) ' myUser'的对象实体。

另一个说关于覆盖ToString方法,我不做。

另一个解释了为什么存在无限循环并建议不要这样做的解决方案。我引用"尝试创建DTO或值对象(简单POJO),无需返回模型的循环,然后返回它。"

这一个 Difference between @JsonIgnore and @JsonBackReference, @JsonManagedReference解释了差异,但这样做我会遇到与第一个相同的问题

' MYUSER'实体

@Entity
public class MyUser {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  private String firstName;
  private String lastName;
  private String email;
  private Integer age;

  //@JsonIgnoreProperties({"myUsers"})
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "userGroupId")
  private UserGroup userGroup;

'用户组'实体

@Entity
public class UserGroup {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private Integer groupOrder;
    @OneToMany
    (
        mappedBy = "userGroup", 
        cascade = CascadeType.ALL, 
        orphanRemoval = true
    )
    private List<MyUser> myUsers;

3 个答案:

答案 0 :(得分:1)

您需要在@JsonIgnore

添加@OneToMany注释 像这样

@JsonIgnore   
@OneToMany
    (
        mappedBy = "userGroup", 
        cascade = CascadeType.ALL, 
        orphanRemoval = true
    )
    private List<MyUser> myUsers;

答案 1 :(得分:1)

我想我明白你的问题了。您想获取 MyUser 包括 userGroup 数据而没有循环引用

根据您列举的解决方案,我建议您仍应使用 @JsonBackReference@JsonManagedReference防止递归对您的实体以及问题的解决方案,您在从服务中检索数据期间,可以尝试使用映射器 (MapStruck) 并将用户组详细信息映射到 DTO。

DTO:

public class MyUserDto {
    private Long id;
    private String firstName;
    private String lastName;
    private String email;
    private Integer age;
    private UserGroupDto userGroupDto;
}

public class UserGroupDto {
    private Long id;
    private Integer groupOrder;
}

映射器(MapStruck):

@Mapper(componentModel = "spring")
public interface MyUserMapper {

    MyUserMapper INSTANCE = Mappers.getMapper(MyUserMapper.class);
    
    UserGroupDto userGroupToDto(UserGroup userGroup);

    @Mapping(source = "myUser.userGroup", target = "userGroupDto")
    MyUserDto myUserToDto(MyUser myUser);
}

repository 检索数据后,您可以调用 myUserToDto 方法将实体映射到 DTO。

这只是解决您问题的一种方式。

答案 2 :(得分:0)

更改MyUser类中的getUserGroup()方法,如下所示。

@Entity
public class MyUser 
{    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String firstName;
    private String lastName;
    private String email;
    private Integer age;

    //@JsonIgnoreProperties({"myUsers"})
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "userGroupId")
    private UserGroup userGroup;

    public UserGroup getUserGroup() 
    {
        userGroup.setMyUsers(null);
        return userGroup;
    }
}