Java – establish a two to many relationship in JPA / hibernate
I have the following physical relationship issues The game must have two (only two) team objects "Team" can have many "games"
As far as I can see, this is a two - to - many relationship However, I don't know how to model in JPA For example, I want to do such a thing
@Entity
public class Team extends BaSEObject {
private Long id;
private Set<Game> games;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {return id;}
public void setId(Long id) {this.id = id;}
@OneToMany(mappedBy = "game")
public Set<Game> getGames() {return games;}
public void setGames(Set<Game> games) {this.games = games;}
}
@Entity
public class Game extends BaSEObject {
private Long id;
private Team team1;
private Team team2;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {return id;}
public void setId(Long id) {this.id = id;}
@ HERE IS THE PROBLEM - WHAT ANNOTATION DO I USE?
public Team getTeam1() {return team1;}
public void setTeam1(Team team1) {this.team1 = team1;}
@ HERE IS THE PROBLEM - WHAT ANNOTATION DO I USE?
public Team getTeam2() {return team2;}
public void setTeam2(Team team1) {this.team2 = team2;}
}
However, as you can see, I don't know how to join tables together in terms of annotations Has anyone ever done such a thing? Any ideas, help?
Thank you.
Solution
I want someone to come up with a great solution, but it's a tricky situation. I've never found a way to map well Your choices include:
>Change the way you build relationships For example, you can do this:
@Entity
public class GameMembership {
Team team;
Game game;
int gamePosition; // If tracking Team 1 vs Team 2 matters to you
}
Then the game has a set < gamemembership >, that is, you model it as many to many The game can still have convenient methods to set team 1 and team 2 (business logic forces only two teams, but they have been completed), but they are mapped back to the collection used by hibernate Abandoning a relationship is two-way – choosing a direction (game → team seems most appropriate) only moves the relationship Find a game that the team participates in and then becomes an operation such as your Dao, rather than an operation that the team itself can access:
public class GameDAO {
....
public Collection<Game> gamesForTeam(Team t) {
....
Query q = session.createQuery("FROM Game WHERE team1 = :team OR team2 = :team");
q.setParameter("team",t);
return q.list();
}
}
Or something like that... > continue along your route, but "cheat" at the end of the team The attributes of the game end should be mapped to the normal many to one relationship; Then use mappedby on the team side to represent the control relationship of the game
public class Team {
...
@OneToMany(mappedBy="team1")
private Set<Game> team1Games;
@OneToMany(mappedBy="team2")
private Set<Game> team2Games;
Then provide convenient properties for your API (team1games and team2games are for hibernate only):
@Transient
public Set<Game> getGames() {
Set<Game> allGames = new HashSet<Game>(team1Games);
allGames.addAll(team2Games);
// Or use google-collections Sets.union() for bonus points
return allGames;
}
So your class caller, it is transparent and has two attributes
