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 无需担心。
要使用序列生成器进行此操作,您可以在将对象添加到集合之前保存对象,或者在集合的映射上设置级联。
我不明白内部休眠行为中的某些内容。
我有一个 正常 休眠配置 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 无需担心。
要使用序列生成器进行此操作,您可以在将对象添加到集合之前保存对象,或者在集合的映射上设置级联。