I have the following entity relationship problem. A "Game" must have two (and only two) "Team" objects. A "Team" can have many "Games"
This, as far as I can see is a Two-to-Many relationship. However...I don't know how to model this in JPA. Eg, I was going to do something like this...
@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;}
}
But, as you can see, I'm not sure how to link the tables together from an annotation side. Has anyone ever done something like this before? Any ideas, help?
thanks very much!
I would love for someone to come up with an awesome solution to this, but it's a tricky situation which I've never been able to find a way to map very well. Your options include:
Change the way you model the relationship. For example, you could have something like:
@Entity
public class GameMembership {
Team team;
Game game;
int gamePosition; // If tracking Team 1 vs Team 2 matters to you
}
and then Game
has a Collection<GameMembership>
, i.e. you model it as many-to-many. Game
can still have convenient methods for setting Team 1 and Team 2, etc, (business logic to enforce that there are only 2 Teams, however that's done) but they map back onto the Collection
as used by Hibernate.
Give up on having the relationship be bidirectional -- pick one direction (Game
→ Team
seems the most appropriate) and nap only that relationship. Finding the Games
a Team
is involved in then becomes an operation from your DAO etc, rather than something that's accessible from the Team
itself:
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 similar...
Continue along the route you're taking, but 'cheat' at the Team
end. The properties at the Game
side should be mapped as normal many-to-one relationships; then used mappedBy
at the Team
end to indicate that Game
'controls` the relationship.
public class Team {
...
@OneToMany(mappedBy="team1")
private Set<Game> team1Games;
@OneToMany(mappedBy="team2")
private Set<Game> team2Games;
and then have a convenience property for your API (team1Games
and team2Games
are just for Hibernate's use):
@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 to callers of your class, it's transparent that there are 2 properties.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With