JPA + Hibernate + ManyToMany problème @MapKey
Bonjour à tous !
En lisant le livre d'Anthony PATRICIO : Java Persistence et Hibernate, je suis tombé sur une gestion d'une association ManyToMany qui correspond à mon besoin, c'est à dire :
- avec des champs supplémentaires dans la table d'association.
- l'association entre la table mère et la table d'association est une composition.
La voici l'exemple du livre :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
|
[Coach]<> ----> *[Season]* ----> [Team]
// Coach.java
@Entity
public class Coach {
@Id
@GeneratedValue
private int id;
@ManyToMany
@MapKey
private Map<Season,Team> teams = new HashMap<Season,Team>();
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map<Season, Team> getTeams() {
return teams;
}
public void setTeams(Map<Season, Team> teams) {
this.teams = teams;
}
}
// Season.java
@Embeddable
public class Season {
private Date startDate;
private Date endDate;
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
}
// Team.java
@Entity
public class Team {
@Id
@GeneratedValue
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
} |
L'exemple du livre (extrait du code source ci-dessus ou téléchargeable ici http://www.editions-eyrolles.com/Liv...e-et-hibernate) est un projet Eclipse avec Embedded JBoss.
Cette exemple fonctionne parfaitement dans cet environnement.
Mais dans les environnements suivants :
- JBoss AS 5.0.1 et EJB3 (en mode TransactionManagementType.BEAN ou TransactionManagementType.CONTAINER)
- Spring pour la l'injection de dépendance et la gestion des transactions
Au moment ou j'appel la fonction getKey() (dans la transaction) de la propriété "private Map<Season,Team> teams" :
Code:
1 2 3 4 5 6 7 8
|
[...]
for (Entry<Season, Team> entry : coach.getTeams().entrySet()) {
System.out.println(entry.getValue().getName());
System.out.println(entry.getKey().getStartDate());
System.out.println(entry.getKey().getEndDate());
}
[...] |
j'ai l'erreur suivante :
Code:
1 2
|
java.lang.ClassCastException: java.lang.Long cannot be cast to com.et.Season |
Si quelqu'un comprend le problème...
Merci.
Nassa.
JPA + Hibernate + ManyToMany problème @MapKey
Bonjour à tous !
J'ai finalement réglé mon problème.
En fait, l'annotation @MapKey décrite dans le livre d'Anthony PATRICIO est celle d'Hibernate alors que j'utilise celle de JPA 2 ! Une erreur de débutant !
Cette annotation Hibernate est aujourd'hui dépréciée, et est remplacée par l'annotation @MapKeyColumn dans JPA 2.
Tout fonctionne correctement maintenant.
D'autre part comme la table Season est la clé dans la Map, j'ai du redéfinir les fonctions equals() et hash().
J'ai aussi ajouté le champs "private int teamKey;" dans la table Season que fonctions equals() et hash() prennent en compte.
Pour réinitialiser ce champs j'ai ajouté addTeam() dnas la classe Coach :
Code:
1 2 3 4 5 6 7 8 9
|
public void addTeam(Date startDate, Date endDate, Team team) {
Season season = new Season();
season.setStartDate(startDate);
season.setEndDate(endDate);
season.setTeamKey(team.getId());
teams.put(season, team);
} |
De cette manière je peut avoir plusieurs Season de même date pour le même Coach. Ça peut paraître idiot dans cet exemple mais dans mon cas d'utilisation ça a tout son sens.
Merci.
Alexandre.