gpt4 book ai didi

postgresql - 具有@OneToOne 关系的Spring Data JPA 无法更新已持久存在的实体

转载 作者:行者123 更新时间:2023-11-29 12:22:08 27 4
gpt4 key购买 nike

我们得到了这样的设置:一个文档有一个元素列表,这些元素是 Element 的子类,在这个例子中是 Link。链接与资源具有@OneToOne 关系。只要我们一步创建整个对象图,一切都正常。

我们现在更改了我们的代码以创建 Resource 的实例,持久化并将其传递给我们的客户端(Web,序列化为 JSON 的对象)。客户端创建一个文档实例并添加一个与现有资源的链接。之后,我们尝试保留新文档。

此时操作失败,因为 JPA 试图用相同的 id 保存已经存在的资源。我认为发生这种情况是因为资源是分离的,JPA 无法确定是否必须合并或保留该实体。当我删除 CascadeType.ALL 并将其替换为 CascadeType.MERGE 时,一切都很好,除了资源根本没有更新。

基本上工作流程如下:

  • 创建并保留资源
  • 离开交易
  • 开始交易
  • 创建带有链接和(分离的)资源的文档
  • 错误

我们的 JPA 配置有问题吗(看看我们的实体)?如果你能给我一个提示,我很想找个时间给你一杯啤酒……:-) TYIA。

我们的设置是:EclipseLink 2.4.1、Spring Data JPA 1.3.0(使用@Repository)和 PostgreSQL 9.2。

文档:

@Entity
public class Document implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
@OrderColumn
@JoinColumn(name = "document_id")
private List<Element> elements = new ArrayList<Element>();

// getters and setters
}

元素:

@Entity
@Inheritance(strategy = InheritanceType.
public class Element implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "document_id", insertable = false, updatable = false)
private Document document;

// getters and setters
}

链接:

@Entity
public class Link extends Element {

@Column
private String appearance;

@Column
private String referenceType;

@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
private Resource resource;

// getters and setters
}

资源:

@Entity
public class Resource {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

@Column
private String uri;

// getters and setters
}

最佳答案

CascadeType.MERGE 用于级联合并操作,例如:

Document document = getDetachedDocumentSomehow();
em.merge(document)

将整个对象图合并到持久化上下文。

您需要做的是将分离的资源实例合并到第二个事务的持久化上下文中。

Resource resource = getDetachedResourceSomehow();
mergedResource = em.merge(resource)
link.setResource(mergedResource)

编辑:不使用实体管理器:

Resource resource = getDetachedResourceSomehow();
managedResource = resourceDao.findOne(resource.getId)
link.setResource(managedResource)

要点是您必须设置 Resource 的托管实例。

关于postgresql - 具有@OneToOne 关系的Spring Data JPA 无法更新已持久存在的实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16037746/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com