休眠将同一实体保存两次

时间:2018-07-16 15:28:57

标签: java spring hibernate spring-boot spring-data-jpa

我有三个具有双向多对一映射的实体:

@MappedSuperclass
@Getter
@Setter
abstract class Media {
  @Id
  @Column
  @GeneratedValue(strategy = GenerationType.SEQUENCE)
  protected Long id;

  @Column(name = "imdb_id")
  private String imdbId;

  @Column(name = "api_movie_id")
  private String apiMovieId;

  @Column
  private Long metadataItemIdentity;

  @Column
  protected String title;

  @Column(name = "original_title")
  protected String originalTitle;

  @Column
  protected String studio;

  @Column
  protected Double rating;

  @Column(length = 500)
  protected String description;

  @Column(name = "content_rating")
  protected String contentRating;

  @Column
  protected String genres;

  @Column
  protected String director;

  @Column
  protected Long duration;

  @Column
  protected String writer;

  @Column
  protected String stars;

  @Column(name = "year_of_release")
  protected Integer year;

  @Column(name = "country_code")
  protected String countryCode;

  @Column(name = "is_ok")
  protected boolean isOk = true;

  @Column(name = "audio_lang")
  protected String audioLanguage = "";

  @Column(name = "sub_lang")
  protected String subtitlesLanguage = "";

  @Column(name = "api_name")
  protected String apiName;
}

@Entity(name = "seasons")
@Getter
@Setter()
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Season {

  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE)
  @Column
  protected Long id;

  @Column
  private Long metadataItemIdentity;

  @ManyToOne
  @JoinColumn(name = "fk_series")
  private Series series;

  @OneToMany(mappedBy = "season", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
  private List<Episode> episodes;

  private Integer number;
}

@Entity(name = "series")
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Series extends Media {

  @OneToMany(mappedBy = "series", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
  List<Season> seasons;
}

现在保存的逻辑是:

@Service
@Slf4j
public class SeriesMigrateServiceImpl implements SeriesMigrateService {

  private final SeriesService seriesService;

  private final MetaDataItemRepository metaDataItemRepository;

  private final ModelMapper modelMapper;

  @Autowired
  public SeriesMigrateServiceImpl(SeriesService seriesService,
                                  MetaDataItemRepository metaDataItemRepository,
                                  ModelMapper modelMapper) {
    this.seriesService = seriesService;
    this.metaDataItemRepository = metaDataItemRepository;
    this.modelMapper = modelMapper;
  }

  @Override
  public void migrateSeries() {
    List<Series> allSeries = this.getAllSeriesFromSqlite();

    allSeries.forEach(this::populateSeasons);

    seriesService.saveSeries(allSeries);
  }

  private void populateSeasons(Series series) {

    List<Season> allSeasons = this.getAllSeasonsForSeriesFromSqlite(series);

    allSeasons.forEach(season -> season.setSeries(series));

    allSeasons.forEach(this::populateEpisodes);

    series.setSeasons(allSeasons);
  }

  private void populateEpisodes(Season season) {

    List<Episode> allEpisodes = this.getAllEpisodesForSeasonFromSqlite(season);

    allEpisodes.forEach(episode -> episode.setSeason(season));

    season.setEpisodes(allEpisodes);
  }

  private List<Series> getAllSeriesFromSqlite() {
    return metaDataItemRepository
            .findAllSeries().stream()
            .map(item -> this.convert(item, Series.class))
            .collect(Collectors.toList());
  }

  private List<Season> getAllSeasonsForSeriesFromSqlite(Series series) {
    return metaDataItemRepository
            .findAllByParentIdentityAndMetadataType(series.getMetadataItemIdentity(), 3).stream()
            .map(item -> this.convert(item, Season.class))
            .collect(Collectors.toList());
  }

  private List<Episode> getAllEpisodesForSeasonFromSqlite(Season season) {
    return metaDataItemRepository
            .findAllByParentIdentityAndMetadataType(season.getMetadataItemIdentity(), 4).stream()
            .map(item -> this.convert(item, Episode.class))
            .collect(Collectors.toList());
  }

  private <T> T convert(MetaDataItem item, Class<T> classType) {
    return modelMapper.map(item, classType);
  }
}

会发生什么情况,有时Hibernate会保存两次实体,例如,如果我有840个媒体文件,Hibernate会保存1680个?而令我最困扰的是,有时正确工作有时却没有?有什么建议么?  *编辑

@Service
public class SeriesServiceImpl implements SeriesService {

  private final SeriesRepository seriesRepository;

  @Autowired
  public SeriesServiceImpl(SeriesRepository seriesRepository) {
    this.seriesRepository = seriesRepository;
  }

  @Override
  @Transactional
  public List<Series> saveSeries(List<Series> series) {
    return seriesRepository.save(series);
  }
}

0 个答案:

没有答案