我的问题可能在于休眠在 findBy() 方法之后刷新并抛出错误,因为更新的实体尚未设置。 我的课程看起来像这样。
public class CodelistItem {
@ToStringExclude
@OneToMany(mappedBy = "codelistItem", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private List<CodelistItemField> codelistItemFields = new ArrayList<>();
}
public class CodelistItemField {
@ToStringExclude
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CODELIST_ITEM_FIELD_DEFINITION_ID", unique = false, nullable = false)
private CodelistItemFieldDefinition codelistItemFieldDefinition;
}
public class CodelistItemFieldDefinition { //this one exists before any other classes are created
private Long id;
private String code;
}
如果我想更新代码列表项,就会出现问题。
我使用一个映射结构来删除所有 ItemFields,创建新的 ItemFields,将它们添加到 codelistItem.codelistItemFields 中,并使用代码创建新的定义,这是当时唯一可用的信息,并使将来更容易。
那么问题来了:
我想添加定义参考,但如果我调用
codelistItemFieldDefinitionRepository.findByCodelistCodeAndCode(codelistItem.getCodelist().getCode(),codelistItem.getCodelistItemFields().get(0).getCodelistItemFieldDefinition().getCode());
,我会收到上述错误(“org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing
”)。我预计会进行一些不需要的(我自己的)实体状态检查,但是有人可以解释检查的原因以及解决此问题的可能性吗?
真正的定义对象是持久化的,所以我不使用cascade.ALL。 (但我尝试了并收到错误“not-null property”)
如果所有这些都是在没有事务的情况下完成的,那么它可以工作,但应该使用事务,因为会执行其他代码和数据库调用。
默认情况下,Hibernate 在提交事务之前以及 JPQL/HQL 和本机 SQL 查询之前刷新。但是,可以使用
EntityManager.setFlushMode()
方法更改此策略。
您可能想要使用
COMMIT
模式,在这种模式下,如果可能的话,Hibernate 会尝试延迟刷新直到事务结束。
entityManager.setFlushMode(FlushModeType.COMMIT)
或者
MANUAL
模式,您负责自己冲洗。
Session session = entityManager.unwrap(Session.class);
session.setHibernateFlushMode(FlushMode.MANUAL);
有关更多信息,请参阅Hibernate 用户指南。