gpt4 book ai didi

java - 如何解决 honeSTLy 没有意义的 TransientObjectException

转载 作者:行者123 更新时间:2023-11-30 07:22:12 25 4
gpt4 key购买 nike

我使用的是 Hibernate 4.1,每当我尝试存储已添加到对象集合中的临时标记列表时,我都会收到以下异常。

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.myapplication.domain.Tag
at org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:249)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:459)
at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:132)
at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:811)

现在,我需要稍微解释一下。我的 Tag 类有一个同义词集合。在添加此关系之前,我从未遇到过此异常并且一切正常:

<class name="com.myapplication.domain.Tag">
<id name="id" column="tag_id" type="long">
<generator class="native"/>
</id>
<property name="term" index="termIndex" unique="true" not-null="true" />
<property name="description" />
<property name="approved" />

<many-to-one name="masterTag" column="master_tag_id"
class="com.myapplication.domain.Tag" />

<bag name="synonyms">
<key column="master_tag_id" />
<one-to-many class="com.myapplication.domain.Tag" />
</bag>
</class>

这是一个对象如何映射标签。 Tags类只是一个组件类。 Tags.list 是 Hibernate 持久化的实际集合。

    <component name="tags">
<bag name="list" table="user_to_tag">
<key column="user_id" />
<many-to-many class="com.myapplication.domain.Tag" column="tag_id"/>
</bag>
</component>

我试图保存在数据库中的标签实际上根本不包含任何同义词,所以我不认为它与 transient 同义词标签有任何关系。我不希望这些级联,这就是为什么我没有在 <bag> 上给它级联属性的原因。标签。

用户通常会通过字符串列表将标签插入系统。我这样做是因为我想在保存包含标签的对象时即时创建标签或同时链接到现有标签。也许这比它的值(value)更麻烦?如果我只让它们链接到存在的标签,那么我知道我可以解决我的问题。也许在 Hibernate 中处理即时标记创建的复杂性有点超出它所能处理的范围?

这是我用来一次性保存新标签/现有标签的方法。每当一个对象被保存到数据库时,它首先调用这个方法来持久化标签集合:

public void saveAll(Tags tags) {
List<Tag> tagsToOverwrite = new ArrayList<Tag>();

Iterator<Tag> i = tags.getList().iterator();
while(i.hasNext()) {
Tag tag = i.next();

if(stopListService.hasWord(tag.getTerm())) {
i.remove();
} else {
if(tag.isTransient()) {
Tag dbTag = findByTerm(tag.getTerm());

if(dbTag == null) {
save(tag);
} else {
tagsToOverwrite.add(dbTag);
}
}
}
}

tags.overwriteAll(tagsToOverwrite);
}

出于某种原因,它在 Tag dbTag = findByTerm(tag.getTerm()); 上失败了那是它抛出 TransientObjectException 的时候.这个方法只是一个简单的查询:

public Tag findByTerm(final String term) {
Query query = getCurrentSession().createQuery(
"from Tag tag " +
"where tag.term = :term "
);

return (Tag) query
.setParameter("term", term.toLowerCase())
.setCacheable(true)
.uniqueResult(); // This is where the exception gets thrown specifically
}

我不确定为什么这个方法会抛出这个异常,因为我只想在保存之前检查它是否在数据库中。为什么我只是在查询对象,却提示对象没有被保存?

如果标签列表只包含一个标签,该方法有效。仅当要保存的临时标签数为 2 个或更多时,它才会失败。例如,这失败了:

@Test
public void saveShouldPersistTransientTags() {
User user = userRepository.find(1);
// makes list of 3 tags that are transient (id = 0)
user.getTags().setTagsAsString("training learning business");

userRepository.save(user);
flush();

user = userRepository.find(1);
assertEquals(3, user.getTags().getList().size());
}

这是 UserRepository.save() 方法:

@Override
public void save(User user) {
tagRepository.saveAll(user.getTags());

super.save(user);
}

如您所见,我试图在保存用户之前先保存所有临时标签(或在数据库中查找它们)。然而,Hibernate 似乎想要坚持 user.tags.list通话中收款tagRepository.saveAll(user.getTags());在异常被抛出的位置,即使我从来没有要求它。

当然,如果我删除 synonyms从 Hibernate 映射收集,这个测试通过没有任何问题。它仅在我启用 synonym 时失败集合,只有在到达 learning 时才会失败标记(training 标记未在数据库中找到,并且保留得很好。)

知道为什么同义词集合会导致这个问题吗?

如果我不能很快解决这个问题,为了节省时间,我很想为此使用 JDBC,因为 Hibernate 在这种情况下的复杂性并不是一件好事。鉴于这种行为,我认为这甚至可能是一个错误。这对我来说仍然没有任何意义。

最佳答案

当您准备好查询时,Hibernate 可能会查看其托管对象。那些脏的,它将尝试刷新到数据库,以便查询访问最新的数据存储。在您的代码中的某处,您正在向集合添加非托管(可能是新的?)同义词,然后当 Hibernate 试图通过刷新脏对象来“帮助”您时,您会得到该异常。

关于java - 如何解决 honeSTLy 没有意义的 TransientObjectException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12922003/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com