【问题标题】:JPA persist object in a ManyToOne relationshipJPA 在多对一关系中持久化对象
【发布时间】:2023-03-20 08:05:01
【问题描述】:

我的数据库中有一个公司/员工@OneToMany 关系定义为:

@Entity
public class Employee {
   @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
   private long id;
   @ManyToOne @JoinColumn(name="companyid")
   Company company;
   ....
}

@Entity
public class Company {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;

...
}

现在我正在向一家独立公司添加一个新创建的员工。我使用的代码是这样的:

Company company = em1.find(Company.class, 555L);
em1.close();

EntityTransaction et = em2.getTransaction();
et.begin();
Employee employee = new Employee();
employee.company = company;
em2.persist(employee);
et.close();

这样可以吗?
hibernate 是将公司合并到第二个 EntityManager 还是只使用它的 id 并保留员工对象?
hibernate 可能会以某种方式复制我的公司对象或抛出异常,说明数据库中已存在具有相同 id 的公司?

【问题讨论】:

  • 值得一提的是,进行公共字段设置 (employee.company = company) 为持久性解决方案提供了最小的机制来了解字段已更改;最好使用 setter,这样任何实现都会很开心。

标签: java hibernate jpa entity-relationship


【解决方案1】:
  • 在所描述的情况下Companyid将在持久化Employee对象时使用,但Company本身不会被合并(注意Employee是关系的拥有方)李>
  • 如果Company 是瞬态的而不是分离的,您将收到“对象引用未保存的瞬态实例”错误
  • 如果使用cascade = CascadeType.PERSIST,您将收到“已传递的分离实体”错误。

来自 JPA 规范:

如果 X 是一个托管实体,它是 同步到数据库。

  • 为 a 引用的所有实体 Y 来自 X 的关系,如果 与 Y 的关系已被注释 具有级联元素值 cascade=PERSIST 或 cascade=ALL, 对 Y 应用持久化操作。
  • 对于由 a 引用的任何实体 Y 来自 X 的关系,其中 与 Y 的关系尚未 用级联元素注释 值级联=PERSIST 或级联=全部:
    • 如果 Y 是新的或已删除,则 将抛出 IllegalStateException 通过刷新操作(和 标记为回滚的事务)或 事务提交将失败。
    • 如果 Y 是分离的,语义取决于 根据所有权 关系。 如果 X 拥有 关系,任何改变 关系是同步的 数据库; 否则,如果 Y 拥有 关系,行为是 未定义。

【讨论】:

  • 非常感谢您。该代码确实可以正常工作(正如您所说)。我们想确保我们遵循 JPA 规则并且不会在一些未经测试的情况下遇到问题。现在我们是。再次感谢!
猜你喜欢
  • 2011-11-28
  • 2012-12-17
  • 2017-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-20
相关资源
最近更新 更多