T
Hi!
There is a problem with GET method’s response.
-
API – GET /api/v1.0/vivre/feedbackPerBarcode/{id} – returns all matched reviews from db.
-
Controller code
@RestController
@AllArgsConstructor
@Tag(name = "vivre_family")
public class PersonController implements VivreFamilyApi {
private final GettingFeedbackService gettingFeedbackService;
@Override
public ResponseEntity<List<FeedbackPerBarcodeResponse>> feedbackPerBarcodeV1(Long id) {
var feedbackPerBarcodeResponse = gettingFeedbackService.feedbackPerBarcodeV1(id);
return ResponseEntity.ok(feedbackPerBarcodeResponse);
}
}
- Interface code
public interface GettingFeedbackService {
List<FeedbackPerBarcodeResponse> feedbackPerBarcodeV1(Long id);
}
- Service impl code
@Override
@Transactional
public List<FeedbackPerBarcodeResponse> feedbackPerBarcodeV1(Long id) {
List<Mp> findAllByBarcode = mpRepository.findAllByBarcode(id);
if (findAllByBarcode.isEmpty()) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, ApiErrorQ.DataNotFound.getErrorMessage());
}
List<FeedbackPerBarcodeResponse> feedbackPerBarcodeResponses = new ArrayList<FeedbackPerBarcodeResponse>();
if (findAllByBarcode.stream().anyMatch(mp -> mp.getId()==1)){ // IReccomend
FeedbackPerBarcodeResponse feedbackPerBarcodeResponse = feedbackPerBarcodeResponseMapper(1, findAllByBarcode);
feedbackPerBarcodeResponses.add(feedbackPerBarcodeResponse);
}
.........
.........
if (findAllByBarcode.stream().anyMatch(mp -> mp.getId()==9)){ // Revivre
FeedbackPerBarcodeResponse feedbackPerBarcodeResponse = feedbackPerBarcodeResponseMapper(9, findAllByBarcode);
feedbackPerBarcodeResponses.add(feedbackPerBarcodeResponse);
}
return feedbackPerBarcodeResponses;
}
}
- findAllByBarcode – repository method. This ones should find in db all feedback with certain id (long). BUT this method come back some random coincidence in DB. This is a main problem.
public interface MpRepository extends JpaRepository<Mp,Integer> {
@Query("""
select m from Mp m left join m.mpProductFeedbacks mpProductFeedbacks
where mpProductFeedbacks.productVivreBarcodeId = ?1""")
List<Mp> findAllByBarcode(Long productVivreBarcodeId);
}
- feedbackPerBarcodeResponseMapper – method. Multidimentional search in db.
public class FeedbackPerBarcodeMapper {
public static FeedbackPerBarcodeResponse feedbackPerBarcodeResponseMapper(Integer mpId, List<Mp> findAllByBarcode){
FeedbackPerBarcodeResponse feedbackPerBarcodeResponse = new FeedbackPerBarcodeResponse();
List<PicturesFromFeedback> pictures = new ArrayList<>();
feedbackPerBarcodeResponse.setWebsourse(findAllByBarcode // websourse
.stream().filter(s -> s.getId().equals(mpId)).iterator().next().getWebSourceName());
feedbackPerBarcodeResponse.setAvgScore(findAllByBarcode // avgScore
.stream().filter(s->s.getId().equals(mpId)).iterator().next()
.getMpProductFeedbacks().stream().iterator().next().getAvgScore());
feedbackPerBarcodeResponse.setAvgSum(findAllByBarcode // avgSum
.stream().filter(s->s.getId().equals(mpId)).iterator().next()
.getMpProductFeedbacks().stream().iterator().next().getAvgSum());
long mpProductFeedbackId = findAllByBarcode.stream().filter(s->s.getId().equals(mpId))
.iterator().next()
.getMpProductFeedbacks()
.stream().iterator().next().getId();
List<PicturesFromFeedback> picturesFromFeedbacks = findAllByBarcode
.stream()
.map(Mp::getMpProductFeedbacks)
.flatMap( Collection::stream )
.filter( feedback -> feedback.getId() == mpProductFeedbackId )
.map(MpProductFeedback::getMpPersonScores)
.flatMap( Collection::stream )
.map(MpPersonScore::getPersonLinkPhotos)
.flatMap(Collection::stream)
.map(personLinkPhoto -> {
PicturesFromFeedback picturesFromFeedback = new PicturesFromFeedback();
picturesFromFeedback.setPicture(personLinkPhoto.getLink());
picturesFromFeedback.setMpPersonScoreId(personLinkPhoto.getMpPersonScoreId());
return picturesFromFeedback;
})
.toList();
List<ScoreType> scores = findAllByBarcode
.stream()
.map(Mp::getMpProductFeedbacks)
.flatMap( Collection::stream )
.filter( feedback -> feedback.getId() == mpProductFeedbackId )
.map(MpProductFeedback::getMpPersonScores)
.flatMap( Collection::stream )
.map( personScore -> {
ScoreType score = new ScoreType();
score.setUserScore( personScore.getMpPersonScore() );
score.setUser( personScore.getMpPersonLogin() );
score.setUserComment( personScore.getMpPersonComment() );
score.setPictures(picturesFromFeedbacks
.stream()
.filter(picturesFromFeedback -> picturesFromFeedback
.getMpPersonScoreId()
.equals(personScore.getId()))
.collect(Collectors.toList()));
// need to add in score - List<@Valid PicturesFromFeedback> pictures , ScoreType -> pictures oneToMany
// findAllByBarcode is nested Collection
return score;
})
.toList();
feedbackPerBarcodeResponse.setScore(scores);
return feedbackPerBarcodeResponse;
}
}
- Classes of models and relations between them.
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "mp")
public class Mp {
// ссылка на схему бд
// https://dbdiagram.io/d/vivre-family-psql-db-65b61167ac844320aede86a7
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "web_source_name")
private String webSourceName;
@Column(name = "web_source_link")
private String webSourceLink;
@OneToMany(mappedBy = "mpId", fetch = FetchType.LAZY)
private List<MpProductFeedback> mpProductFeedbacks;
}
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "mp_product_feedback")
public class MpProductFeedback {
// ссылка на схему бд
// https://dbdiagram.io/d/vivre-family-psql-db-65b61167ac844320aede86a7
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "product_vivre_id")
private String productVivreId;
@Column(name = "product_vivre_barcode_id")
private Long productVivreBarcodeId;
@Column(name = "mp_id")
private Integer mpId;
@Column(name = "avg_score")
private BigDecimal avgScore;
@Column(name = "avg_sum")
private BigDecimal avgSum;
@OneToMany(mappedBy = "mpProductFeedbackId", fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
private List<MpPersonScore> mpPersonScores;
@Column(name = "created_at", updatable = false)
private LocalDateTime createdAt;
@Column(name = "modified_at", updatable = false)
private LocalDateTime modifiedAt;
@PrePersist
public void prePersist(){
this.createdAt = LocalDateTime.now();
this.modifiedAt = createdAt;
}
@PreUpdate
public void preUpdate(){
this.modifiedAt = LocalDateTime.now();
}
}
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "mp_person_score")
public class MpPersonScore {
// ссылка на схему бд
// https://dbdiagram.io/d/vivre-family-psql-db-65b61167ac844320aede86a7
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "product_vivre_id")
private String productVivreId; // пока непойму зачем мне это поле
@Column(name = "product_vivre_barcode_id")
private Long productVivreBarcodeId;
@Column(name = "mp_id")
private Integer mpId;
@Column(name = "mp_product_feedback_id")
private Long mpProductFeedbackId;
@Column(name = "mp_person_login")
private String mpPersonLogin;
@Column(name = "mp_person_score")
private Integer mpPersonScore;
@Column(name = "mp_person_comment")
private String mpPersonComment;
@OneToMany(mappedBy = "mpPersonScoreId", fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
private List<PersonLinkPhoto> personLinkPhotos;
@Column(name = "created_at", updatable = false)
private LocalDateTime createdAt;
@Column(name = "modified_at", updatable = false)
private LocalDateTime modifiedAt;
@PrePersist
public void prePersist(){
this.createdAt = LocalDateTime.now();
this.modifiedAt = createdAt;
}
@PreUpdate
public void preUpdate(){
this.modifiedAt = LocalDateTime.now();
}
}
Question – How to search a particular data in db? May i should use sql syntax in string value?
Now response looks like i using ‘like’ query.
But it should be ‘where’ or query (particular).
Use case – if i put 12345 in path of GET method -> i need to get feedbacks with id=12345, not 123456 or 1234567 etc.
Real example of response with id = 123456789123:
{
"websourse": "Revivre",
"avgScore": null,
"avgSum": null,
"score": [
{
"user": "loginFromMp2",
"userScore": 5,
"userComment": "Good",
"pictures": []
}
]
}
BUT – this one has id = 123456789111
id in query type = long
id in DB bigint.
2