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

2023-11-22

我正在开发一个 RESTful 网络服务弹簧数据作为其数据访问层,由 JPA/Hibernate 支持。 领域实体之间存在关系是很常见的。例如,想象一个实体Product which has a Category entity.

现在,当客户POSTs a ProductJAX-RS 方法的表示。该方法注释为@Transactional将每个存储库操作包装在事务中。当然,客户端只发送id一个已经存在的Category,不是整个表示,只是一个引用(外键)。

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

entity = repository.save(entity);

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

然后我这样做了:

entity = repository.save(entity);
entity = repository.findOne(entity.getId());

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

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

对于 Hibernate,解决方案似乎是使用session.refresh(entity) (see this and this)。说得通。

但是我如何用 Spring Data 来实现这一点呢?

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


tl;dr

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

Details

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

所以假设你有现有的Category暴露通过/categories/4711,您可以发布到您的服务器:

POST /products
{ links : [ { rel : "category", href : "/categories/4711" } ],
  // further product data
}

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

  1. 通过查找链接关系类型(例如category这里的财产。
  2. 从给定的 URI 中提取后端标识符
  3. 使用相应的存储库查找相关实体实例
  4. 将其设置在根实体上

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

Product product = new Product();
// populate primitive properties
product.setCategory(categoryRepository.findOne(4711));
productRepository.save(product);

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

POST /products
{ category : {
    id : 1, … },
  … 
}

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

  1. 您希望持久性提供者隐式地持久化Product实例并同时“认识到”Category引用的实例(实际上仅由 id 组成)并不意味着被持久化,而是用已经存在的数据进行更新Category?我认为这有点神奇。
  2. 您实质上将用于 POST 到服务器的数据结构强加给持久层,期望它透明地处理您决定执行 POST 的方式。这不是持久层的责任,而是 Web 层的责任。 Web 层的全部目的是使用表示和到后端服务的链接来缓解基于 HTTP 的协议的特性。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

保存后如何检索实体关系? 的相关文章

随机推荐

  • 将数组从 jQuery 传递到 MVC.NET 控制器,在控制器上给出 null 结果,但 jQuery 函数上存在值

    我正在尝试将数组从 jQuery 函数传递到我的控制器 该数组包含内容和保存该内容的 div 的 id 当我检查通过 Firebug 中的 AJAX 发送的对象时 那里有正确的值 但在我的控制器上放置断点后 收到的值是一个空列表或数组或我尝
  • 使用gradle将jar上传到本地Maven仓库

    这个问题已经被问过好几次了 但不知何故我无法让它发挥作用 Gradle 是一个很棒的工具 但它的文档却一点也不出色 对于那些不每天使用它的人来说 没有任何例子几乎不可能理解它 我正在使用 Android Studio 我想将模块输出 jar
  • symfony2 注销

    我的问题是捕获用户注销 我所拥有的代码是 public function onAuthenticationFailure Request request AuthenticationException exception return ne
  • Angularjs:使用日期助手将时间戳格式化为 UTC 时间

    我正在寻找如何使用 AngularJS 日期助手格式化 unix 时间戳的想法 In 官方文档 只有字符串输入的解释 如果字符串输入中没有指定时区 则认为时间是本地时区 但是时间戳呢 有什么提示吗 我找到了一些带有自定义过滤器和 momen
  • 无法获取 Google Cloud Storage 存储桶的位置

    我尝试使用 Java 客户端将数据从 S3 传输到 GCS 但出现此错误 无法获取 Google Cloud Storage GCS 存储桶的位置 由于权限不足 请验证是否已授予必要的权限 我正在使用具有项目所有者角色的服务帐户 该帐户应授
  • onTouch MotionEvent getTouchMinor 和 getTouchMajor 的数字结果总是完全相同,为什么?

    查看文档 触摸主坐标和触摸副坐标是触摸事件的椭圆轴 一种是触摸区域的最长测量长度 另一种是触摸事件的最短测量长度 就像椭圆的测量一样 不过 我在几台 Android 平板电脑上测试了 getTouchMajor 和 getTouchMino
  • Magento 中多个模块覆盖同一个核心文件

    Magento 如何处理覆盖同一核心文件的多个模块 是否可以 它是如何完成的 您有 3 种解决冲突的选择 将一个冲突文件中的代码合并到另一个文件中 并关闭其中一个文件中的重写 config xml 关闭一个 config xml 中的重写
  • C++ 中的函数组合

    有许多令人印象深刻的 Boost 库 例如 Boost Lambda 或 Boost Phoenix 它们在使 C 成为真正的函数式语言方面大有帮助 但是是否有一种直接的方法可以从任意 2 个或更多任意函数或函子创建复合函数 如果我有 in
  • strstr() 在 gcc 和 VS 中的实现是否具有线性复杂度?

    我知道有快速的字符串搜索算法 例如博耶 摩尔 and 高德纳 莫里斯 普拉特 其复杂度为 O n m 而普通解决方案为 O n m 那么 最流行的工具链 gcc 和 Visual Studio 的 strstr 实现是使用这些快速 O n
  • css 过渡不透明度在元素显示:无然后更改为显示:块的情况下不起作用

    正如标题所说 我有这个代码 https jsfiddle net fwo9ym1o javascript var container document querySelector container container style disp
  • 如何在 subprocess.Popen() 中使用现有环境变量

    Scenario 在我的 python 脚本中 我需要将一个可执行文件作为子进程运行 其中包含可执行文件所期望的 x 个命令行参数 Example EG 1 myexec sh 参数1 参数2 EG 2 myexec sh param1 M
  • 了解 Matlab FFT 示例

    我是 matlab 和 FFT 新手 想了解Matlab FFT 示例 现在我有两个主要问题 1 为什么x轴 频率 以500结束 我怎么知道没有更多频率或者它们只是被忽略了 2 我如何知道频率在0到500之间 FFT 不应该告诉我频率的限制
  • 如何检测 `snprintf` 错误?

    int snprintf char restrict s size t n const char restrict format snprintf 很好地防止超出目的地s 然而 当目的地不足以获得完整结果时 如何检测该错误和其他错误 以下内
  • 为什么在 Windows 上创建新进程比在 Linux 上更昂贵?

    我听说在 Windows 机器上创建新进程比在 Linux 上更昂贵 这是真的 有人可以解释为什么它更昂贵的技术原因 并提供这些原因背后的设计决策的任何历史原因吗 mweerden NT 从第一天起就是为多用户设计的 所以这并不是一个真正的
  • 在C++中连接字符串流

    如何连接两个字符串流 include
  • 长按按钮

    我想重复一个动作Button长时间按下 例如 MP3 阅读器的前进按钮 WinForm 中是否存在现有的 c 事件 我可以处理MouseDown启动一个计时器的事件 该计时器将执行该操作并停止MouseUp事件 但我正在寻找一种更简单的方法
  • 无法连接到远程://localhost:9999。连接超时 Jboss 7.1.1 Final

    我正在端口 9999 将构建部署到本地和远程 Jboss AS 7 1 1 Final Maven 使用 jboss 插件 jboss as maven plugin 7 1 1 Final 来管理服务器的构建 我已确认服务器已启动并正在运
  • Python:QML 布局内的 matplotlib 绘图

    考虑以下 python3 PyQt 代码来显示带有工具栏的交互式 matplotlib 图形 import sys sip import numpy as np from PyQt5 import QtGui QtWidgets from
  • 如何在 Rust 中按值传递装箱特征对象?

    我正在编写一些代码 并且有一个方法的特征 该方法需要self按价值 我想调用这个方法Box d 特征对象 消耗Box及其价值 这可能吗 如果是这样 怎么办 就代码而言 最小示例如下 不完整 代码 trait Consumable fn co
  • 保存后如何检索实体关系?

    我正在开发一个 RESTful 网络服务弹簧数据作为其数据访问层 由 JPA Hibernate 支持 领域实体之间存在关系是很常见的 例如 想象一个实体Product which has a Category entity 现在 当客户P