2010-10-03 9 views
12

Burada bir veritabanı bir PERSON_ADDRESS üçlü birleştirme tablosu tarafından sürdürülen bir PERSON - - ADDRESS_TYPE ilişkisine sahip bir veritabanı var. PERSON - ADDRESS ilişkisi etkili bire çoktur.Üçlü birleştirme tablosu tarafından AddressType başına Kişi'de birden çok Adres özelliğini tanımlama

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

Bu JPA 2.0 ek açıklamalarla hiç mümkün mü

public class Person { 
    private Address homeAddress; // Insertable/updateable by ADDRESS_TYPE_ID=1 
    private Address officeAddress; // Insertable/updateable by ADDRESS_TYPE_ID=2 
} 

: Pratik nedenlerden dolayı

, ben gibi olmak benim Person varlık olmasını istiyorum?

Map Key Columns chapter of the JPA wikibook'u okudum ve @MapKeyJoinColumn kullanmam gerekiyor gibi görünüyor, ancak bu durumda başarılı bir şekilde nasıl kullanacağımı tamamen açık değil. Onunla birlikte bir @JoinColumn örneğini görmeyi bekledim, ancak wikibook'daki kod parçacıklarında yok.

o @MapKeyJoinColumn ile mümkün değilse, o zaman belki @MapKeyClass bir Map<AddressType, Address> üzerinde yardımıyla alternatif yaklaşım aynı zamanda sürece ben Person varlıktaki bir getHomeAddress() ve getOfficeAddress() ile sona erebilir gibi açığız. Önceden tanımlanmış adres türleri için

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); 
    } 
} 

Yani, önceden tanımlanmış olan yöntemlere, diğer türleri aracılığıyla kullanılabilir:

+0

ADDRESS_TYPE için bir numara kullanıyor musunuz? Çünkü derleme zamanı sabit adres türleri istediğiniz için bu mantıklı olur. – Bozho

+0

@Bozho: Henüz tam olarak uygulamamışım, ancak eğer mümkün ise, bir '@ Numaralı’ kullanmak benim tercihimi kesinlikle kullanırdı, evet. – BalusC

+0

aha. Ve kalıcılık sağlayıcınız nedir? (Sağlayıcıya özel ek açıklamalar son çare olarak kabul edilir, sanırım) – Bozho

cevap

11

diğer @MapKeyJoinColumn eserlerle, aşağıdaki yaklaşım eklenebilir zaman önceden tanımlanmış iki AddressType s olduğunu varsayarsak haritaya doğrudan erişim. orphanRemoval, setHomeAddress(null) davranışını uygulamak için kullanılır. Birleştirme masasını desteklemediği için @ElementCollection burada çalışmaz.

+0

Oh oğlum, işe yarıyor :) Çok teşekkür ederim. Bu arada ben de çok uğraştım, ama 'JoinTable'ı tamamen yanlış ettim. Şimdi daha da mantıklı. Yine de bir "enum AddressType" ile mümkün olup olmadığını merak ediyorum. – BalusC

+0

Çok iyi, +1 :) – Bozho

+0

@BalusC: DB şemanızı değiştirmedikçe 'numara 'kullanamazsınız. "Enum" veya "ADDRESS_TYPE" tablosuna eşlenen varlıkları kullanabilirsiniz. – axtavt