Reputation: 1149
OneToMany relationship causing infinite loop using Spring Data JPA with hibernate as provider
The problem here is not the type of exception but the infinite loop that causes this exception
I tried @JsonIgnoreProperties which gives me another error => 'Could not write JSON: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer'
The post referencing the solution does not have a solution that adresses my problem.
One says use @JsonManagedReference and @JsonBackReference that does stop the recursion but excludes the object (UserGroup in 'myUser' entity) from the result which I need when I want an object of 'myUser' entity.
The other one says about overriding ToString method which I don't do.
Another one explains why there is an infinite loop and suggest as solution to not do that way. I quote "Try to create DTO or Value Object (simple POJO) without cycles from returned model and then return it."
And this one Difference between @JsonIgnore and @JsonBackReference, @JsonManagedReference explains the difference but doing so I will have the same problem as the first one
'myUser' entity
@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;
'UserGroup' entity
@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;
Upvotes: 7
Views: 6624
Reputation: 856
I think I'm getting the point of your problem. You want to fetch MyUser
including the userGroup
data without the circular reference.
Based from the solutions you enumerated, I suggest you should still use the @JsonBackReference
and @JsonManagedReference
to prevent recursion on your entities and for the solution on your problem, you can try to use a mapper (MapStruck) and map the userGroup details to a DTO during the retrieval of data from the service.
DTOs:
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;
}
Mapper (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);
}
After retrieving the data from your repository
, you may then call the myUserToDto
method to map the entity to a DTO.
This is just one way of solving your problem.
Upvotes: 1
Reputation: 2385
change the getUserGroup()
method in your MyUser class as follows.
@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;
}
}
Upvotes: 4
Reputation: 124
you need to add @JsonIgnore
annotation at @OneToMany
like this
@JsonIgnore
@OneToMany
(
mappedBy = "userGroup",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<MyUser> myUsers;
Upvotes: 3