如何修复hibernate警告(HHH000470)?

有时,我得到这个警告信息:

 aug 09,2017 3:40:02 AM org.hibernate.collection.internal.AbstractPersistentCollection setCurrentSession
警告:HHH000470:为集合定义了意外会话,但该集合未连接到该会话。 持久集合一次只能与一个会话相关联。 覆盖会话。 收集:[royaleserver.database.entity.PlayerEntity.homeChests#1757]

PlayerEntity:

public class PlayerEntity implements Identifiable, Serializable { ... @OneToMany(mappedBy = "player") private Set homeChests = new HashSet(); public Set getHomeChests() { return homeChests; } public PlayerEntity setHomeChests(Set homeChests) { this.homeChests = homeChests; return this; } } 

HomeChestEntity:

 public class HomeChestEntity implements Serializable { @Id @ManyToOne @PrimaryKeyJoinColumn(name = "player_id", referencedColumnName = "id") private PlayerEntity player; ... } 

在此警告消息之后,会话将关闭。

 java.lang.IllegalStateException:Session / EntityManager已关闭
    在org.hibernate.internal.AbstractSharedSessionContract.checkOpen(AbstractSharedSessionContract.java:337)
    在org.hibernate.engine.spi.SharedSessionContractImplementor.checkOpen(SharedSessionContractImplementor.java:135)
    在org.hibernate.internal.AbstractSharedSessionContract.checkOpenOrWaitingForAutoClose(AbstractSharedSessionContract.java:343)
    在org.hibernate.internal.SessionImpl.getPersistenceContext(SessionImpl.java:2275)
     ...

有什么问题?

如果您在两个线程中管理持久化对象,混合从两个不同会话收集的对象,或者如果您将对象添加到瞬态对象上的集合并稍后尝试保存它(可能是不同的消息,则通常会发生此类错误虽然)。

在所有情况下,它归结为不正确的会话管理。

你的问题是这个代码:

 public PlayerEntity setHomeChests(Set homeChests) { this.homeChests = homeChests; return this; } 

您可能会使用属性中给出的瞬态集替换关系(在this.homeChests字段中)。

更好的解决方案是:

 if(this.homeChests == null) { this.homeChests = new HashSet<>(homeChests); } else { // very simply, you possibly better sync the new elements in... this.homeChests.addAll(homeChests); } 

如果你不能保证,这个解决方案也有问题,这些元素都是新的。 您也可能遇到陈旧的对象。

正如我所说,您需要注意您的会话处理涵盖树上的所有操作。 不要简单地在新会话中使用临时对象,您需要将它们合并或再次加载它们。 我建议你仔细看看有关hibernate会话处理的stackoverflow问题。 此外,hibernate文档介绍了如何使用hibernate管理会话或实体管理器的一些最佳实践。