提问者:小点点

Hibernate-随机发生错误:非空属性引用瞬态值-瞬态实例必须在当前操作之前保存


我无法理解将实体保存到数据库时出错的原因。我想澄清一下,有时实体会被保存。

我有两个实体:

@Data
@Entity
@Table(...)
public class RuleCollection {
    // Fields
}

@Data
@Entity
@Table(...)
public class RuleAttribute {
    // Fields

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "rule_collection_id", nullable = false)
    private RuleCollection ruleCollection;
}

Rule属性必须包含RuleCollection。

首先,在处理JSON文件期间,保存"RuleCollection"对象:

Map<UUID, RuleCollection> ruleCollectionsMap = 
json.getRuleCollections().stream().map(ruleCollectionDto -> {
        RuleCollection ruleCollection = new RuleCollection();
        // Set ruleCollection fields
        return ruleCollectionRepository.save(ruleCollection);
    }
).collect(Collectors.toMap(RuleCollection::getId, Function.identity()));

之后,填充并保存“规则属性”:

List<RuleAttribute> attributes = json.getAttributes().stream()
    .filter(attr -> ruleCollectionsMap.get(attr.getCollectionId()) != null)
    .parallel()
    .map(attr -> {
        RuleAttribute ruleAttribute = new RuleAttribute();
        // Set ruleAttribute fields
        ruleAttribute.setRuleCollection(ruleCollectionsMap.get(attr.getCollectionId()));
        return ruleAttribute;
    }
).collect(Collectors.toList());
ruleAttributeRepository.save(attributes);

然后可能会出现错误:

无法初始化代理-无会话;嵌套异常是org. hibernate.LazyFirst alizationException:无法初始化代理-无会话

如果我在流中保存属性,错误会发生变化:

.map(attr -> {
    ...
    return ruleAttributeRepository.save(ruleAttribute);
    }
).collect(Collectors.toList());

org. hibernate.TranentProperty tyValueException:非空属性引用一个瞬态值-必须在当前操作之前保存瞬态实例:RuleProperties.ruleCollection-

我不知道可能是什么问题,因为“规则收集”已经保存了。

我尝试更改类“RuleAt在StackOverflow上有类似问题的帖子中提到:

@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "rule_collection_id", nullable = false)
private RuleCollection ruleCollection;

错误发生在相同的数据上。有一次,我可以不出错地保存数据,从数据库中删除它,当我再次保存它时得到这个错误。

UPD:

RuleCollection Repository和RuleAtbanteRepository扩展org.springframework.data. reposity.CrudRepository


共1个答案

匿名用户

保存和处理在具有@Transactional属性的方法中。

显然,在这种情况下,并行流违反了Hibernate会话:Java。

在搜索了类似的问题后,我找到了几个解决方案:

>

  • 将属性@Transactional中的参数传播设置为传播。REQUIRES_NEW。但是,此选项不可靠,因为由于主会话不知道子会话的状态,它可能导致数据丢失或类似问题。

    不要使用并行流。

    如果无法拒绝并行流,则需要去掉@Transactional属性,先设置必要的数据,然后在标有@Transactional属性的单独方法中进行顺序保存。例如:

    public void saveData(Json json) {
        Map<UUID, RuleCollection> ruleCollectionsMap = // Set data
        List<RuleAttribute> attributes = // Set data
    
        saveInDB(ruleCollectionsMap.values(), attributes);
    }
    
    @Transactional
    private void saveInDB(Collection<RuleCollection> ruleCollections, Collection<RuleAttribute> attributes) {
        ruleCollectionRepository.save(ruleCollections);
        ruleAttributeRepository.save(attributes);
    }