通过三重连接表在Person/AddressType中定义多个Address属性

Bal*_*usC 12 jpa map jointable jpa-2.0

我在这里有一个数据库,其中PERSON- ADDRESS- ADDRESS_TYPE关系由三联接表维护PERSON_ADDRESS.本PERSON- ADDRESS关系实际上是一个一对多的.

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

出于实际原因,我想让我的Person实体最终如下:

public class Person {
    private Address homeAddress; // Insertable/updateable by ADDRESS_TYPE_ID=1
    private Address officeAddress; // Insertable/updateable by ADDRESS_TYPE_ID=2
}
Run Code Online (Sandbox Code Playgroud)

JPA 2.0注释是否可以实现这一点?

我已经阅读了JPA wikibookMap Key Columns章节,似乎我必须使用a @MapKeyJoinColumn,但我并不完全清楚如何在这种情况下成功使用它.我希望看到@JoinColumn它的一个例子,但它在wikibook的代码片段中不存在.

如果这是不可能的@MapKeyJoinColumn,然后用也许帮助的另一种方法@MapKeyClassMap<AddressType, Address>也是值得欢迎的,只要我可以用一个结束getHomeAddress()getOfficeAddress()Person实体.

axt*_*avt 11

假设您AddressType可以添加其他两个预定义的s,以下方法@MapKeyJoinColumn有效:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,您可以通过直接访问地图来使用其他类型的预定义地址类型的预定义方法.orphanRemoval用于实现setHomeAddress(null)行为.@ElementCollection不会在这里工作,因为它不支持连接表.