jpa - 通过三重联接表在每个 AddressType 的 Person 中定义多个 Address 属性

标签 jpa dictionary jpa-2.0 join

我这里有一个数据库 PERSON -ADDRESS -ADDRESS_TYPE由三重联接表维护的关系 PERSON_ADDRESSPERSON -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

For practical reasons, I'd like to have my Person entity to end up like:

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

这可以通过 JPA 2.0 注释实现吗?

我已阅读Map Key Columns chapter of the JPA wikibook看来我必须使用 @MapKeyJoinColumn ,但我并不完全清楚如何在这种情况下成功使用它。我预计会看到 @JoinColumn示例,但它在 wikibook 的代码片段中不存在。

如果 @MapKeyJoinColumn 无法做到这一点,然后在 @MapKeyClass 的帮助下另一种方法在Map<AddressType, Address>上也欢迎,只要我最终能得到 getHomeAddress()getOfficeAddress()Person实体。

最佳答案

假设您有两个预定义的 AddressType(当可以添加其他类型时),则以下使用 @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);
    }
}

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

关于jpa - 通过三重联接表在每个 AddressType 的 Person 中定义多个 Address 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3850967/

相关文章:

Python dict 像满射多键→值容器

jpa - EclipseLink 和 Oracle DB 出现时区错误

jpa - 使用搜索字符串排序 - JPA

java - App Engine 不创建 local_db.bin

java - hibernate/JPA : Is it possible to Override @Id field?

java - 分离实体和被管理实体

python - 通过 readlines(size) 提高大文件搜索的效率

java - 比较 JPA 查询中的当前日期时间

hibernate - 带有 JPA : default constructor hell 的 Kotlin

C++ 字计数器