JPA – 实体设计问题

我正在开发Java桌面应用程序并使用JPA进行持久化。 我有一个问题如下:

我有两个实体:

  • 国家

国家/地区具有以下属性:

  • 国名(PK)

City具有以下属性:

  • 城市名

现在由于两个不同国家/地区可能有两个同名的城市,因此数据库中City表的primaryKey是由CityNameCountryName组成的复合主键。

现在我的问题是如何将City的主键实现为Java中的Entity

  @Entity public class Country implements Serializable { private String countryName; @Id public String getCountryName() { return this.countryName; } } @Entity public class City implements Serializable { private CityPK cityPK; private Country country; @EmbeddedId public CityPK getCityPK() { return this.cityPK; } } @Embeddable public class CityPK implements Serializable { public String cityName; public String countryName; } 

现在我们知道从CountryCity的关系是OneToMany并且在上面的代码中显示这种关系,我在City类中添加了一个country变量。

但是,我们将重复数据( countryName )存储在City类对象的两个位置:一个位于country对象中,另一个位于cityPK对象中。

但另一方面,两者都是必要的:

  • countryName对象中的cityPK是必需的,因为我们以这种方式实现复合主键。

  • country对象中的countryName是必需的,因为它是显示对象之间关系的标准方式。

如何解决这个问题?

countryName中的CityPK应使用@Column(insertable = false, updatable = false) countryName @Column(insertable = false, updatable = false)标记为只读@Column(insertable = false, updatable = false)并且countryName s应映射到同一列(使用name属性):

  @Entity public class City implements Serializable { @EmbeddedId private CityPK cityPK; @ManyToOne @JoinColumn(name = "countryName") private Country country; } @Embeddable public class CityPK implements Serializable { public String cityName; @Column(name = "countryName", insertable = false, updatable = false) public String countryName; } 

IMO处理此类问题的正确方法是使用生成的内部(通常为Long )ID而不是自然主键 – 这消除了整个问题。 当然,这需要修改您的数据库架构,但是从您的post我认为这是可能的。

 @Entity public class City implements Serializable { private Long id; private String name; private Country country; @Id @GeneratedValue @Column(name = "CITY_ID") public Long getId() { return this.id; } private void setId(Long id) { this.id = id; } // more getters, setters and annotations }