0

I have CATEGORY, AD and CATEGORY_AD table, typical many to many relationship. Somehow nothing is inserted into CATEGORY_AD table. What am I missing?

In Category.java:

@ManyToMany
@JoinTable(name = "CATEGORY_AD", joinColumns = {
        @JoinColumn(name = "CATEGORY_ID", referencedColumnName = "ID") }, inverseJoinColumns = {
                @JoinColumn(name = "AD_ID", referencedColumnName = "ID") })
private List<Ad> ads;

In Ad.java:

@ManyToMany(mappedBy = "ads")
private List<Category> categories;

In my Service class:

        Category laCat = new Category();
        laCat.setId(categoryId);
        laCat.getAds().add(ad);

        ad.getCategories().add(laCat);
ad = adRepository.saveAndFlush(ad);
topcan5
  • 1,511
  • 8
  • 30
  • 54

3 Answers3

6

You are saving the 'owned' side instead of the 'owning' side.

Every ManyToMany relationship must have an owner, which in your case is Category. You can see that because in Category you have the definition of the @JoinTable in the ads List, and in Ad you refer to that list by @ManyToMany(mappedBy = "ads").

Whenever you save the owning side of the relationship, this will trigger a save on the join table too, but not the other way around. So saving the owned side (Ad) will do nothing on the CATEGORY_ADtable.

You should do something like this:

Category laCat = new Category();
laCat.setId(categoryId);
laCat.getAds().add(ad);
// Next line will insert on CATEGORY and CATEGORY_AD tables
laCat = categoryRepository.saveAndFlush(category);

// We add the category to the ad object to keep both sides in sync
ad.getCategories().add(laCat);

You can see that even if a save on Category triggers a save on the join table, it's still our responsibility manually add the category to the categories Listin the ad object so both sides are in sync, having the same elements. And there's no need to save the ad object already.

David Lizárraga
  • 1,172
  • 10
  • 17
0

Try to save Category object also (before you invoke ad.getCategories().add(laCat);)

Oskar Dajnowicz
  • 1,700
  • 12
  • 16
0

Please use hibernate @Cascade annotations on List<Category> categories;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

 @ManyToMany(mappedBy = "ads")
 @Cascade(value = CascadeType.SAVE_UPDATE)
 private List<Category> categories;

If you prefer using JPA annotations then you can try this:

 @ManyToMany(mappedBy = "ads", cascade = CascadeType.PERSIST)
 @Cascade(value = CascadeType.SAVE_UPDATE)
 private List<Category> categories;

Please check this thread: what is cascading in hibernate

Community
  • 1
  • 1
SyntaX
  • 2,090
  • 17
  • 30