У меня есть два класса под названием SeriesDBModel и SermonDBModel;Серия содержит много проповедей.
в SermonDBModel, у меня есть
@ManyToOne
@JoinColumn(name="series_id", nullable = false)
private SeriesDBModel series;
в SeriesDBModel, у меня есть
@JoinColumn(name="series_id")
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true )
private List<SermonDBModel> sermons = new ArrayList<>();
Я сохраняю данные с помощью этого вызова (сервис просто оборачивает стандартные Spring-data-репозиторий jpa),
final SeriesDBModel persisted = this.seriesDBService.save(seriesDBModel);
кажется, что он записывает в базу данных штраф (db имеет правильное значение в seriesId в таблице проповедей), и SeriesDBModel возвращается с SermonDBModels.Однако поле серии в возвращаемых SermonDBModels имеет значение null.
В настоящее время происходит то, что контроллер сохраняет данные через службу, а затем при преобразовании сохраненного объекта модели обратно в DTO для отправки обратно вызывающей стороне происходит сбой (в классе Sermon), поскольку отношения наобъекты модели проповеди не установлены должным образом (т. е. серия равна нулю).
Метод контроллера:
@RequestMapping(method = RequestMethod.POST,
value = "/series",
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<FBCApiResponse<Series>> create(@RequestBody SeriesDBModel seriesDBModel){
FBCApiResponse<Series> response;
if(seriesDBModel.getId() != null && seriesDBService.findById(seriesDBModel.getId()).isPresent()){
logger.error("Can't create an entity that already exists");
response = new FBCApiResponse<Series>(null,"Can't create an entity that already exists" );
}
else{
logger.info(String.format("Saving or updating series %s", seriesDBModel));
final SeriesDBModel persisted = this.seriesDBService.save(seriesDBModel);
final Series series = new Series(persisted);
response = new FBCApiResponse<Series>(series, HttpStatus.OK);
}
return new ResponseEntity<FBCApiResponse<Series>>(response, response.getStatusCode());
}
Серия DTO:
public Series(final SeriesDBModel seriesDBModel){
this.id = seriesDBModel.getId();
this.title = seriesDBModel.getTitle();
this.imageURI = Optional.of(URI.create(seriesDBModel.getImageURL()));
final List<SermonDBModel> sermonDBModels = seriesDBModel.getSermons();
this.sermons = (CollectionUtils.isEmpty(sermonDBModels)) ?
Optional.empty() :
Optional.of(
sermonDBModels.stream()
.map(s -> Sermon.fromDBModel(s))
.collect(Collectors.toList())
);
final Stats stats = new Stats(seriesDBModel.getPlays(), seriesDBModel.getLikes(), seriesDBModel.getShares());
this.stats = Optional.of(stats);
this.tags = Optional.ofNullable(seriesDBModel.getTags()).map(tagList -> new HashSet<>(tagList));
}
Проповедь DTO (в настоящее время разрывается из-за NullpointerException, поскольку серия равна нулю)
public static Sermon fromDBModel(final SermonDBModel sermonDBModel){
final int id = sermonDBModel.getId();
final String title = sermonDBModel.getTitle();
final String speaker = sermonDBModel.getSpeaker();
final String series = sermonDBModel.getSeries().getTitle();
final LocalDate date = sermonDBModel.getDate();
final String seriesLink = "/series/" + sermonDBModel.getSeries().getId();
final Optional<URI> mp3URI = Optional.ofNullable(sermonDBModel.getMp3Url()).map(URI::create);
final Optional<URI> imageURI = Optional.ofNullable(sermonDBModel.getImageUrl()).map(URI::create);
final Optional<URI> pdfURI = Optional.ofNullable(sermonDBModel.getImageUrl()).map(URI::create);
final Stats stats = new Stats(sermonDBModel.getPlays(), sermonDBModel.getLikes(), sermonDBModel.getShares());
final Optional<List<String>> tags = Optional.ofNullable(sermonDBModel.getTags());
final Optional<Set<String>> tagSet = tags.map(list -> new HashSet(list));
return new Sermon(id, title, speaker, series, Optional.of(seriesLink), date, mp3URI, imageURI, pdfURI, Optional.of(stats), tagSet);
}
Обратите внимание, я могу «исправить» это, добавив одну строку сразу после того, как возвращенная серия будет сохранена.Но это похоже на взлом.Почему бы hibernate не установить эти отношения для меня?
persisted.getSermons().forEach(sermon -> sermon.setSeries(persisted));