professional/standard 用外键保存对象的方法是什么?

What is the professional/standard way to save an object with a foreign key?

我正在用 Spring-mvc 开发一个简单的字典 RESTful API。有两个相关实体:

public class Word {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private int id;

  private String word;

  @ManyToOne(fetch=FetchType.EAGER)
  @JoinColumn(name="LANGUAGE_ID", insertable=false, updatable=false)
  private Language language;

}

根据上面的代码,相关实体是 Language

问题:我想用POST请求在Word实体上实现CREATE操作。实施并不困难,但我确实找到了至少两个与 POST 请求 URL 和 JSON 请求正文相关的候选解决方案:

Solution Candicate I: 直接插入 JSON body request。 JSON 主体包含嵌套的 JSON 对象 - 语言,类似于

{id:1, word:"hello", Language: {id:1, language:"English"}}

参考:Spring: Save object with foreign keys with a POST request

Solution Candidate II:通过POST请求获取引用的Language id URL,说类似

POST http://localhost:8080/rest/language/1/words

因此,JSON POST 请求正文中根本没有 Language 引用。

参考:https://www.youtube.com/watch?v=_Jnu_jHfQbM

我有两个问题:

问题一:这两个备选方案,哪个更好,或者说是专业的标准方案?或者还有其他解决方案吗?

问题2:对于给定的候选解,无论如何我们都需要至少在相应的[=17=中检索引用的Language POJO ] class。但是从面向对象设计原则的角度来看,这种方式似乎与控制器紧密耦合,所以我在想我们是否应该在控制器之外的其他地方解耦这种检索行为?例如在 service 层。但这是专业的方式吗?并且我们需要有相应的DTO?

我认为应该保存的数据必须嵌套在正文中。 Spring 可以将 json 数据直接映射到对象中,您不必将其从参数设置为另一个模型 class。

我会为您的实体创建单独的模型 classes。因此控制器将数据填充到模型 classes 并将它们提供给服务。然后服务将模型 classes 映射到实体。之后,它们可以通过存储库存储。

示例:

@Controller
public class RestController {

  @Autowired
  RestService restService;

  @PostMapping(value="/")
  public void saveVariable( @RequestBody TestModel testModel ) {
    testService.saveTest( testModel );
  }
}

@Service
public class RestService {

  @Autowired 
  TestRespository testRepository;

  public void saveTest( TestModel testModel ) {
    TestEntity testEntity = new TestEntity();
    //some mapping from testModel to testEntity
    testRepository.save( testEntity );
  }
}

假设属于一种语言,我会设计如下:

POST /api/languages/en/words HTTP/1.1
Host: localhost:8080
Content-Type: application/json

{
  "word": "hello"
}

在请求负载中将单词的表示(例如 JSON 文档)发送到表示层次结构的 URL(语言 个单词).

您也可以使用 two-letter codes 来识别语言,因为它比数值更清晰。在上面的例子中,en表示English.


我建议您避免在 REST API 和 use DTOs 中公开持久性实体。您的 REST 资源表示不需要具有与持久性对象相同的属性。


让您的 REST 控制器尽可能精简,并让您的服务层专注于业务规则。