保存后如何检索实体关系?

mig*_*ain 5 java rest jpa hypermedia spring-data-jpa

我正在开发一个RESTful webservice,其中spring-data作为其数据访问层,由JPA/Hibernate支持.在域实体之间建立关系是很常见的.例如,设想一个实体Product,其具有一个Category实体.

现在,当在客户端POSTSA Product表示到JAX-RS方法.该方法@Transactional用于在事务中包装每个存储库操作进行注释.当然,客户端只发送id一个已经存在的Category,而不是整个表示,只是一个引用(外键).

在那种方法中,如果我这样做:

entity = repository.save(entity);
Run Code Online (Sandbox Code Playgroud)

变量entity现在Category只有id字段集.这并没有让我感到惊讶.我没想到要保存(SQL插入)来检索相关对象的信息.但我需要整个Product对象和相关实体能够返回给用户.

然后我这样做了:

entity = repository.save(entity);
entity = repository.findOne(entity.getId());
Run Code Online (Sandbox Code Playgroud)

也就是说,在持久化之后,在同一个事务/会话中检索对象.

令我惊讶的是,变量entity没有改变任何东西.实际上,数据库甚至没有获得单个选择查询.这与Hibernate的缓存有关.出于某种原因,当在同一事务中时,如果该对象先前已持久化,则查找不会检索整个对象图.

使用Hibernate,解决方案似乎是使用session.refresh(entity)(参见本节).说得通.

但是如何通过弹簧数据实现这一目标?

我想避免创建重复的自定义存储库.我认为这个功能应该是spring数据的一部分(有些人已经在spring数据论坛中报告过:thread1,thread2).

Oli*_*ohm 2

太长了;博士

\n\n

Web 层中的实体之间的引用需要通过使用链接来明确,并且不应隐藏在半填充的对象实例后面。持久层中的引用由对象引用表示。因此,应该有一个专门的步骤将一个(链接)转换为另一个(完全填充的对象引用)。

\n\n

细节

\n\n

这是一种反模式,它会传递后端 id 并假设编组绑定做了正确的事情。因此,客户端应该使用链接并将这些链接交给服务器,以表明他们希望在现有资源和即将创建的资源之间建立连接。

\n\n

Category因此,假设您已经通过 暴露了现有的/categories/4711,您可以发布到您的服务器:

\n\n
POST /products\n{ links : [ { rel : "category", href : "/categories/4711" } ],\n  // further product data\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

服务器将实例化一个新Product实例,用附加数据填充它并最终填充关联,如下所示:

\n\n
    \n
  1. 通过查找链接关系类型来识别要填充的属性(例如,category此处的属性)。
  2. \n
  3. 从给定的 URI 中提取后端标识符
  4. \n
  5. 使用相应的存储库查找相关实体实例
  6. \n
  7. 将其设置在根实体上
  8. \n
\n\n

所以在你的例子中归结为:

\n\n
Product product = new Product();\n// populate primitive properties\nproduct.setCategory(categoryRepository.findOne(4711));\nproductRepository.save(product);\n
Run Code Online (Sandbox Code Playgroud)\n\n

只需将这样的内容发布到服务器即可:

\n\n
POST /products\n{ category : {\n    id : 1, \xe2\x80\xa6 },\n  \xe2\x80\xa6 \n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

由于多种原因,它不是最理想的:

\n\n
    \n
  1. 您希望持久性提供程序隐式地持久保存一个Product实例,同时“认识到”所Category引用的实例(实际上仅包含 id)并不意味着要持久保存,而是要使用已存在的数据进行更新Category?我认为这有点神奇。
  2. \n
  3. 您实质上将用于 POST 到服务器的数据结构强加给持久层,期望它透明地处理您决定执行 POST 的方式。这不是持久层的责任,而是 Web 层的责任。Web 层的全部目的是使用表示和到后端服务的链接来缓解基于 HTTP 的协议的特性。
  4. \n
\n