如何在使用 findBy... 时跳过不需要的刷新,这会导致:对象引用未保存的瞬态实例

问题描述 投票:0回答:1

我的问题可能在于休眠在 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”)

如果所有这些都是在没有事务的情况下完成的,那么它可以工作,但应该使用事务,因为会执行其他代码和数据库调用。

spring-boot hibernate
1个回答
0
投票

默认情况下,Hibernate 在提交事务之前以及 JPQL/HQL 和本机 SQL 查询之前刷新。但是,可以使用

EntityManager.setFlushMode()
方法更改此策略。

您可能想要使用

COMMIT
模式,在这种模式下,如果可能的话,Hibernate 会尝试延迟刷新直到事务结束。

entityManager.setFlushMode(FlushModeType.COMMIT)

或者

MANUAL
模式,您负责自己冲洗。

Session session = entityManager.unwrap(Session.class);
session.setHibernateFlushMode(FlushMode.MANUAL);

有关更多信息,请参阅Hibernate 用户指南

© www.soinside.com 2019 - 2024. All rights reserved.