一尘不染

JPA多对一关系-仅需保存ID

hibernate

我有2个班级:驾驶员和汽车。汽车表在单独的过程中更新。我需要的是在Driver中具有属性,该属性使我可以阅读完整的汽车说明,并仅写入指向现有Car的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);
    }

}

汽车对象只是典型的JPA对象,没有向后引用驱动程序。

因此,我想通过以下方法实现的目标是:1)我可以使用详细的JSON View阅读完整的汽车描述2)或在简短的JsonView 3中仅阅读汽车的ID
3),最重要的是,在创建新驱动程序时,我只想传递汽车的JSON ID。这样,我在持久化期间不需要对汽车进行不必要的读取,而只需更新ID。

我收到以下错误消息:“对象引用了一个未保存的瞬态实例-在刷新之前保存该瞬态实例:com.Driver.car-> com.Car”

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

谢谢。

更新:忘记提及在创建驱动程序期间我通过的Car的ID是DB中现有Car的有效ID。


阅读 598

收藏
2020-06-20

共1个答案

一尘不染

该错误消息表示您的对象图中有一个瞬态实例,没有明确保留。简短回顾一下对象在JPA中可以具有的状态:

  • 瞬态 :尚未存储在数据库中的新对象(因此对于实体管理器而言是未知的)。没有设置ID。
  • 托管 :实体管理器跟踪的对象。托管对象是您在事务范围内使用的对象,一旦提交事务,对托管对象所做的所有更改将自动存储。
  • 分离的 :提交转换后仍可访问的先前管理的对象。(事务外部的托管对象。)设置了ID。

错误消息告诉您,正在使用的(托管/分离)驱动程序对象持有对Hibernate未知(瞬态)的Car对象的引用。为了使Hibernate了解从驱动程序引用的任何未保存的Car实例也应保存,您可以调用EntityManager的persist-
method。

另外,您可以在持久性上添加一个层叠(我想,只是从我的头顶上还没有测试过),它将在持久化驱动程序之前在Car上执行持久化。

@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;
2020-06-20