Home > Software engineering >  Spring boot JPA persist manytomany unidirectionnal relationship
Spring boot JPA persist manytomany unidirectionnal relationship

Time:11-11

I have a Spring Boot project (with JHipster) with 2 JPA Entities : User and Film.

I've created an unidirectionnal ManyToMany relationship between them. User is the owner of the relationship.

I would like to add films into favorite list of films of user (property 'favorites' in User entity).

But when I try to add a film into favorites list, nothing is persisted into table 'user_film_favorite' (join table between the 2 entities).

The mapping seems ok because when I manually enter data in this join table, I'm able to retrieve the list of films for a user.

I've looked for a lot of similar issues here but can't find where the problem is.

Entity User :

@Entity
@Table(name = "jhi_user")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class User extends AbstractAuditingEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // Other properties

    @ManyToMany(cascade = CascadeType.PERSIST)
    @JoinTable(
        name = "user_film_favorite",
        joinColumns = { @JoinColumn(name = "user_id", referencedColumnName = "id") },
        inverseJoinColumns = { @JoinColumn(name = "movie_id", referencedColumnName = "id") }
    )
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    @BatchSize(size = 20)
    private List<Film> favorites = new ArrayList<>();

Entity Film :

@Entity
@Table(name = "film")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Film implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @NotNull
    @Column(name = "title", nullable = false)
    private String title;

    @Column(name = "plot")
    private String plot;

    @Column(name = "rating")
    private Float rating;

FilmService :

   /**
     * Add one film to current user favorites.
     *
     * @param id the id of the film.
     * @return the film saved into user favorites.
     */
    @Transactional(readOnly = true)
    public Optional<FilmDTO> addToFavorites(Long id) {
        log.debug("Request to get Film : {}", id);
        Optional<Film> filmOpt = filmRepository.findById(id);
        // Get current logged user with his favorites
        Optional<User> userOpt = userService.getUserWithFavorites();
        if (filmOpt.isPresent() && userOpt.isPresent()) {
            User user = userOpt.get();
            user.getFavorites().add(filmOpt.get());
            userService.save(user); 
        }
        return filmOpt.map(filmMapper::toDto);
    }

UserService :

    /**
     * Save a user.
     *
     * @param user the entity to save.
     * @return the persisted entity.
     */
    public User save(User user) {
        log.debug("Request to save User : {}", user);
        return userRepository.save(user);
    }

If anyone could help me that would be really cool ! Thanks in advance :)

CodePudding user response:

You are reading the User from the database so calling save will call EntityManger.merge. Therefor you also need to add

CascadeType.MERGE

to the ManyToMany mapping.

  • Related