La définition de plusieurs propriétés en personne par adresse AddressType par une triple table de jointure
Question
Je l'ai ici une base de données avec un PERSON
- ADDRESS
- relation ADDRESS_TYPE
maintenue par une triple table de jointure PERSON_ADDRESS
. La relation PERSON
-ADDRESS
est effectivement l'un à plusieurs.
PERSON
ID FIRSTNAME LASTNAME -- --------- -------- 1 John Doe 2 Jane Doe
ADDRESS
ID STREET CITY -- -------------------- ------------- 1 Home Street 1 Hometown 2 Office Street 1 Officetown 3 Main Street 1 Maintown 4 Business Building 1 Businesstown
ADDRESS_TYPE
ID NAME -- --------------- 1 Home Address 2 Office Address
PERSON_ADDRESS
PERSON_ID ADDRESS_TYPE_ID ADDRESS_ID --------- --------------- ---------- 1 1 1 1 2 2 2 1 3 2 2 4
Pour des raisons pratiques, j'aimerais avoir mon entité Person
finir comme:
public class Person {
private Address homeAddress; // Insertable/updateable by ADDRESS_TYPE_ID=1
private Address officeAddress; // Insertable/updateable by ADDRESS_TYPE_ID=2
}
Est-ce toujours possible avec annotations JPA 2.0?
J'ai lu Carte Colonnes clés chapitre de l'Assemblée parlementaire paritaire wikilivre et il semble que je dois utiliser un @MapKeyJoinColumn
, mais il est pas tout à fait clair pour moi comment utiliser avec succès dans cette situation. Je pensais voir un exemple @JoinColumn
le long, mais il est absent dans les extraits de code dans le wikilivre.
Si cela est impossible avec @MapKeyJoinColumn
, puis une autre approche avec l'aide de peut-être @MapKeyClass
sur Map<AddressType, Address>
est également la bienvenue, aussi longtemps que je peux retrouver avec un getHomeAddress()
et getOfficeAddress()
dans l'entité Person
.
La solution
En supposant que vous avez deux AddressType
s prédéfinis quand d'autres peuvent être ajoutés, l'approche suivante avec @MapKeyJoinColumn
fonctionne:
public class AddressType {
public static final AddressType HOME = new AddressType(1L, "Home");
public static final AddressType OFFICE = new AddressType(2L, "Office");
...
... hashCode, equals based on id ...
}
public class Person {
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinTable(name = "PERSON_ADDRESS",
joinColumns = @JoinColumn(name = "PERSON_ID"),
inverseJoinColumns = @JoinColumn(name = "ADDRESS_ID"))
@MapKeyJoinColumn(name = "ADDRESS_TYPE_ID")
private Map<AddressType, Address> addresses = new HashMap<AddressType, Address>();
...
public Address getHomeAddress() {
return getAddress(AddressType.HOME);
}
public void setHomeAddress(Address a) {
setAddress(AddressType.HOME, a);
}
...
public void setAddress(AddressType type, Address a) {
if (a == null) {
addresses.remove(type);
} else {
addresses.put(type, a);
}
}
public Address getAddress(AddressType type) {
return addresses.get(type);
}
}
Ainsi, vous avez des méthodes prédéfinies pour les types d'adresses prédéfinies, alors que d'autres types peuvent être utilisés par un accès direct à la carte. orphanRemoval
est utilisé pour mettre en œuvre le comportement de setHomeAddress(null)
. @ElementCollection
ne fonctionnerait pas ici car il ne supporte pas se joindre à la table.