对象引用了一个未保存的瞬时实例,在刷新之前请先保存该瞬时实例。

4
我有一个自连接员工实体类,包含id、name和ref列,与自身有关系。我想创建该类的新实例并将其持久化到数据库中。
首先,我创建了一个Employee类的实例并将其命名为manager。然后,我从Employee表中获取了一条记录,并将这些值设置为manager对象的属性:Id = 1,Name =“A”,RefId = null。之后,我再次创建了一个Employee类的实例,并设置它的属性值如下:emp.Name =“B”,emp.Ref = manager。最后,我使用base.Add(resource)方法将其持久化。此时,Nhibernate引发了以下错误:“对象引用了未保存的瞬态实例,请在刷新之前保存瞬态实例”。
以下是映射文件内容:
<class name="Employee" table="Employee" schema="dbo" optimistic-lock="none" lazy="true">
    <id name="Id" access="property" column="Id">
        <generator class="identity" />
    </id>
    <property name="Name" type="String" column="Name" length="50" />
    <property name="RefId" type="Int64" column="RefId"  insert="false" update="false"/>
    <many-to-one name="Ref" class="Employee" column="RefId" not-null="false" fetch="select" />
 class>

请帮我解决这个错误。 谢谢。


只是为了明确,您的意思是有一个自我引用的对象,还是有两个员工对象之间的引用?也就是说,是否有两个员工记录,它们之间有外键,或者只有一个员工记录,其中包含指向主键的外键。 - bzarah
同时,拥有员工实体的映射文件或代码将非常有帮助。 - bzarah
感谢您的建议。我会尝试更加清晰明了。我已编辑了我的问题。这里有两条员工记录,它们之间有外键关系。 - Vahid Ghadiri
1个回答

4
假设实体1是数据库中的现有记录,实体2是您要创建且具有对实体1的引用的新记录。Hibernate告诉您正在保存的新实体(实体2)具有对实体1(来自数据库的实体)的引用,并且实体1具有必须在保存实体2之前保存的未保存更改。最简单的方法是先保存实体1,然后再保存实体2。但是,我认为真正的问题是您如何获取Entity1的实例。
您说您创建并命名一个employee的实例,然后从employee表中获取记录。如果您想更新表中的现有记录,请为什么不先获取实体,然后进行编辑?为什么要实例化一个对象?我不确定的另一件事是对象之间的关系是否是双向的。也就是说,实体1具有对实体2的外键,而实体2也具有对实体1的外键。如果是这种情况,您需要确保两次分配“Ref”属性。Entityy1.Ref = Entity2 AND ALSO Entity2.Ref = Entity1.

我不想编辑数据库中已存在的实体记录Entity1,但我必须获取它,以便将其分配给具有员工类型的Entity2的RefId属性。 - Vahid Ghadiri
与此同时,仅Entity2具有引用到其经理Entity1的FK,但是Entity1在其refId属性中具有null值。我的目标是在表中拥有这两条记录:一个在其refId列中具有null值的经理以及一个在其refId列中具有managerId值的员工。 - Vahid Ghadiri
更简单了!如果您只需要从Entity2创建对Entity1的引用,那么您甚至不需要获取记录。如果您知道Entity1的id值,您可以使用Entity2.Ref = Session.Load(idValue)。这将为您连接引用。我刚刚注意到一些问题,我早该发现了。您需要删除RefId属性。 <Many-to-One>是唯一需要创建引用的内容。RefId是多余的,并且可能会给您带来一些问题。 - bzarah
你说得对。拥有两个RefId和<Many-To-One>属性让我很困扰。但是我更喜欢从refid中删除insert="false" update="false"并将其粘贴到<Many_to_One>属性中,这解决了我的问题。感谢您的建议。祝好运。 - Vahid Ghadiri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接