【问题标题】:JPA: duplicate simple vs. relationship mappings - where to put insertable = false, updatable = false and whyJPA:重复简单与关系映射 - 在哪里放置可插入 = 假、可更新 = 假以及为什么
【发布时间】:2017-10-16 15:48:42
【问题描述】:

这是Hibernate: Where do insertable = false, updatable = false belong in composite primary key constellations involving foreign keys?的后续问题:

考虑以下实体映射:

public class Zip {

    @ManyToOne
    @JoinColumn(name = "country_code", referencedColumnName = "iso_code")
    private Country country = null

    @Column(name = "country_code")
    private String countryCode;

    ...
}

像这样,JPA 实现会窒息说“country_code 的重复映射,其中只有一个可能被指定为可写”。

为什么在此处/通常将关系设为只读 (private Country country) 而非将简单 ID 字段设为只读 (private String countryCode) ?

为什么一个在实践中比另一个更好(优点/缺点)?

我能想到的唯一事情是,当数据库使用任何 FK 时,使用可写关系会更好,这会使使用实体变得有些强制性,但是,这不会阻止用户从能够将新实体插入到具有未知 ID 的数据库中,这只会使可写关系稍微安全一些。能够使用 ID 当然会使从数据库中加载完整的实体变得多余,这可能是一个很大的性能方面。

欢迎更多论据。

PS:我将 JPA 实现添加为标签以吸引更多观众。

【问题讨论】:

    标签: hibernate jpa eclipselink openjpa datanucleus


    【解决方案1】:

    首先,没有真正需要countryCode 映射,因为其中的数据保存在引用的国家/地区,在iso_code 的映射中。例如 EclipseLink 可以在查询中使用 zip.country.id = :isoCode 并且知道它可以直接使用 country_code 外键而无需加入表,就像您使用 zip.countryCode = :isoCode 一样。因此,如果两者兼而有之,则应该有一个理由,并且该理由应该决定您想要控制country_code 外键的哪个。

    其次,如果数据库没有外键约束,建立关系对您没有任何帮助。如果没有限制,如果您从数据库中删除国家/地区,您的Zip 仍将引用该国家/地区。如果它不在缓存中,则 countryCode 将有一个值,但引用将为空(或根据提供者抛出错误)。

    我也不同意关系应该是只读的;我相信这样做很可能是为了在数据库中更改关系,而无需读取 IMO 是一种不好的做法的引用对象。 JPA 允许 2 层缓存,因此更改将导致缓存的关系与数据库不同步,然后需要额外的开销来解决。如果您打算这样做,您可能根本不映射country 关系引用 - 如果/在需要时从 JPA 中读取它,并在有意义的情况下将其作为瞬态存储在实体中。

    最后,您的对象模型应该映射您的业务需求。仅仅因为数据库具有引用和字段,并不意味着您的 Java 实体也必须以完全相同的方式映射它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-01
      • 2016-10-09
      • 2011-02-05
      • 1970-01-01
      • 1970-01-01
      • 2012-07-06
      • 1970-01-01
      • 2018-12-26
      相关资源
      最近更新 更多