java - 使用 @JoinColumn 保留不指向任何 ID 属性的实体

标签 java hibernate jpa

我有一个实体 ConfigurationEntity,它的属性 dayOfTheWeek 的值可以为 1-7。当客户端获取 GET.../configuration 时,他们希望同时拥有名称和代码 (1-7)。考虑到分解,我创建了一个 DictionaryEntity ,它映射到存储值的表

id   | group        | name    | code
123  | dayOfTheWeek | Monday  | 1
124  | dayOfTheWeek | Tuesday | 2
etc..

我已将 ConfigurationEntity 定义为

(我省略了一些我认为对问题不重要的细节和注释)

class ConfigurationEntity {
  @Id
  private Long id;

  @ManyToOne
  @JoinColumn(column = "dayOfTheWeek", referenceColum = "code", table = "dictionary")
  @Where("dictionary.group = 'dayOfTheWeek'")
  @JsonIgnore
  private DictionaryEntity dayOfTheWeekDictionary;

  @JsonProperty
  public Number getDayOfTheWeek() {
    return this.dayOfTheWeekDictionary.code;
  }

  @JsonProperty
  public String getDayOfTheWeekDescription() {
    return this.dayOfTheWeekDictionary.name;
  }
}

这会导致对 GET 的响应:

{
  "id": 1,
  "dayOfTheWeek": 1,
  "dayOfTheWeekDescription": "Monday"
}

问题是当客户端想要向 ConfigurationEntity 提交一些更改并发送以下 PATCH 请求时:

{
  "id": 1,
  "dayOfTheWeek": 2
}

Hibernate/JPA(我通常很困惑哪个具体做了什么)可以坚持这一点(通过一些技巧),但 repository.save(entity) 返回我一个带有 dayOfTheWeekDictionary 的记录 等于nullrepository.getById(id) 也是如此。再次调用 GET 后,客户端收到正确映射/连接的记录。

问题是:如何持久化一个只知道 dictionary.code 的实体,以便 hibernate 可以找到该记录对应的 DictionaryEntity

我意识到 DictionaryEntity 实际上有一个组合键(组、代码)。我可以添加此 key ,但客户端仍然只知道 key 的一部分,而实体知道第二部分(@Where 子句)。我可以自己获取 DictionaryEntity,但是如果我有 100 个表,其中 200 个字段与 dictionary 表连接,该怎么办?我希望解决方案是抽象/通用的。

最佳答案

这是一个设计问题。以下是我认为错误的地方以及我认为您应该如何解决这个问题。

首先:您不需要任何数据库表来指定 1 是星期一,2 是星期二。这应该简单地硬编码在您的代码中:永远不会改变。您所需要的只是一个正确定义的枚举和一个自定义 JSON 序列化器,该序列化器将该枚举的实例序列化为带有代码和日期名称的对象:

"dayOfTheWeek": {
  "code": 1,
  "name": "Monday"
}

现在允许修改配置实体的 API。绝对没有理由让任何客户提交一天的名称。目标是更改配置实体,该实体具有由数字代码唯一且明确标识的一周中的某一天。因此,要更改配置实体的日期,您只需要一个新的日期代码即可。发送新的日期名称既多余又令人困惑(如您的问题所示)。因此,将您的 API 输入设计为需要日期代码但不需要日期名称的对象。

作为示例,请参阅 github REST API。如果你get an issue作为响应中问题的一部分,您将获得一个受让人对象,其中包含有关受让人的大量详细信息:标识受让人的登录名,还有他/她的头像、URL 等。

但是,如果您提交新问题,则唯一需要的信息是问题受让人的 ID。受让人的头像和 URL 毫无用处,提交它们会造成困惑,因为 API 不希望(也可能不会)更改受让人的详细信息。所以,what does the API take as input ?一个对象,仅包含受让人的字符串,该字符串仅包含唯一标识受让人的内容:他/她的登录名。

将“问题”替换为“配置实体”,将“受让人”替换为“星期几”,您的情况与您的情况相同。

关于java - 使用 @JoinColumn 保留不指向任何 ID 属性的实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56063118/

相关文章:

java - ack 方法仅适用于第一个 bolt ,不适用于其他 bolt

java - 使用 hibernate 6.0.10 验证结果来自 EachPattern 的 ConstraintDefinitionException

java - NetBeans 7 中的 Jpa Controller

java - 如何根据用户输入更改 Android 应用程序的背景颜色?

java - 获取 Object[] 信息到 ArrayList 并将其呈现在 ListView 布局上

java - TwoSums 代码仅返回 [0,0]

Java JPA/Hibernate级联删除

java - Hibernate 有没有办法在不先加载整个实体对象的情况下获取实体加载的 PersistentCollection?

java - Hibernate:缺少列数

java - 如何从 JPA 中的唯一约束异常中获取字段名称