Skip to content
This repository was archived by the owner on May 21, 2026. It is now read-only.

Commit 97d4a1e

Browse files
Refactor MediaModel: fix equals bug, List->Set, remove SUBSELECT, add BatchMapping
Co-authored-by: vitorhugo-java <65777252+vitorhugo-java@users.noreply.github.com>
1 parent b9c3e31 commit 97d4a1e

28 files changed

Lines changed: 376 additions & 69 deletions

src/main/java/com/espacogeek/geek/batch/MovieItemWriter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,13 @@ public void write(List<? extends MediaModel> items) {
7575

7676
// fetch and persist alternative titles using the external API id (if present)
7777
try {
78-
String externalId = original.getExternalReference().get(0).getReference();
78+
String externalId = original.getExternalReference().iterator().next().getReference();
7979
if (externalId != null) {
8080
var alts = movieApi.getAlternativeTitles(Integer.valueOf(externalId));
8181
if (alts != null && !alts.isEmpty()) {
8282
alts.forEach(a -> a.setMedia(persisted));
8383
alternativeTitlesService.saveAll(alts);
84-
persisted.setAlternativeTitles(alts);
84+
persisted.setAlternativeTitles(new java.util.LinkedHashSet<>(alts));
8585
}
8686
}
8787
} catch (Exception e) {

src/main/java/com/espacogeek/geek/batch/MovieProcessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public MediaModel process(JSONObject json) {
8787
externalReference.setTypeReference(typeReference);
8888
externalReference.setReference(idStr);
8989

90-
List<ExternalReferenceModel> refs = new ArrayList<>();
90+
java.util.LinkedHashSet<ExternalReferenceModel> refs = new java.util.LinkedHashSet<>();
9191
refs.add(externalReference);
9292
media.setExternalReference(refs);
9393

src/main/java/com/espacogeek/geek/batch/SerieItemWriter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,15 @@ public void write(List<? extends MediaModel> items) {
7575
}
7676

7777
try {
78-
String externalId = original.getExternalReference().get(0).getReference();
78+
String externalId = original.getExternalReference().iterator().next().getReference();
7979
if (externalId != null) {
8080
List<AlternativeTitleModel> alts = tvSeriesApi.getAlternativeTitles(Integer.valueOf(externalId));
8181
if (alts != null && !alts.isEmpty()) {
8282
for (AlternativeTitleModel alternativeTitleModel : alts) {
8383
alternativeTitleModel.setMedia(persisted);
8484
}
8585
alternativeTitlesService.saveAll(alts);
86-
persisted.setAlternativeTitles(alts);
86+
persisted.setAlternativeTitles(new java.util.LinkedHashSet<>(alts));
8787
}
8888
}
8989
} catch (Exception e) {

src/main/java/com/espacogeek/geek/batch/SerieProcessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public MediaModel process(JSONObject json) {
8787
externalReference.setTypeReference(typeReference);
8888
externalReference.setReference(idStr);
8989

90-
List<ExternalReferenceModel> refs = new ArrayList<>();
90+
java.util.LinkedHashSet<ExternalReferenceModel> refs = new java.util.LinkedHashSet<>();
9191
refs.add(externalReference);
9292
media.setExternalReference(refs);
9393

src/main/java/com/espacogeek/geek/controllers/MediaController.java

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,42 @@
22

33
import lombok.RequiredArgsConstructor;
44
import org.springframework.graphql.data.method.annotation.Argument;
5+
import org.springframework.graphql.data.method.annotation.BatchMapping;
56
import org.springframework.graphql.data.method.annotation.QueryMapping;
67
import org.springframework.stereotype.Controller;
78

9+
import com.espacogeek.geek.models.AlternativeTitleModel;
10+
import com.espacogeek.geek.models.CompanyModel;
11+
import com.espacogeek.geek.models.ExternalReferenceModel;
12+
import com.espacogeek.geek.models.GenreModel;
813
import com.espacogeek.geek.models.MediaModel;
14+
import com.espacogeek.geek.models.PeopleModel;
15+
import com.espacogeek.geek.models.SeasonModel;
16+
import com.espacogeek.geek.repositories.AlternativeTitlesRepository;
17+
import com.espacogeek.geek.repositories.ExternalReferenceRepository;
18+
import com.espacogeek.geek.repositories.MediaRepository;
19+
import com.espacogeek.geek.repositories.SeasonRepository;
920
import com.espacogeek.geek.services.MediaService;
1021
import com.espacogeek.geek.types.MediaPage;
1122
import com.espacogeek.geek.utils.MediaUtils;
1223
import com.espacogeek.geek.exception.GenericException;
1324

1425
import graphql.schema.DataFetchingEnvironment;
1526

27+
import java.util.HashSet;
28+
import java.util.List;
29+
import java.util.Map;
30+
import java.util.Set;
31+
import java.util.stream.Collectors;
1632
@Controller
1733
@RequiredArgsConstructor
1834
public class MediaController {
1935
private final MediaService mediaService;
36+
private final SeasonRepository seasonRepository;
37+
private final AlternativeTitlesRepository alternativeTitlesRepository;
38+
@SuppressWarnings("rawtypes")
39+
private final ExternalReferenceRepository externalReferenceRepository;
40+
private final MediaRepository mediaRepository;
2041

2142
/**
2243
* Finds a MediaModel object by its ID.
@@ -125,4 +146,113 @@ public MediaPage getAnime(@Argument(name = "id") Integer id, @Argument(name = "n
125146

126147
return this.mediaService.findAnimeByIdOrName(id, name, MediaUtils.getPageable(dataFetchingEnvironment));
127148
}
149+
150+
/**
151+
* Batch-loads seasons for a list of MediaModel sources, resolving the N+1 problem.
152+
*/
153+
@BatchMapping
154+
public Map<MediaModel, Set<SeasonModel>> season(List<MediaModel> medias) {
155+
Map<Integer, MediaModel> sourceById = medias.stream()
156+
.collect(Collectors.toMap(MediaModel::getId, m -> m));
157+
Map<MediaModel, Set<SeasonModel>> result = medias.stream()
158+
.collect(Collectors.toMap(m -> m, m -> new HashSet<>()));
159+
for (SeasonModel season : seasonRepository.findByMediaIn(medias)) {
160+
MediaModel source = sourceById.get(season.getMedia().getId());
161+
if (source != null) {
162+
result.get(source).add(season);
163+
}
164+
}
165+
return result;
166+
}
167+
168+
/**
169+
* Batch-loads genres for a list of MediaModel sources, resolving the N+1 problem.
170+
*/
171+
@BatchMapping
172+
public Map<MediaModel, Set<GenreModel>> genre(List<MediaModel> medias) {
173+
Map<Integer, MediaModel> sourceById = medias.stream()
174+
.collect(Collectors.toMap(MediaModel::getId, m -> m));
175+
Map<MediaModel, Set<GenreModel>> result = medias.stream()
176+
.collect(Collectors.toMap(m -> m, m -> new HashSet<>()));
177+
for (MediaModel loaded : mediaRepository.findAllWithGenreByMediaIn(medias)) {
178+
MediaModel source = sourceById.get(loaded.getId());
179+
if (source != null && loaded.getGenre() != null) {
180+
result.put(source, loaded.getGenre());
181+
}
182+
}
183+
return result;
184+
}
185+
186+
/**
187+
* Batch-loads companies for a list of MediaModel sources, resolving the N+1 problem.
188+
*/
189+
@BatchMapping
190+
public Map<MediaModel, Set<CompanyModel>> company(List<MediaModel> medias) {
191+
Map<Integer, MediaModel> sourceById = medias.stream()
192+
.collect(Collectors.toMap(MediaModel::getId, m -> m));
193+
Map<MediaModel, Set<CompanyModel>> result = medias.stream()
194+
.collect(Collectors.toMap(m -> m, m -> new HashSet<>()));
195+
for (MediaModel loaded : mediaRepository.findAllWithCompanyByMediaIn(medias)) {
196+
MediaModel source = sourceById.get(loaded.getId());
197+
if (source != null && loaded.getCompany() != null) {
198+
result.put(source, loaded.getCompany());
199+
}
200+
}
201+
return result;
202+
}
203+
204+
/**
205+
* Batch-loads people for a list of MediaModel sources, resolving the N+1 problem.
206+
*/
207+
@BatchMapping
208+
public Map<MediaModel, Set<PeopleModel>> people(List<MediaModel> medias) {
209+
Map<Integer, MediaModel> sourceById = medias.stream()
210+
.collect(Collectors.toMap(MediaModel::getId, m -> m));
211+
Map<MediaModel, Set<PeopleModel>> result = medias.stream()
212+
.collect(Collectors.toMap(m -> m, m -> new HashSet<>()));
213+
for (MediaModel loaded : mediaRepository.findAllWithPeopleByMediaIn(medias)) {
214+
MediaModel source = sourceById.get(loaded.getId());
215+
if (source != null && loaded.getPeople() != null) {
216+
result.put(source, loaded.getPeople());
217+
}
218+
}
219+
return result;
220+
}
221+
222+
/**
223+
* Batch-loads external references for a list of MediaModel sources, resolving the N+1 problem.
224+
*/
225+
@BatchMapping
226+
@SuppressWarnings("unchecked")
227+
public Map<MediaModel, Set<ExternalReferenceModel>> externalReference(List<MediaModel> medias) {
228+
Map<Integer, MediaModel> sourceById = medias.stream()
229+
.collect(Collectors.toMap(MediaModel::getId, m -> m));
230+
Map<MediaModel, Set<ExternalReferenceModel>> result = medias.stream()
231+
.collect(Collectors.toMap(m -> m, m -> new HashSet<>()));
232+
for (ExternalReferenceModel ref : (List<ExternalReferenceModel>) externalReferenceRepository.findAllByMediaIn(medias)) {
233+
MediaModel source = sourceById.get(ref.getMedia().getId());
234+
if (source != null) {
235+
result.get(source).add(ref);
236+
}
237+
}
238+
return result;
239+
}
240+
241+
/**
242+
* Batch-loads alternative titles for a list of MediaModel sources, resolving the N+1 problem.
243+
*/
244+
@BatchMapping
245+
public Map<MediaModel, Set<AlternativeTitleModel>> alternativeTitles(List<MediaModel> medias) {
246+
Map<Integer, MediaModel> sourceById = medias.stream()
247+
.collect(Collectors.toMap(MediaModel::getId, m -> m));
248+
Map<MediaModel, Set<AlternativeTitleModel>> result = medias.stream()
249+
.collect(Collectors.toMap(m -> m, m -> new HashSet<>()));
250+
for (AlternativeTitleModel alt : alternativeTitlesRepository.findByMediaIn(medias)) {
251+
MediaModel source = sourceById.get(alt.getMedia().getId());
252+
if (source != null) {
253+
result.get(source).add(alt);
254+
}
255+
}
256+
return result;
257+
}
128258
}

src/main/java/com/espacogeek/geek/data/api/impl/GamesAndVNsApiImpl.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public MediaModel getDetails(Integer id) {
9595
genresName.add(genre.getName());
9696
});
9797

98-
media.setGenre(genreService.findAllByNames(genresName));
98+
media.setGenre(new java.util.LinkedHashSet<>(genreService.findAllByNames(genresName)));
9999
media.setAbout(result.getSummary());
100100
media.setName(result.getName());
101101

@@ -112,8 +112,8 @@ public MediaModel getDetails(Integer id) {
112112
for (proto.AlternativeName title : result.getAlternativeNamesList()) {
113113
if (!title.getName().isEmpty()) alternativeTitles.add(new AlternativeTitleModel(null, title.getName(), media));
114114
}
115-
media.setAlternativeTitles(alternativeTitles);
116-
media.setExternalReference(new ArrayList<>(List.of(reference)));
115+
media.setAlternativeTitles(new java.util.LinkedHashSet<>(alternativeTitles));
116+
media.setExternalReference(new java.util.LinkedHashSet<>(List.of(reference)));
117117
media.setMediaCategory(category);
118118
}
119119
}
@@ -154,8 +154,8 @@ public List<MediaModel> doSearch(String search, MediaCategoryModel mediaCategory
154154
for (proto.AlternativeName title : result.getGame().getAlternativeNamesList()) {
155155
if (!title.getName().isEmpty()) alternativeTitles.add(new AlternativeTitleModel(null, title.getName(), media));
156156
}
157-
media.setAlternativeTitles(alternativeTitles);
158-
media.setExternalReference(new ArrayList<>(List.of(reference)));
157+
media.setAlternativeTitles(new java.util.LinkedHashSet<>(alternativeTitles));
158+
media.setExternalReference(new java.util.LinkedHashSet<>(List.of(reference)));
159159

160160
media.setMediaCategory(category);
161161

src/main/java/com/espacogeek/geek/data/api/impl/MovieAPIImpl.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,12 @@ public MediaModel getDetails(Integer id) {
9999
movieDb.getPosterPath() == null ? null : ExternalCDN.TMDB.getUrl() + movieDb.getPosterPath(),
100100
movieDb.getBackdropPath() == null ? null : ExternalCDN.TMDB.getUrl() + movieDb.getBackdropPath(),
101101
mediaCategoryService.findById(MediaDataController.MediaType.MOVIE.getId()).get(),
102-
externalReferences,
102+
new java.util.LinkedHashSet<>(externalReferences),
103103
null,
104104
null,
105-
formatGenre(movieDb.getGenres()),
105+
new java.util.LinkedHashSet<>(formatGenre(movieDb.getGenres())),
106106
null,
107-
formatAlternativeTitles(movieDb.getAlternativeTitles().getTitles()),
107+
new java.util.LinkedHashSet<>(formatAlternativeTitles(movieDb.getAlternativeTitles().getTitles())),
108108
null);
109109

110110
return serie;

src/main/java/com/espacogeek/geek/data/api/impl/TvSeriesApiImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,13 @@ public MediaModel getDetails(Integer id) {
105105
rawSerieDetails.getPosterPath() == null ? null : ExternalCDN.TMDB.getUrl() + rawSerieDetails.getPosterPath(),
106106
rawSerieDetails.getBackdropPath() == null ? null : ExternalCDN.TMDB.getUrl() + rawSerieDetails.getBackdropPath(),
107107
mediaCategoryService.findById(MediaDataController.MediaType.SERIE.getId()).get(),
108-
externalReferences,
108+
new java.util.LinkedHashSet<>(externalReferences),
109109
null,
110110
null,
111-
formatGenre(rawSerieDetails.getGenres()),
111+
new java.util.LinkedHashSet<>(formatGenre(rawSerieDetails.getGenres())),
112112
null,
113-
formatAlternativeTitles(rawSerieDetails.getAlternativeTitles().getResults()),
114-
season);
113+
new java.util.LinkedHashSet<>(formatAlternativeTitles(rawSerieDetails.getAlternativeTitles().getResults())),
114+
new java.util.LinkedHashSet<>(season));
115115

116116
return serie;
117117
}

0 commit comments

Comments
 (0)