我有以下情况:
实体命令:
@Entity
public class Command {
@Id
@GeneratedValue
private long id;
@Column(nullable=false)
private Date timeOfExecution;
--constructors, getters, setters...--
扩展Command的实体CmdTest:
@Entity
@SecondaryTable(name = "CmdTest")
public class CmdTest extends Command{
@Column(table = "CmdTest", nullable = false)
private String testParam;
@OneToOne
@JoinColumn(table="CmdTest")
private Citizen citizen;
-- getters, setters, construcotr --
}
实体公民:
@Entity
public class Citizen {
@Id
@GeneratedValue
private long id;
@Column(nullable=false)
private String name;
@OneToOne(mappedBy="citizen")
private CmdTest cmdTest;
-- getters, setters, constructor --
}
正如您所看到的,我在Citizen和CmdTest之间存在双向关系。 我想首先坚持公民,然后是CmdTest。
我正在使用Web服务来调用MyBean的initTest()方法。 MyBean创建一个Citizen和一个CmdTest实例,然后尝试先保留公民,然后是CmdTest。
这是我的initTest()方法:
public void initTest() {
CmdTest cmd = new CmdTest();
cmd.setTestParam("asd");
cmd.setTimeOfExecution(new Date());
Citizen citizen = new Citizen();
citizen.setName("John Doe");
citizen.setCmdTest(cmd);
cmd.setCitizen(citizen);
em.persist(citizen);
em.persist(cmd);
}
通过在公民字段上设置@JoinColumn(table =“CmdTest”)我尝试告诉JPA在CmdTest表中保留citizen_id外键,如果我注释掉该行,一切正常,但我在内部获得了citizen_id外键命令表。
当我把@JoinColumn(table =“CmdTest”)时,我得到以下异常:Not-null property references a transient value - transient instance must be saved before current operation
我知道我可以先坚持CmdTest将瞬态CmdTest对象放在持久化上下文中,然后是Citizen,它会起作用。我试过了。
但是,我想知道,为什么这不起作用?这是Hibernate或JPA中的错误吗?我似乎无法找到原因...
答案 0 :(得分:0)
您遇到此异常是因为您尝试使用对citizen
对象的引用来保存cmd
对象,而您没有将cmd
实例持久保存到数据库中。
hibernate如何工作,它持久化并管理数据库中的对象,当它试图保持citizen
实例时,它发现它被映射到一个对象(cmd
),当它试图在数据库中构建这种关系时,它将使用cmd
查找相应的id
对象,但它不会发现它无法找到它&#39 ;为什么你会得到例外Not-null property references a transient value - transient instance must be saved before current operation
,因为cmd
没有被保留。
在尝试保存persist/save
对象之前,您需要cmd
citizen
对象到数据库,这就是您的代码应该如何:
public void initTest() {
CmdTest cmd = new CmdTest();
cmd.setTestParam("asd");
cmd.setTimeOfExecution(new Date());
Citizen citizen = new Citizen();
citizen.setName("John Doe");
em.persist(cmd);
citizen.setCmdTest(cmd);
cmd.setCitizen(citizen);
em.persist(citizen);
}
所以这不是Hibernate
中的错误,但这就是它的工作方式,您无法将对象映射到另一个transient
(而不是{{ 1}})一个。