考虑以下实体映射:
public class Zip {
@ManyToOne
@JoinColumn(name = "country_code", referencedColumnName = "iso_code")
private Country country = null
@Column(name = "country_code")
private String countryCode;
...
}
就像这样,JPA实现会扼杀类似于"乡村代码的重复映射,只有其中一个可以被指定为可写"。
问:
为什么关系只读(private Country country
)首选/通常将只读放在简单ID字段上({{ 1}})?
为什么一个人在实践中优于另一个人(优点/缺点)?
我唯一能想到的是,当数据库不使用任何FK时,使用可写关系会更好,这会使实体在某种程度上是强制性的,但这不会阻止用户从能够将新实体插入到具有未知ID的DB中,这将使可写关系稍微安全一些。能够使用ID当然会使数据库中的完整实体加载冗余,这可能是一个很大的性能方面。
欢迎更多参数。
PS:我将JPA实现添加为标签以吸引更多观众。
答案 0 :(得分:2)
首先,没有真正需要countryCode
映射,因为其中的数据保存在引用的国家/地区,在iso_code
的映射中。例如,EclipseLink可以在查询中使用zip.country.id = :isoCode
,并且知道它可以直接使用country_code
外键而无需加入表,就像使用zip.countryCode = :isoCode
一样。因此,如果您同时拥有它们,那么您应该有理由,并且该原因应该决定您希望控制哪个country_code
外键。
其次,如果数据库没有外键约束,那么建立关系对你没有任何帮助。没有限制,如果您从数据库中删除国家/地区,则Zip
仍会引用该国家/地区。如果它不在缓存中,则countryCode
将具有值,但引用将为null(或根据提供程序抛出错误)。
我也不同意关系应该是只读的;我相信可能这样做可以在数据库中更改关系,而无需在引用的对象中读取IMO是一种不好的做法。 JPA允许2层缓存,因此更改将导致缓存关系与数据库不同步,然后需要额外的开销来解决。如果您打算这样做,您可能根本不会映射country
关系引用 - 如果/需要时从JPA读取它并将其作为瞬态存储在实体中(如果有意义的话)。
最后,您的对象模型应该映射您的业务需求。仅仅因为数据库有引用和字段,并不意味着你的Java实体也必须以完全相同的方式映射它们。