【问题标题】:Spring Data JPA @OneToMany infinite loop exceptionSpring Data JPA @OneToMany 无限循环异常
【发布时间】:2018-08-02 13:29:43
【问题描述】:

OneToMany 关系 使用 Spring Data JPA 和 hibernate 作为提供者导致 无限 循环

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

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

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

One 说使用@JsonManagedReference 和@JsonBackReference 确实会停止递归,但会在我想要'myUser' 对象时从我需要的结果中排除对象('myUser' 实体中的用户组)实体。

另一个说的是我不这样做的覆盖 ToString 方法。

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

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

“我的用户”实体

@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;

【问题讨论】:

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


【解决方案1】:

如下更改 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;
    }
}

【讨论】:

  • 我在 UserGroup 而不是 MyUser 中添加了更新的 getter 方法,但您的建议为我指出了解决方案,所以谢谢 :)
  • 有效!仅在多对一中
【解决方案2】:

你需要在@OneToMany处添加@JsonIgnore注解

喜欢这个

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

【讨论】:

  • 感谢您的回复。 @JsonIgnore 的问题在于,当我在获取“UserGroup”实体时,它会完全忽略我的结果中的“myUsers”字段。在执行后者时,我需要该字段出现在我的结果中。
【解决方案3】:

我想我明白了你的问题的重点。您想在没有循环引用的情况下获取 MyUser 包括 userGroup 数据。

根据您列举的解决方案,我建议您仍应使用@JsonBackReference@JsonManagedReference 在您的实体上防止递归,对于您的问题的解决方案,您可以尝试使用映射器 (MapStruck) 并在从服务中检索数据期间将 userGroup 详细信息映射到 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。

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

【讨论】:

  • 谢谢兄弟。前段时间我确实用 DTO 解决了这个问题。换句话说,我建议停止直接使用您的实体获取数据,以节省时间来处理这些错误和忽略属性的配置等。使用 DTO 执行此操作实际上更容易,您只获取您需要的数据,它为您提供了更大的灵活性。我还建议您使用 spring 来使用 lombok 注释包。谢谢
  • 确定是兄弟!
猜你喜欢
  • 2016-01-18
  • 2019-05-17
  • 2017-01-09
  • 2017-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-10
  • 2012-08-15
相关资源
最近更新 更多