Hibernate 生成器序列和为 id = 0 分配的内部差异

Hibernate inner differences between generator sequence and assigned for id = 0

我不明白内部休眠行为中的某些内容。

我有一个 正常 休眠配置 class 有另一个参考。

下面是我的校长class

<hibernate-mapping package="com.my.package">

        <class name="MyClass" table="MY_TABLE">
            <id name="id" column="ID">
                <generator class="sequence">
                    <param name="sequence">SEQ_MY_TABLE</param>
                </generator>
            </id>
            <!-- reference -->
            <many-to-one class="MyReferenceClass" fetch="select" name="myReference">
                <column name="ID" not-null="true"/>
            </many-to-one>
            <!-- some other properties ... -->
            .
            .
    </class>
</hibernate-mapping>

和下面的参考class

<hibernate-mapping package="com.my.package">
    <class name="MyReferenceClass" table="MY_REFERENCE_CLASS">
        <id name="id" type="long">
            <column name="ID" precision="22" scale="0" />
            <generator class="sequence" />
        </id>
    </class>

    <!-- Some propeties -->
    .
    .

</hibernate-mapping>

我在这篇 table 的参考文献中有几行: 编号,属性 1,属性 2 0 val1x val2x
1 val1y val2y 2 val1z val2z . .

我的问题是,当我尝试插入一个引用了 MyReferenceClass 且 id 为 1,2,... 的新 MyClass 实例时,我没有遇到任何问题。但是当我尝试插入一个 id = 0 时,出现以下异常:

org.hibernate.PropertyValueException: not-null property references a null or transient value: com.my.package.MyClass.myReference
    at org.hibernate.engine.Nullability.checkNullability(Nullability.java:72)
    at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:290)
    at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
    at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:94)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
    at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)

我通过将生成器 class 从顺序更改为在 MyReferenceClass.hbm.xml 中分配来解决问题:

<hibernate-mapping package="com.my.package">
        <class name="MyReferenceClass" table="MY_REFERENCE_CLASS">
            <id name="id" type="long">
                <column name="ID" precision="22" scale="0" />
                <generator class="assigned" />
            </id>
        </class>

        <!-- Some propeties -->
        .
        .

</hibernate-mapping>

问题是我不知道为什么它只在我的 id = 0 时不起作用,而不是每次都不起作用。

在 Hibernate Framework 的这一部分中,我不理解哪个机制?

PS:我知道我的第一个文件中的序列是错误的,因为我们这里没有序列,这实际上是我正在进化的旧遗留代码,但我不明白它为什么起作用之前。

似乎 MyReferenceClass 的 id 映射的未保存值属性默认为 0,并且未为 MyClass 启用级联更新。

当您添加一个 id 不是 unsaved-value 的对象时,Hibernate 假定您引用的是现有行。当您添加一个 id 与 unsaved-value 匹配的对象时,Hibernate 会假定该实体是瞬态的并且需要持久化以便从序列中获取新值。并且由于您的集合不是级联的,Hibernate 假定引用是对现有的非瞬态实体的引用。

将生成器更改为 "assigned" 意味着您承担填充 id 的全部责任,Hibernate 无需担心。

要使用序列生成器进行此操作,您可以在将对象添加到集合之前保存对象,或者在集合的映射上设置级联。