【问题标题】:Spring JPA: Insert new Entity and Cascade detached ReferenceSpring JPA:插入新实体和级联分离参考
【发布时间】:2023-03-08 07:56:01
【问题描述】:

我有两个实体类组织和用户,它们具有一对多关系(为了简单起见,使用 Groovy 代码!):

@Entity
class Organisation {
  @Id Long id
  String name
  @OneToMany
  List<User> users
}

@Entity 
class User {
  @Id Long id
  String username
  @ManyToOne(optional=false, cascade = CascadeType.Persist)
  Organisation organisation
}

当我为新组织创建新用户时,一切正常:

def user = new User(organisation: new Organisation(...))

但是当我采用现有组织时,将其设置为 new 用户的组织属性时出现错误:

def user = new User(organisation: organisationRepository.findOne(orgId))
userRepo.save(user)

将导致:

org.hibernate.PersistentObjectException:分离的实体传递给 坚持:组织

我知道不能对分离的实体调用persist。但在那种情况下,由于我没有更改组织实体本身的任何内容,我认为 hibernate 会允许这样做。

我尝试将cascade = {CascadeType.Persist, CascadeType.Merge} 放入ManyToOne 注释中,但以同样的错误结束。

我想归档的东西是不能用休眠的,还是我在某个地方有思维错误?

【问题讨论】:

标签: java spring hibernate jpa orm


【解决方案1】:

你正朝着正确的方向前进:

cascade = {CascadeType.Persist, CascadeType.Merge}

问题是,当您仍然执行save 操作时,持久性提供程序会尝试级联persist 操作,因此它最终会尝试持久化已经设置了@Id 并已分离的组织实体。

您需要做的是执行merge 而不是save

在这种情况下,新实体将被持久化,组织将被合并回持久化上下文中,从而使整个操作成功。

请记住,当您使用合并并希望之后对传递的实体执行操作时,您需要将结果分配给一个新变量并对其执行操作 f.e.:

User mergedUser = userRepo.merge(user);

// operations on mergedUser from now on

【讨论】:

  • 您好,感谢您的快速回复! :) 因为我使用 Spring Framework 和 JpaRepository 类,所以那里没有合并方法。这是否意味着我必须使用一些休眠内部存储库类?像实体管理器?或者,如果 Spring Repos 也提供一些合并功能,你现在可能会。我快速浏览了文档,但没有找到任何内容。
  • 我什至可以在新实体上调用合并吗?
  • 是的,它将支持创建新实体。你必须记住,虽然合并比持久化操作更昂贵。您可以考虑对组织进行合并,然后对用户进行持久化。如果您不在乎并且想一口气完成所有工作,请按照我的回答。
猜你喜欢
  • 2015-08-10
  • 1970-01-01
  • 2015-09-11
  • 1970-01-01
  • 1970-01-01
  • 2016-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多