Reputation: 922
I have following code (Spring Boot) that works perfectly:
@Getter
@Setter
@ManyToMany(fetch = FetchType.LAZY)
@Column(name = "fight")
@JoinTable(name = "fighter_fight",
joinColumns = {@JoinColumn(name = "fighter_id")},
inverseJoinColumns = {@JoinColumn(name = "fight_id")})
private Set<Fight> fights;
it's creating this table:
I need to have three columns. Two fighter_id
let's say called first_fighter_id
and second_fighter_id
and fight_id
. When I'm trying to add one more line with like this
joinColumns = {@JoinColumn(name = "fighter_id")},
I'm getting an error ("Duplicate attribute joinColumns"). How can I have two columns in a table with the same object (Fighter
in my case)?
Upvotes: 0
Views: 5742
Reputation: 11551
First you should consider whether you are describing the correct schema. If you only have fighter1 and fighter2 then you probably are talking about two ManyToOne
relationships like so:
That should be pretty easy to model. If you think you actually have a ManyToMany
relationship, perhaps for WWE or something, and you want an additional attribute in the relationship then you need a relationship with an attribute, like so:
This is not an uncommon schema requirement and is realized with two ManyToOne
relationships to a new entity, like so:
Simple JPA entities for this require an Embeddable
entity to be used as an EmbeddableId
like so:
@Entity
@Data
public class Fight {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
@Entity
@Data
public class Fighter {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
@Entity
@Data
public class Fights {
@EmbeddedId
private FightsPK id;
@MapsId("fighterId")
@ManyToOne
private Fighter fighter;
@MapsId("fightId")
@ManyToOne
private Fight fight;
private String fId;
}
@Embeddable
@Data
public class FightsPK implements Serializable {
private static final long serialVersionUID = 1L;
private Long fighterId;
private Long fightId;
}
And using it gets a little awkward but is doable:
private void create() {
Fighter f1 = new Fighter();
fighterRepo.save(f1);
Fighter f2 = new Fighter();
fighterRepo.save(f2);
Fight f = new Fight();
fightRepo.save(f);
Fights f1s = new Fights();
f1s.setId(new FightsPK());
f1s.setFighter(f1);
f1s.setFight(f);
f1s.setFId("f1");
fightsRepo.save(f1s);
Fights f2s = new Fights();
f2s.setId(new FightsPK());
f2s.setFighter(f2);
f2s.setFight(f);
f2s.setFId("f2");
fightsRepo.save(f2s);
}
The fId
field is a String so you can put anything in there if, for example, a fight organizer needs to put their own designation in the field. You might want to reconsider whether you need the initially described relationship. With only two fighters you can put additional fields in the Fight
for fighter1 and fighter1 designations.
Upvotes: 2