2010-10-03 13 views
12

Tôi đã ở đây cơ sở dữ liệu với mối quan hệ PERSON - ADDRESS - ADDRESS_TYPE được duy trì bởi bảng nối ba số PERSON_ADDRESS. Mối quan hệ PERSON - ADDRESS có hiệu quả một-nhiều.Xác định nhiều thuộc tính Địa chỉ trong Person trên mỗi AddressType bằng bảng kết hợp ba

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 

Vì những lý do thực tế, tôi muốn có thực thể Person của tôi kết thúc như:

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

Đây có phải là bao giờ có thể với chú thích JPA 2.0?

Tôi đã đọc Map Key Columns chapter of the JPA wikibook và có vẻ như tôi phải sử dụng @MapKeyJoinColumn, nhưng không hoàn toàn rõ ràng đối với tôi cách sử dụng thành công trong tình huống này. Tôi mong đợi để xem một ví dụ @JoinColumn dọc theo nó, nhưng nó vắng mặt trong đoạn mã trong wikibook.

Nếu đó là không thể với @MapKeyJoinColumn, sau đó là một cách tiếp cận khác với sự giúp đỡ của lẽ @MapKeyClass trên Map<AddressType, Address> là cũng hoan nghênh, miễn là tôi có thể kết thúc với một getHomeAddress()getOfficeAddress() trong thực thể Person.

+0

Bạn có đang sử dụng enum cho ADDRESS_TYPE không? Bởi vì điều đó có ý nghĩa, vì bạn muốn các loại địa chỉ cố định biên dịch. – Bozho

+0

@Bozho: Tôi chưa triển khai đầy đủ, nhưng nếu có thể, sử dụng '@ Enumerated' chắc chắn sẽ có sở thích của tôi, vâng. – BalusC

+0

aha. Và nhà cung cấp kiên trì của bạn là gì? (Chú thích dành riêng cho nhà cung cấp được phép là phương sách cuối cùng, tôi đoán) – Bozho

Trả lời

11

Giả sử rằng bạn có hai được xác định trước AddressType s khi khác có thể được thêm vào, cách tiếp cận sau đây với @MapKeyJoinColumn công trình:

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

phương pháp Vì vậy, bạn đã xác định trước với nhiều loại địa chỉ được xác định trước, khi các loại khác có thể được sử dụng thông qua truy cập trực tiếp vào bản đồ. orphanRemoval được sử dụng để thực hiện hành vi setHomeAddress(null). @ElementCollection sẽ không hoạt động ở đây vì nó không hỗ trợ bảng tham gia.

+0

Oh boy, nó hoạt động :) Cảm ơn bạn rất nhiều. Lúc đó tôi cũng không thích, nhưng tôi đã có '' JoinTable' hoàn toàn sai. Nó cũng có ý nghĩa hơn bây giờ. Tuy nhiên, tôi tò mò nếu nó cũng có thể với một 'địa chỉ enum'. – BalusC

+0

rất tốt, +1 :) – Bozho

+0

@BalusC: Tôi nghĩ bạn không thể sử dụng 'enum' trừ khi bạn thay đổi lược đồ DB của mình. Bạn có thể sử dụng 'enum' hoặc thực thể được ánh xạ tới bảng' ADDRESS_TYPE'. – axtavt

Các vấn đề liên quan