And*_*i V 16 java hibernate jpa many-to-one
我有2个班:司机和汽车.汽车表在单独的过程中更新.我需要的是在驱动程序中拥有属性,允许我读取完整的汽车描述并只写入指向现有汽车的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);
}
}
Run Code Online (Sandbox Code Playgroud)
Car对象只是典型的JPA对象,没有对Driver的反向引用.
所以我试图通过这个实现:1)我可以使用详细的JSON View 2)阅读完整的汽车描述或者我只能阅读简短的JsonView 3中的汽车ID而且最重要的是,当创建新的驱动程序我只是想要传递汽车的JSON ID.这样我就不需要在持久化期间为汽车执行不必要的读取操作,而只是更新Id.
我得到以下错误:"对象引用未保存的瞬态实例 - 在刷新之前保存瞬态实例:com.Driver.car - > com.Car"
我不想在DB中更新Car的实例,而只是从Driver中引用它.知道怎么做到我想要的吗?
谢谢.
更新:忘记提及我在创建驱动程序期间传递的汽车ID是DB中现有汽车的有效ID.
sce*_*tix 19
您可以通过以下方式getReference拨打电话EntityManager:
EntityManager em = ...;
Car car = em.getReference(Car.class, carId);
Driver driver = ...;
driver.setCar(car);
em.persist(driver);
Run Code Online (Sandbox Code Playgroud)
这不会从数据库执行SELECT语句.
作为对okutane的回答,请参见代码段:
@JoinColumn(name = "car_id", insertable = false, updatable = false)
@ManyToOne(targetEntity = Car, fetch = FetchType.EAGER)
private Car car;
@Column(name = "car_id")
private Long carId;
Run Code Online (Sandbox Code Playgroud)
因此,这里发生的是,当您要执行插入/更新时,仅填充carId字段并执行插入/更新。由于car字段是不可插入且不可更新的,因此Hibernate不会对此提出抱怨,并且由于在数据库模型中,您无论如何都只将car_id填充为外键,这时就足够了(并且数据库上的外键关系会确保您的数据完整性)。现在,当您提取实体时,Hibernate将填充汽车字段,从而为您提供了灵活的方式,在需要时仅由您的父母获取。
该错误消息表示您的对象图中有一个瞬态实例,没有明确保留。简短回顾一下对象在JPA中可以具有的状态:
错误消息告诉您,正在使用的(托管/分离)驱动程序对象持有对Hibernate未知(瞬态)的Car对象的引用。为了使Hibernate了解从驱动程序引用的任何未保存的Car实例也应保存,您可以调用EntityManager的persist-method。
另外,您可以在持久性上添加一个层叠(我想,只是从我的头顶上还没有测试过),它将在持久化驱动程序之前在Car上执行持久化。
@ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.PERSIST)
@JoinColumn(name = "CAR_ID")
private Car car;
Run Code Online (Sandbox Code Playgroud)
如果您使用entitymanager的合并方法来存储驱动程序,则应该添加CascadeType.MERGE,或两者都添加:
@ManyToOne(fetch=FetchType.LAZY, cascade={ CascadeType.PERSIST, CascadeType.MERGE })
@JoinColumn(name = "CAR_ID")
private Car car;
Run Code Online (Sandbox Code Playgroud)
您只能使用以下carID:
@JoinColumn(name = "car")
@ManyToOne(targetEntity = Car.class, fetch = FetchType.LAZY)
@NotNull(message = "Car not set")
@JsonIgnore
private Car car;
@Column(name = "car", insertable = false, updatable = false)
private Long carId;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
25751 次 |
| 最近记录: |