假设我们有一些看起来像这样的实体(我会尽量简化):
@Entity
class MainEntity {
//nothing too special here
}
@Entity
class DependentEntity implements Serializable {
@Id
@OneToOne( fetch = FetchType.LAZY, optional = false )
@JoinColumn( name = "mainEntityId", insertable = false, updatable = false, nullable = false )
private MainEntity mainEntity;
}
@Entity
@IdClass(AnotherDependentEntityId.class)
class AnotherDependentEntity {
@Id
@ManyToOne( fetch = FetchType.LAZY, optional = false )
@JoinColumn( name = "mainEntityId", insertable = false, updatable = false, nullable = false )
private MainEntity mainEntity;
@Id
@Column ( name = "type", insertable = false, updatable = false, nullable = false )
private SomeEnum type;
}
如您所见,每个
DependentEntity
最多可以有一个MainEntity
,但可以有多个AnotherDependentEntity
-每个SomeEnum
值可以有一个。现在,每当有人创建
MainEntity
时,我们也要创建必要的DependentEntity
和AnotherDependentEntity
实例。我们正在尝试通过PostInsertEventListener
和依赖的子会话来做到这一点,如下所示:Session subSession = pEvent.getSession().sessionWithOptions()
.autoClose( true)
.autoJoinTransactions( true )
.noInterceptor()
.openSession();
subSession.saveOrUpdate( new DependentEntity( mainEntity ) );
subSession.saveOrUpdate( new AnotherDependentEntity ( mainEntity, SomeEnum.VALUE1 ) );
它对于
DependentEntity
效果很好,但对于AnotherDependentEntity
则不行,我们无法弄清原因。对于第二个
saveOrUpdate()
,我们收到以下消息:HHH000346:托管刷新期间发生错误[org.hibernate.HibernateException:复合标识符的任何部分都不能为null]
(在org.hibernate.tuple.entity.AbstractEntityTuplizer $ IncredablySillyJpaMapsIdMappedIdentifierValueMarshaller.getIdentifier(AbstractEntityTuplizer.java:367))
调试代码时,似乎在
AnotherDependentEntity
上执行了persist时,即使mainEntity
属性是以前设置的,它也为null(并且正确设置了原始会话中的相同调试位置)。这导致以下印象:
mainEntity
必须以某种方式设置为null,但即使值观察断点也不会被触发,因此它必须通过反射发生(并且我们验证了这两种情况下它都是相同的AnotherDependentEntity
实例)。所以这是问题:
有谁知道为什么/部分ID设置为空?也许我们做错了所有事情,并且有一种更好的方法(请注意:由于某些原因,我们不能将引用添加到
MainEntity
中,而只能使其级联)。环境:Wildfly 10.1.0和Hibernate 5.2.7
编辑:
我们观察到的另一件事:在调试时,可以看到实体持久程序同时引用了该实体和id类的实例(即
AnotherDependentEntityId
)。 id-class包含两个值,即两个字段均为null,而实际实体的id已部分为null。 最佳答案
我在hibernate.atlassian中发现了一个问题。尝试使用此解决方案...