Reputation: 591
I am trying to create a many to many relationship. Below is the relationship that I am trying to create:
Heroes table is saving the values normally but no records are written in the Hero_DnDClasses table.
Here are my classes:
Hero.java
@Entity
@Table(name = "HEROES")
public class Hero {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "HERO_ID")
private Long id;
private Short strength;
private Short dexterity;
private Short constitution;
private Short intelligence;
private Short wisdom;
private Short charisma;
private String name;
@ManyToOne
private Race race;
@OneToMany(mappedBy = "hero")
private List<HeroDnDClasses> heroDnDClasses = new ArrayList<>();
public Hero() {
}
public Hero(Short strength, Short dexterity, Short constitution, Short intelligence, Short wisdom, Short charisma, String name, Race race, List<HeroDnDClasses> heroDnDClasses) {
this.strength = strength;
this.dexterity = dexterity;
this.constitution = constitution;
this.intelligence = intelligence;
this.wisdom = wisdom;
this.charisma = charisma;
this.name = name;
this.race = race;
this.heroDnDClasses = heroDnDClasses;
}
public Long getId() {
return id;
}
public Short getStrength() {
return strength;
}
public Short getDexterity() {
return dexterity;
}
public Short getConstitution() {
return constitution;
}
public Short getIntelligence() {
return intelligence;
}
public Short getWisdom() {
return wisdom;
}
public Short getCharisma() {
return charisma;
}
public String getName() {
return name;
}
public Race getRace() {
return race;
}
public List<HeroDnDClasses> getHeroDnDClasses() {
return heroDnDClasses;
}
@Override
public String toString() {
return "Hero{" +
"id=" + id +
", strength=" + strength +
", dexterity=" + dexterity +
", constitution=" + constitution +
", intelligence=" + intelligence +
", wisdom=" + wisdom +
", charisma=" + charisma +
", name='" + name + '\'' +
", race=" + race +
", HeroDnDClasses=" + heroDnDClasses +
'}';
}
public static HeroBuilder builder(){
return new HeroBuilder();
}
public static class HeroBuilder {
private Short strength;
private Short dexterity;
private Short constitution;
private Short intelligence;
private Short wisdom;
private Short charisma;
private String name;
private Race race;
private List<HeroDnDClasses> heroDnDClasses;
public HeroBuilder setStrength(Short strength) {
this.strength = strength;
return this;
}
public HeroBuilder setDexterity(Short dexterity) {
this.dexterity = dexterity;
return this;
}
public HeroBuilder setConstitution(Short constitution) {
this.constitution = constitution;
return this;
}
public HeroBuilder setIntelligence(Short intelligence) {
this.intelligence = intelligence;
return this;
}
public HeroBuilder setWisdom(Short wisdom) {
this.wisdom = wisdom;
return this;
}
public HeroBuilder setCharisma(Short charisma) {
this.charisma = charisma;
return this;
}
public HeroBuilder setName(String name) {
this.name = name;
return this;
}
public HeroBuilder setRace(Race race) {
this.race = race;
return this;
}
public HeroBuilder setHeroDnDClasses(List<HeroDnDClasses> heroDnDClasses) {
this.heroDnDClasses = heroDnDClasses;
return this;
}
public Hero build() {
return new Hero(strength, dexterity, constitution, intelligence, wisdom, charisma, name, race, heroDnDClasses);
}
}
}
HeroDnDClasses.java
@Entity
@Table(name = "HERO_DNDCLASSES")
public class HeroDnDClasses implements Serializable {
@Id
@ManyToOne
@JoinColumn(name = "HERO_ID")
private Hero hero;
@Id
@ManyToOne
@JoinColumn(name = "DNDCLASS_ID")
private DnDClass dnDClass;
private Integer level;
public Hero getHero() {
return hero;
}
public void setHero(Hero hero) {
this.hero = hero;
}
public DnDClass getDnDClass() {
return dnDClass;
}
public void setDnDClass(DnDClass dnDClass) {
this.dnDClass = dnDClass;
}
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
@Override
public String toString() {
return "HeroDnDClasses{" +
"hero=" + hero +
", dnDClass=" + dnDClass +
", level=" + level +
'}';
}
}
HeroService.java
@Service
public class HeroService {
private static final Logger LOGGER = LoggerFactory.getLogger(HeroService.class);
@Autowired
HeroRepository heroRepository;
@Autowired
DnDClassService dnDClassService;
@Autowired
RaceService raceService;
public List<Hero> getAllHeroes(){
return heroRepository.findAll();
}
@Transactional
public void addHero(Hero hero){
DnDClass newDnDClass = dnDClassService.findDnDClassById(hero.getHeroDnDClasses().get(0).getDnDClass().getId());
HeroDnDClasses newHeroDnDClasses = new HeroDnDClasses();
Race newRace = raceService.getRaceById(hero.getRace().getId());
newHeroDnDClasses.setDnDClass(newDnDClass);
newHeroDnDClasses.setLevel(hero.getHeroDnDClasses().get(0).getLevel());
List<HeroDnDClasses> heroDnDClassesList = new ArrayList<>();
heroDnDClassesList.add(newHeroDnDClasses);
Hero newHero = Hero.builder().setName(hero.getName())
.setStrength(hero.getStrength())
.setDexterity(hero.getDexterity())
.setConstitution(hero.getConstitution())
.setIntelligence(hero.getIntelligence())
.setWisdom(hero.getWisdom())
.setCharisma(hero.getCharisma())
.setRace(newRace)
.setHeroDnDClasses(heroDnDClassesList)
.build();
heroRepository.save(newHero);
}
public Hero findHeroById(Long id){
return heroRepository.findById(id);
}
public Hero findHeroByName(String name){
return heroRepository.findByName(name);
}
}
I have followed some tutorials but my code, although it runs, it does not seem to work. Please tell me if you need me to post any other classes. Thanks in advance.
Upvotes: 0
Views: 214
Reputation: 26572
1) Set cascading:
@OneToMany(mappedBy = "hero", cascade = {CascadeType.PERSIST, CascadeTYPE.MERGE})
private List<HeroDnDClasses> heroDnDClasses = new ArrayList<>();
2) You forgot to set the hero reference on the linking entity:
newHeroDnDClasses.setDnDClass(newDnDClass);
newHeroDnDClasses.setLevel(hero.getHeroDnDClasses().get(0).getLevel());
..
Hero newHero = Hero.builder().setName(hero.getName())
..
newHeroDnDClasses.setHero(newHero);
Now having the reference on the both side, the save
operation will cascade to the linking table as well.
Upvotes: 2