Java JPA-实体设计问题
我正在开发一个Java桌面应用程序,并使用JPA进行持久化。我有一个问题提到如下: 我有两个实体:Java JPA-实体设计问题,java,jpa,entity,entity-relationship,object-relationships,Java,Jpa,Entity,Entity Relationship,Object Relationships,我正在开发一个Java桌面应用程序,并使用JPA进行持久化。我有一个问题提到如下: 我有两个实体: 国家 城市 国家/地区具有以下属性: 国家名称(PK) 城市具有以下属性: 城市名称 现在,由于在两个不同的国家/地区可以有两个同名城市,因此数据库中City表的primaryKey是由CityName和CountryName组成的复合主键 现在我的问题是如何在Java中将城市的主键实现为实体 现在我们知道从Country到City的关系是OneToMany,为了在上面的代码中显示这种
- 国家
- 城市
- 国家名称(PK)
- 城市名称
CityName
和CountryName
组成的复合主键
现在我的问题是如何在Java中将城市
的主键实现为实体
现在我们知道从Country
到City
的关系是OneToMany
,为了在上面的代码中显示这种关系,我在City
类中添加了Country
变量
但是,我们在城市
类”对象中的两个地方存储了重复数据(countryName
),一个在国家
对象中,另一个在城市pk
对象中
但另一方面,两者都是必要的:
对象中的cityPK
是必需的,因为我们以这种方式实现复合主键countryName
对象中的country
是必需的,因为它是显示对象之间关系的标准方式countryName
如何解决此问题?
CityPK
中的countryName
应使用@列(insertable=false,updateable=false)
标记为只读,并且两个countryName
应映射到同一列(使用name
属性):
IMO处理此类问题的正确方法是使用生成的内部(通常为
Long
)ID,而不是自然主键-这消除了整个问题。当然,这需要修改您的DB模式,但是从您的帖子中我假设这是可能的
@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
}
这是处理这类问题的标准方法吗?这个问题在JPA中常见吗?@Yatendra:是的,这是一种标准的方法(如果你不使用代理键,就像Peter建议的那样)。然后我认为我不能在equals方法中使用
id
,来实现相等。对吗?@Yatendra为什么不?两个名称相同但国家不同的城市必须有不同的ID。您只需确保不会在表中两次插入同一国家的同一城市。这可以由DB触发器或Hibernate拦截器强制执行。您不能在equals()
中使用id
,因为id
是由数据库生成的。并且在对象持久化之前不可用。请参阅Gavin King的“使用Hibernate的Java持久化”,请参阅关于业务密钥和代理密钥的讨论。@Ram,只有当您需要在两个尚未持久化的实体之间进行比较时,这才是一个问题(这不是很常见,但我可能错了)。在这种情况下,如果id
为null
,则可以扩展equals
以比较其他重要属性。或者,如果我们执行new City()
并将其添加到集合中,则会出现问题。因为ID可以更改。我也不确定,但那是书上说的。
@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;
}
@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
}