JPA - 带有JoinTable的@OneToMany

时间:2013-07-17 19:51:03

标签: java jpa jointable persist

我希望我能在第一次尝试中清楚地解释这一点。所以我有两个实体:Person和Address。一个人可以拥有多个地址,因此我的Person实体由地址列表组成。请注意,地址可以在不同的人之间共享,但是我的地址实体不需要对Person实体的引用。此外,每个地址实体都将具有 rank 属性。

我的表格结构如下:

PERSON (
  person_id,
  etc,
  primary key (person_id)
)

ADDRESS (
  address_id,
  etc,
  primary key (address_id)
)

PERSON_ADDRESS_MAP (
  person_id,
  address_id,
  rank,
  foreign key (person_id) references person (person_id),
  foreign key (address_id) references address (address_id),
  primary key (person_id, address_id, rank)
)

鉴于上述情况,我不确定如何在Person中注释我的地址列表,或者在Address中注释rank属性。我怀疑这个人看起来如下:

@Entity
public class Person {
  @OneToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
  @JoinTable(name="person_address_map", joinColumns=@JoinColumn(name="person_id"), inverseJoinColumns=@JoinColumn(name="address_id") )
  private List<Address> addresses;
  ...
}

我对如何在地址实体中注释 rank 一无所知。

提前致谢

1 个答案:

答案 0 :(得分:1)

首先,Person和Address之间的逻辑关联是多对多的,因为一个人有很多地址,并且很多人共享一个地址。

你说,等级是地址的属性。但对于给定的地址,等级可以是1(对于Bob)或2(对于Mary)。这只是显示(并且表格模型清楚地显示)等级不是地址的属性。

因此,您的问题的解决方案很简单:您必须将PERSON_ADDRESS_MAP表映射到实体:

public class Person {
    @OneToMany(mappedBy = "person")
    private Set<RankedAddress> rankedAddresses;
}

public class RankedAddress {
    @ManyToOne
    private Person person;

    @ManyToOne
    private Address address;
}

public class Address {
    @OneToMany(mappedBy = "adress")
    private Set<RankedAddress> rankedAddresses;
}

对于所有实体,我还建议您向RankedAddress实体添加单列自动生成的ID(和相应的列)。

如果rank是连接表的唯一附加,并且它用于包含人员地址列表中每个地址的索引(即它从0到N-1,N是用户的地址数量) ),然后有一个替代方案,它不会强制您将连接表映射到实体:

public class Person {
    @ManyToMany
    @OrderColumn(name = "rank")
    private List<Address> addresses;
}

请注意,该列的值将完全由JPA处理,并且它仅用于存储列表中给定索引处的每个地址。它不能用于查询,除了在列表中获取索引之外,您将无法知道某人的地址等级。