Hibernate生成器序列之间的内部差异,并为id = 0分配

时间:2015-05-06 14:10:04

标签: java hibernate generator

内心的冬眠行为中有一些我不明白的行为。

我有一个正常 hibernate配置的类,其中另一个参考。

我的主要课程

<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>

下面的参考类

<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>

我在这个参考表中有一些行: id,property1,property2 0 val1x val2x
1 val1y val2y 2 val1z val2z 。

我的问题是,当我尝试插入一个新的MyClass实例时,它引用了ID为1,2的MyReferenceClass,...,我没有问题。但是当我尝试插入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)

我通过在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:我知道我的第一个文件中的序列是假的,因为我们这里没有序列,这实际上是一个旧的遗留代码,我正在进化,但我不明白为什么它以前工作过。

1 个答案:

答案 0 :(得分:0)

看起来MyReferenceClass的id映射的unsaved-value属性默认为0,并且没有为MyClass启用级联更新。

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

将发电机更改为&#34;已分配&#34;意味着你承担了填充id的全部责任,而Hibernate不必担心它。

要使序列生成器能够正常工作,您可以在将对象添加到集合之前保存对象,或者在集合的映射上设置级联。