Quantcast
Channel: Active questions tagged rest - Stack Overflow
Viewing all articles
Browse latest Browse all 4782

Rest API POST/PATCH/DELETE for an intermediate entity in Spring

$
0
0

right now I am working on a java project with Spring, but I got really confused about something. In my domain I have the following three entities.
Museum, MuseumReview and Visitor.

A visitor can review multiple museums but can only review a museum once.

A museum can be reviewed by multiple visitors.

The classes:

@Entity @Table(name = "museums") public class Museum { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Integer id;@Column(name = "name", nullable = false, unique = true)private String name;@Column(name = "location", nullable = false)private String location;@Column(name = "date_established", nullable = false)private LocalDate dateEstablished;@Column(name = "status", nullable = false)@Enumerated(EnumType.STRING)private MuseumStatus status;@OneToMany(mappedBy = "museum")private List<MuseumReview> reviews;@OneToMany(mappedBy = "museum", fetch = FetchType.EAGER)private List<Fossil> fossils;// Getters and Setters}   // class Museum@Entity @Table(name = "museum_review", uniqueConstraints = {@UniqueConstraint(columnNames = {"museum_id", "visitor_id"})}) public class MuseumReview { @Id@GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Integer id;@ManyToOne(optional = false)@JoinColumn(name = "museum_id")@OnDelete(action = OnDeleteAction.CASCADE)private Museum museum;@ManyToOne(optional = false)@JoinColumn(name = "visitor_id")@OnDelete(action = OnDeleteAction.CASCADE)private Visitor visitor;@Column(name = "review_date", nullable = false)private LocalDate reviewDate;@Column(name = "star_rating")private int starRating;@Column(name = "content")private String content;// Getters and Setters}   // class MuseumReview@Entity@Table(name = "visitors") public class Visitor {@Id@GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Integer id;@Column(name = "name", nullable = false)private String name;@Column(name = "email")private String email;@Column(name = "password")private String password;@Column(name = "role", nullable = false)@Enumerated(EnumType.STRING)private Role role;@OneToMany(mappedBy = "visitor")private List<MuseumReview> reviews;public Visitor() {}public Visitor(int id, String name, String email, String password) {    this.id = id;    this.name = name;    this.email = email;    this.password = password;    this.role = Role.VISITOR;}// Getters and setters}   // class Visitor

The Role enum:

public enum Role {VISITOR,ADMIN}   // enum Role

Currently I have an Rest controller for Museum as follows:

@RestController@RequestMapping("/api/museums")public class MuseumApiController { private final MuseumService museumService;private final ModelMapper modelMapper;public MuseumApiController(MuseumService museumService, ModelMapper modelMapper) {    this.museumService = museumService;    this.modelMapper = modelMapper;}@GetMapping("/{id}")public ResponseEntity<MuseumDto> getMuseum(@PathVariable("id") int id) {    final Museum museum = museumService.getById(id);    return ResponseEntity.ok(modelMapper.map(museum, MuseumDto.class));}@GetMappingpublic ResponseEntity<List<MuseumDto>> getAllMuseums() {    final List<Museum> museums = museumService.getAllWithReviewers();    if (museums.isEmpty()) {        return new ResponseEntity<>(HttpStatus.NO_CONTENT);    } else {        return ResponseEntity.ok(museums.stream().map(museum -> modelMapper.map(museum, MuseumDto.class)).toList());    }}@GetMapping("/search")public ResponseEntity<List<MuseumDto>> searchMuseums(@RequestParam("searchTerm") String searchTerm) {    final List<Museum> museums = museumService.search(searchTerm);    return ResponseEntity.ok(museums.stream().map(museum -> modelMapper.map(museum, MuseumDto.class)).toList());}@GetMapping("/{id}/reviewers")public ResponseEntity<List<VisitorDto>> getMuseumReviewers(@PathVariable("id") int id) {    final List<Visitor> reviewedVisitors = museumService.getReviewedVisitors(id);    final List<VisitorDto> reviewedVisitorDtos = reviewedVisitors            .stream()            .map(visitor -> modelMapper.map(visitor, VisitorDto.class))            .toList();    return ResponseEntity.ok(reviewedVisitorDtos);}@DeleteMapping("/{id}")@PreAuthorize("hasRole('ROLE_ADMIN')")public ResponseEntity<Void> deleteMuseum(@PathVariable("id") int id) {    museumService.delete(id);    return ResponseEntity.noContent().build();}@PostMapping@PreAuthorize("hasRole('ROLE_ADMIN')")public ResponseEntity<MuseumDto> addMuseum(@RequestBody @Valid AddMuseumDto addMuseumDto) {    final Museum addedMuseum = museumService.add(addMuseumDto.name(), addMuseumDto.location(), addMuseumDto.dateEstablished());    return ResponseEntity.status(HttpStatus.CREATED).body(modelMapper.map(addedMuseum, MuseumDto.class));}@PatchMapping("/{id}")@PreAuthorize("hasRole('ROLE_ADMIN')")public ResponseEntity<MuseumDto> patchMuseum(        @PathVariable("id") int id,        @RequestBody @Valid PatchMuseumDto patchMuseumDto) {    final Museum patchedMuseum = museumService.patch(            id,            patchMuseumDto.name(),            patchMuseumDto.location(),            patchMuseumDto.dateEstablished(),            patchMuseumDto.status()    );    return ResponseEntity.ok(modelMapper.map(patchedMuseum, MuseumDto.class));}}   // class MuseumApiController

However I also want the visitors to be able to add, remove and update their museum review written for a specific museum. How could I achieve this? I want to be able to specify the star rating and the review content when creating the reviews.

I currently have the following dto which I want to use:

public class ReviewDto {@Min(1)@Max(5)private Integer starRating;@Size(min = 3, max = 300)private String content;// Getters and Setters}   // class ReviewDto

Should I use a separate MuseumReviewApiController and a MuseumReviewService for this and if so what should my methods in the MuseumReviewService class look like to achieve this? Would be very happy if anyone could help me on this.

I tried to handle things in the MuseumApiController, but things got really confusing for me and basically I got stuck.


Viewing all articles
Browse latest Browse all 4782

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>