0

I have an entity Movies and an entity Genres in a relationship many to many.

@ManyToMany
@JoinTable(name = "movies_genres", joinColumns = @JoinColumn(name = "movies_id"), inverseJoinColumns = @JoinColumn(name = "genres_id"))
private Set<Genres> genresSet = new HashSet<>();

In a rest controller class, I want to do this:

@GetMapping("/search-movies")
public Iterable<Movies> search(
    @RequestParam(value = "genresSet", required = false) Set<Genres> genresSet,
    @RequestParam(value = "synopsis", required = false) String synopsis,
    @RequestParam(value = "title", required = false) String title,
    @RequestParam(value = "runtime", required = false) Integer runtime
)

I use axios on front-end to send params to the back-end and genresSet is array of objects, for example

[
    { id: 1, name: 'action'},
    { id: 2, name: 'crime'},
    { id: 3, name: 'comedy'}
]

I thought that Spring would automatically convert array of objects into set of genres, but it gives me null.

How to get values of genres in form of a set of values?

To recap, the user enters more than one genre, where each genre is represented as an object, so front-end sends array of genre objects and back-end needs to bind that array to the set of genres, where set of genres is a many to many property of Movie entity.

sninja
  • 401
  • 1
  • 6
  • 14

2 Answers2

0

You can rethink your parameters and change Set<Genres> either to Set<Integer> or Set<String>. Because you need just ids or just names of genres to use them in search query, you don't need to pass the whole Genres object.

@GetMapping("/search-movies")
public Iterable<Movies> search(
    @RequestParam(value = "genresIds", required = false) Set<Long> genresIds,
    // ... other parameters without changes

would accept

"genresIds": [1, 2, 3]

or

@GetMapping("/search-movies")
public Iterable<Movies> search(
    @RequestParam(value = "genresNames", required = false) Set<String> genresNames,
    // ... other parameters without changes

would accept

"genresNames": ['action', 'crime', 'comedy']
naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
  • I like the `Set genresIds` approach. I used this to extract id values from array of objects: `genresIds: genresSet.map(a => a.id)` and I get 1, 2, 3. To avoid null on a back-end, it is vital to put square brackets after genresIds in value parameter, like this: `@RequestParam(value = "genresIds[]", required = false) Set genresIds`. With this, it is a complete answer for me. Thanks @naXa – sninja Mar 25 '18 at 19:14
0

Another way you could accomplish this is to create a wrapper class for the Set. For example:

public class GenresWrapper {
    Set<Genres> genresSet; 
    // ... accessors
}

Then your controller method would look like this:

@GetMapping("/search-movies")
public Iterable<Movies> search(
        @ModelAttribute GenresWrapper genres,
        // ... other parameters
)

Or you could wrap all the request parameters in a single wrapper object.

This answer is based on another SO answer.

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259