JPA 多对一关系 - 只需要保存 Id

新手上路,请多包涵

我有 2 个班级:司机和汽车。汽车表在单独的过程中更新。我需要的是在 Driver 中拥有属性,使我能够阅读完整的汽车描述并仅写入指向现有汽车的 Id。这是例子:

 @Entity(name = "DRIVER")
public class Driver {
... ID and other properties for Driver goes here .....

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name = "CAR_ID")
    private Car car;

    @JsonView({Views.Full.class})
    public Car getCar() {
      return car;
    }
    @JsonView({Views.Short.class})
    public long getCarId() {
      return car.getId();
    }
    public void setCarId(long carId) {
      this.car = new Car (carId);
    }

}

Car 对象只是典型的 JPA 对象,没有对 Driver 的反向引用。

所以我试图通过这个实现的是:

  1. 我可以使用详细的 JSON 视图阅读完整的汽车描述
  2. 或者我只能在 Short JsonView 中读取汽车的 Id
  3. 最重要的是,在创建新驱动程序时,我只想传入汽车的 JSON ID。这样我就不需要在坚持期间对汽车进行不必要的读取,而只需更新 Id。

我收到以下错误:

 object references an unsaved transient instance - save the transient instance before flushing : com.Driver.car -> com.Car

我不想在数据库中更新 Car 的实例,而只是从 Driver 中引用它。知道如何实现我想要的吗?

谢谢你。

更新:忘记提及我在创建驱动程序期间传递的汽车 ID 是数据库中现有汽车的有效 ID。

原文由 Andrei V 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 919
2 个回答

该错误消息意味着您的对象图中有一个未明确保留的瞬态实例。对象在 JPA 中可以具有的状态的简短回顾:

  • Transient :尚未存储在数据库中的新对象(因此对于 entitymanager 而言是未知的。)没有 id 集。
  • _托管_:实体管理器跟踪的对象。托管对象是您在事务范围内使用的对象,一旦提交事务,对托管对象所做的所有更改将自动存储。
  • 分离 的:一个以前管理的对象,在事务提交后仍然可以访问。 (事务外的托管对象。)有一个 id 集。

错误消息告诉您的是,您正在使用的(托管/分离的)驱动程序对象持有对 Hibernate 未知的 Car 对象的引用(它是瞬态的)。为了让 Hibernate 理解任何从 Driver 引用的未保存的 Car 实例也应该被保存,你可以调用 EntityManager 的持久化方法。

或者,您可以在 persist 上添加一个级联(我想,只是从我的头顶开始,还没有测试过),这将在持久化 Driver 之前在 Car 上执行 persist。

 @ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.PERSIST)
@JoinColumn(name = "CAR_ID")
private Car car;

如果您使用 entitymanager 的合并方法来存储驱动程序,您应该添加 CascadeType.MERGE 代替,或两者:

 @ManyToOne(fetch=FetchType.LAZY, cascade={ CascadeType.PERSIST, CascadeType.MERGE })
@JoinColumn(name = "CAR_ID")
private Car car;

原文由 Tobb 发布,翻译遵循 CC BY-SA 3.0 许可协议

您可以通过 getReference 调用 EntityManager 来做到这一点:

 EntityManager em = ...;
Car car = em.getReference(Car.class, carId);

Driver driver = ...;
driver.setCar(car);
em.persist(driver);

这不会从数据库执行 SELECT 语句。

原文由 scetix 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题