Весенняя JPA Один ко многим Бесконечная рекурсия - PullRequest
0 голосов
/ 09 апреля 2020

я пытаюсь вернуться к данным JPA (преобразованным в DTO, конечно), где они имеют двустороннюю связь @OneToMany и @ManyToOne. Я сейчас применяю вещь fix . Проблема в том, что вывод является recusrive. комментарии есть пост есть комментарии, затем есть посты (комментарии -> пост -> комментарии -> так далее ..)

Я только хочу иметь что-то подобное

{
    "post_id": 1
    "user": {
        // user data
    },
    "description": "some description",
    "images": "{images,images}",
    "tags": "{tags, tags}",
    "comments": [
     {
        //some comments data

     },
     {
        //some comments data
     }
    ]
    "lastUpdated": "2020-04-08T14:23:18.000+00:00"
}

Вот мой код

Это мой Posts.class

@Data
@Entity
@Table(name = "posts")
@EntityListeners(AuditingEntityListener.class)
public class Posts {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "post_id")
    private Long post_id;

    @ManyToOne
    @JoinColumn(name = "user_id", nullable = false)
    private Users user;

    @Column(name = "description")
    private String description;

    @Column(name="images")
    private String images;

    @Column(name="tags")
    private String tags;

    @OneToMany(
        fetch = FetchType.LAZY,
        mappedBy = "post",
        cascade = CascadeType.ALL,
        orphanRemoval = true
    )
    @JsonIgnoreProperties(value = { "comments" ,"hibernateLazyInitializer", "handler" }, allowSetters = true)
    //@JsonManagedReference
    private List<Comments> comments;


    @LastModifiedDate
    @Column(name = "last_updated")
    private Date lastUpdated;


    public void addComments(Comments comment) {
        this.comments.add(comment);
    }
}

Вот мой PostDTO.class

@Data
public class PostDTO {

    private Long post_id;
    private UserDTO user;
    private String description;
    private String images;
    private String tags;
    private List<CommentsDTO> comments;
    private Date lastUpdated;


}

Это мой Comments.class

@Data
@Entity
@Table(name = "comments")
@EntityListeners(AuditingEntityListener.class)
public class Comments {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="comment_id")
    private Long comment_id;

    @OneToOne
    @JoinColumn(name = "user_id")
    private Users user;

    @Column(name = "description")
    private String description;

    @Column(name="images")
    private String images;

    @ManyToOne
    @JoinColumn(name ="post_id" , nullable = false)
    @JsonIgnoreProperties(value = { "post" ,"hibernateLazyInitializer", "handler" }, allowSetters = true)
    //@JsonBackReference
    private Posts post;

    @Column(name="last_updated")
    @LastModifiedDate
    private Date lastUpdated;

}

Здесь мои комментарииDTO.class

@Data
public class CommentsDTO {

    private Long comment_id;

    private UserDTO user;

    private String description;

    private PostDTO post;

    private String images;

    private Date lastUpdated;
}

Вот мой REST Controller

@GetMapping
public @ResponseBody ResponseEntity<List<PostDTO>>  getAll() throws Exception {

    return new ResponseEntity<List<PostDTO>>(service.getAll(), HttpStatus.OK);
}

Вот мой сервис

public List<PostDTO> getAll() throws Exception  {
    return repo.findAll()
               .stream()
               .map(this::convert)
               .collect(Collectors.toList());
}

private PostDTO convert(Posts e) {
    return  mapper.map(e, PostDTO.class);
}

Надеюсь, кто-то может пролить свет на мою проблему. Кинда проиграла с этого времени.

Ответы [ 3 ]

1 голос
/ 09 апреля 2020

Проблема в том, что когда вы конвертируете Post в PostDTO, то с помощью ModelMapper он вызывает получатель Post всего поля для PostDTO. Так что это произошло рекурсивно для этого mapper.map(e, PostDTO.class)

Итак, просто удалите private PostDTO post из CommentDTO, тогда модельер не пытается установить поле PostDTO-> comment-> post. И вам не нужно двунаправленное отношение в DTO. DTO - это все, что вы хотите показать в ответ.

0 голосов
/ 09 апреля 2020

Используйте JsonIgnoreProperties вместе с управлением и обратными ссылками.

 @Data
    @Entity
    @Table(name = "comments")
    @EntityListeners(AuditingEntityListener.class)
    public class Comments {

        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name="comment_id")
        private Long comment_id;

        @OneToOne
        @JoinColumn(name = "user_id")
        private Users user;

        @Column(name = "description")
        private String description;

        @Column(name="images")
        private String images;

        @ManyToOne
        @JoinColumn(name ="post_id" , nullable = false)
        @JsonIgnoreProperties(value = { "comments" ,"hibernateLazyInitializer", "handler" }, allowSetters = true)
       @JsonBackReference
        private Posts post;

        @Column(name="last_updated")
        @LastModifiedDate
        private Date lastUpdated;

    }

И класс Your Post должен быть

@Data
@Entity
@Table(name = "posts")
@EntityListeners(AuditingEntityListener.class)
public class Posts {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "post_id")
    private Long post_id;

    @ManyToOne
    @JoinColumn(name = "user_id", nullable = false)
    private Users user;

    @Column(name = "description")
    private String description;

    @Column(name="images")
    private String images;

    @Column(name="tags")
    private String tags;

    @OneToMany(
        fetch = FetchType.LAZY,
        mappedBy = "post",
        cascade = CascadeType.ALL,
        orphanRemoval = true
    )
    @JsonIgnoreProperties(value = { "post" ,"hibernateLazyInitializer", "handler" }, allowSetters = true)
    @JsonManagedReference
    private List<Comments> comments;


    @LastModifiedDate
    @Column(name = "last_updated")
    private Date lastUpdated;


    public void addComments(Comments comment) {
        this.comments.add(comment);
    }
}

Также я бы предложил использовать аннотацию Getter и Setter вместо @Data. Поскольку метод Tostring () также вызовет рекурсию.

0 голосов
/ 09 апреля 2020

Вы прерываете цикл сериализации json для неправильного класса.

Вы отправляете список из PostDTO, но применяете JsonBackReference к Comments и JsonManagedReference к Posts

Обновление

Обратите внимание, что ObjectMapper class, JsonManagedReference и JsonBackReference может из 2 пакетов

  • com.faster xml .jackson.databind.ObjectMapper
  • com.faster xml .jackson.annotation.JsonManagedReference
  • com.faster xml .jackson.annotation.JsonBackReference

или:

  • org.codehaus.jackson.map.ObjectMapper
  • org.codehaus.jackson.annotate.JsonManagedReference
  • org.codehaus.jackson. annotate.JsonBackReference

Если вы не согласуетесь между всеми ними, несовпадающая аннотация будет проигнорирована, и вы все равно получите бесконечное l oop во время сериализации.

...