JSON结果中缺少Java Spring Boot@ManyToOne关系

mm5n2pyu  于 2022-10-23  发布在  Java
关注(0)|答案(2)|浏览(126)

我刚刚开始使用Spring Boot,并且我正在使用默认的存储库API来检索json形式的数据库数据。我已将@ManyToOne关系添加到我的Song and Artist实体。
但现在我没有从服务器获得json响应中的Artist对象,我也不清楚如何才能在不错过PagingAndSorting存储库的分页函数的情况下包括它。
我正在使用Spring-data-rest-JPA。
我现在的回应是:

"_embedded": {
    "songs": [
      {
        "id": 1,
        "title": "SongTitle",
        "genre": "Rap",
        "length": 500,
        "_links": {
          "self": {
            "href": "http://localhost:8080/api/songs/1"
          },
          "song": {
            "href": "http://localhost:8080/api/songs/1"
          },
          "artist": {
            "href": "http://localhost:8080/api/songs/1/artist"
          }
        }
      }
    ]
  },
  "_links": {
    "first": {
      "href": "http://localhost:8080/api/songs?page=0&size=1"
    },
    "self": {
      "href": "http://localhost:8080/api/songs?size=1"
    },
    "next": {
      "href": "http://localhost:8080/api/songs?page=1&size=1"
    },
    "last": {
      "href": "http://localhost:8080/api/songs?page=19&size=1"
    },
    "profile": {
      "href": "http://localhost:8080/api/profile/songs"
    }
  },
  "page": {
    "size": 1,
    "totalElements": 20,
    "totalPages": 20,
    "number": 0
  }
}

但我更希望是这样的:

"_embedded": {
    "songs": [
      {
        "id": 1,
        "title": "SongTitle",
        "genre": "Rap",
        "length": 500,
        "artist": {
           "id": 1,
           "name": "Artistname"
        }
        "_links": {
          "self": {
            "href": "http://localhost:8080/api/songs/1"
          },
          "song": {
            "href": "http://localhost:8080/api/songs/1"
          },
          "artist": {
            "href": "http://localhost:8080/api/songs/1/artist"
          }
        }
      }
    ]
  },
  "_links": {
    "first": {
      "href": "http://localhost:8080/api/songs?page=0&size=1"
    },
    "self": {
      "href": "http://localhost:8080/api/songs?size=1"
    },
    "next": {
      "href": "http://localhost:8080/api/songs?page=1&size=1"
    },
    "last": {
      "href": "http://localhost:8080/api/songs?page=19&size=1"
    },
    "profile": {
      "href": "http://localhost:8080/api/profile/songs"
    }
  },
  "page": {
    "size": 1,
    "totalElements": 20,
    "totalPages": 20,
    "number": 0
  }
}

Song.java

@Getter
@Setter
@Entity
@Table(name = "song")
public class Song {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false, unique = true)
    private Long id;

    @NotNull
    @NotBlank(message = "The song has to have a title")
    private String title;

    @NotNull
    @NotBlank(message = "The song has to have a genre")
    private String genre;

    @NotNull
    @Min(value = 1, message = "The song has to have a song length in seconds")
    private int length;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "artist_id", referencedColumnName = "id")
    private Artist artist;

   /* @Version
    private long version;*/

    public Song() {
    }

    public Song(String title, Artist artist, String genre, int length) {
        this.title = title;
        this.artist = artist;
        this.genre = genre;
        this.length = length;
    }

    public void setArtist(Artist artist) {
        this.artist = artist;
    }

    public Artist getArtist() {
        return artist;
    }

}

Artist.java

@Getter
@Setter
@Entity
@Table(name = "artist")
public class Artist {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Long id;

    @NotNull
    @NotBlank(message = "The artist has to have a name")
    private String name;

    @JsonIgnore
    @OneToMany(mappedBy = "artist")
    private List<Song> songs;

    public Artist() {
    }

    public Artist(String name) {
        this.name = name;
    }

出于测试的目的,我在我的SongController中编写了一个方法:

@GetMapping
    List<Song> getSongs() {
        return songRepository.findAll();
    }

结果包括Artist对象,但不会对其进行任何分页。我怎么能把它包括进去呢?
JSON结果:

[
{
    "id": 1,
    "title": "SongTitle",
    "genre": "Rap",
    "length": 500,
    "artist": {
      "id": 1,
      "name": "ArtistName"
    }
  }
]
wgmfuz8q

wgmfuz8q1#

在您的所有有用建议之后,我找到了一个答案:我已经将我的控制器中方法的返回类型更改为Page,并使用了如下所示的PageRequest类:

@GetMapping
    public Page<Song> getSongs(@RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "5") int size) {
        PageRequest pr = PageRequest.of(page, size);
        return songRepository.findAll(pr);
    }

还使用了一些缺省值,以避免一些例外;)

f4t66c6m

f4t66c6m2#

使用@JsonIdentityInfo或@JsonIgnore并删除@JsonBackReference。以下是@JsonIgnore的示例

public class Artist {
    public Long id;
    public String name;

    public List<Song> songs;
}

public class Song {
    public Long id;
    public String title;
    public String genre;
    public int length;

    @JsonIgnore
    public Artist artist;
}

在这种情况下,@JsonManagedReference或@JsonBackReference将无济于事(有关https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion的更多信息):
(.)我们可以使用@JsonIgnore注解来简单地忽略关系的一方,从而打破链。[我的补充:经常性呼叫链]
以下是@JsonIdentityInfo的示例:

@JsonIdentityInfo(
  generator = ObjectIdGenerators.PropertyGenerator.class, 
  property = "id")
public class Artist { ... }

@JsonIdentityInfo(
  generator = ObjectIdGenerators.PropertyGenerator.class, 
  property = "id")
public class Song { ... }

相关问题