JPA:多对多关系 - JsonMappingException:无限递归

2022-01-01 00:00:00 mysql spring-boot jpa spring-data-jpa

我在处理与 JPA 的多对多关系时遇到问题.我的代码如下所示:

I'm having trouble with a many to many relation with JPA. My code looks as follows:

传感器类:

@Entity
@Table(name = "sensor")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Sensor {
    @Id
    private long chipId;
    @OneToMany(mappedBy = "sensor")
    @JsonBackReference
    private Set<Link> userLinks;
    private String firmwareVersion;
    private long creationTimestamp;
    private String notes;
    private long lastMeasurementTimestamp;
    private long lastEditTimestamp;
    private double gpsLatitude;
    private double gpsLongitude;
    private double gpsAltitude;
    private String country;
    private String city;
    private boolean indoor;
    private boolean published;
}

用户类:

@Entity
@Table(name = "user")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @JsonManagedReference
    private int id;
    private String firstName;
    private String lastName;
    private String email;
    private String password;
    @OneToMany(mappedBy = "user")
    private Set<Link> sensorLinks;
    private int role;
    private int status;
    private long creationTimestamp;
    private long lastEditTimestamp;
}

还有Link类(关系类):

And the Link class (relation class):

@Entity
@Table(name = "link")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Link {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "user_id")
    @MapsId("user_id")
    private User user;

    @ManyToOne
    @JoinColumn(name = "sensor_id")
    @MapsId("sensor_id")
    private Sensor sensor;

    private boolean owner;
    private String name;
    private int color;
    private long creationTimestamp;
}

控制器:

...

@RequestMapping(method = RequestMethod.GET, path = "/user/{email}", produces = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = "Returns details for one specific user")
public User getUserByEmail(@PathVariable("email") String email) {
    return userRepository.findByEmail(email).orElse(null);
}

...

用户存储库:

public interface UserRepository extends JpaRepository<User, Integer> {

    Optional<User> findByEmail(String email);

    @Modifying
    @Query("UPDATE User u SET u.firstName = ?2, u.lastName = ?3, u.password = ?4, u.role = ?5, u.status = ?6 WHERE u.id = ?1")
    Integer updateUser(int id, String firstName, String lastName, String password, int role, int status);
}

我想实现的是,用户端点显示与该特定用户关联的所有传感器.我得到的只是一条错误消息:

I want to achieve, that the user endpoint shows all linked sensors with that particular user. What I get is only an error message:

JSON 映射问题:com.chillibits.particulatematterapi.model.db.main.User["sensorLinks"];嵌套异常是com.fasterxml.jackson.databind.JsonMappingException:无限递归(StackOverflowError)(通过参考链:com.chillibits.particulatematterapi.model.db.main.User["sensorLinks"])

JSON mapping problem: com.chillibits.particulatematterapi.model.db.main.User["sensorLinks"]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.chillibits.particulatematterapi.model.db.main.User["sensorLinks"])

我该如何解决这个问题?

How can I fix this issue?

提前致谢

马克

----------------------------------------- 编辑 -----------------------------------

------------------------------------ Edit -----------------------------------

根据 Abinash Ghosh 的回答,我添加了以下 DTO:

According to Abinash Ghosh's answer, I added following DTOs:

UserDto:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserDto {
    private int id;
    private String firstName;
    private String lastName;
    private Set<LinkDto> sensorLinks;
    private int role;
    private int status;
    private long creationTimestamp;
    private long lastEditTimestamp;
}

链接:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class LinkDto {
    private Integer id;
    private SensorDto sensor;
    private boolean owner;
    private String name;
    private int color;
    private long creationTimestamp;
}

和映射器(我意识到它有点不同,但应该是相同的):

And the mapper (I realized it a bit different, but it should be the same):

public UserDto getUserByEmail(@PathVariable("email") String email) {
    User user = userRepository.findByEmail(email).orElse(null);
    return convertToDto(user);
}

private UserDto convertToDto(User user) {
    return mapper.map(user, UserDto.class);
}

这会导致以下异常:

2020-04-13 14:22:24.383  WARN 8176 --- [nio-8080-exec-2] o.h.e.loading.internal.LoadContexts      : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@68ab57c7<rs=HikariProxyResultSet@2017009664 wrapping Result set representing update count of -1>

1) Error mapping com.chillibits.particulatematterapi.model.db.main.User to com.chillibits.particulatematterapi.model.io.UserDto
1 error] with root cause
java.lang.StackOverflowError: null
at com.mysql.cj.NativeSession.execSQL(NativeSession.java:1109) ~[mysql-connector-java-8.0.19.jar:8.0.19]
...

推荐答案

它正在工作!这篇文章有帮助:https://stackoverflow.com/a/57111004/6296634

It's working! This post helped: https://stackoverflow.com/a/57111004/6296634

在这种情况下,您似乎不应该使用 Lombok @Data.

Seems that you should not use Lombok @Data in such cases.

相关文章