问题描述
我有 2 个类:Driver 和 Car.汽车表在单独的过程中更新.我需要的是 Driver 中的属性允许我阅读完整的汽车描述并只写入指向现有汽车的 Id.示例如下:
I have 2 classes: Driver and Car. Cars table updated in separate process. What I need is to have property in Driver that allows me to read full car description and write only Id pointing to existing Car. Here is example:
@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 的反向引用.
Car object is just typical JPA object with no back reference to the Driver.
所以我试图通过这个实现的是:
So what I was trying to achieve by this is:
- 我可以使用详细的 JSON 视图阅读完整的汽车描述
- 或者我只能在 Short JsonView 中读取汽车的 Id
- 最重要的是,在创建新驱动程序时,我只想传入汽车的 JSON ID.这样我就不需要在坚持期间对 Car 进行 unnesesery 读取,而只需更新 Id.
我收到以下错误:
object references an unsaved transient instance - save the transient instance before flushing : com.Driver.car -> com.Car
我不想更新数据库中的 Car 实例,而只想从 Driver 引用它.知道如何实现我想要的吗?
I dont want to update instance of the Car in DB but rather just reference to it from Driver. Any idea how to achieve what I want?
谢谢.
更新:忘了说了,我在创建Driver时传递的Car ID是DB中现有Car的有效ID.
UPDATE:Forgot to mention that the ID of the Car that I pass during creation of the Driver is valid Id of the existing Car in DB.
推荐答案
该错误消息意味着您的对象图中有一个未显式持久化的瞬态实例.对象在 JPA 中可以具有的状态的简短回顾:
That error message means that you have have a transient instance in your object graph that is not explicitly persisted. Short recap of the statuses an object can have in JPA:
- Transient:尚未存储在数据库中的新对象(因此实体管理器不知道).没有设置 id.
- Managed:实体管理器跟踪的对象.托管对象是您在事务范围内使用的对象,一旦提交事务,对托管对象所做的所有更改都将自动存储.
- 分离:在事务提交后仍可访问的先前管理的对象.(事务外的托管对象.)有一个 id 集.
- Transient: A new object that has not yet been stored in the database (and is thus unknown to the entitymanager.) Does not have an id set.
- Managed: An object that the entitymanager keeps track of. Managed objects are what you work with within the scope of a transaction, and all changes done to a managed object will automatically be stored once the transaction is commited.
- Detached: A previously managed object that is still reachable after the transction commits. (A managed object outside a transaction.) Has an id set.
错误消息告诉您的是,您正在使用的(托管/分离的)Driver 对象包含对 Hibernate 未知的 Car 对象的引用(它是瞬态的).为了让 Hibernate 理解从 Driver 引用的任何未保存的 Car 实例都应该保存,你可以调用 EntityManager 的persist-method.
What the error message is telling you is that the (managed/detached) Driver-object you are working with holds a reference to a Car-object that is unknown to Hibernate (it is transient). In order to make Hibernate understand that any unsaved instances of Car being referenced from a Driver about be saved should also be saved you can call the persist-method of the EntityManager.
或者,您可以在persist上添加一个级联(我认为,只是从我的头顶来看,还没有测试过),它将在持久化驱动程序之前在汽车上执行持久化.
Alternatively, you can add a cascade on persist (I think, just from the top of my head, haven't tested it), which will execute a persist on the Car prior to persisting the Driver.
@ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.PERSIST)
@JoinColumn(name = "CAR_ID")
private Car car;
如果你使用entitymanager的merge-method来存储Driver,你应该添加CascadeType.MERGE
,或者两者都添加:
If you use the merge-method of the entitymanager to store the Driver, you should add CascadeType.MERGE
instead, or both:
@ManyToOne(fetch=FetchType.LAZY, cascade={ CascadeType.PERSIST, CascadeType.MERGE })
@JoinColumn(name = "CAR_ID")
private Car car;
这篇关于JPA 多对一关系 - 只需要保存 Id的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!