我遇到了这样的情况,我需要将分离的对象重新附加到hibernate会话,尽管会话中可能已经存在相同标识的对象,这将导致错误。

现在,我可以做两件事之一。

getHibernateTemplate()。更新(obj) 当且仅当对象在hibernate会话中还不存在时,这才有效。当我以后需要它时,抛出异常,声明具有给定标识符的对象已经存在于会话中。 getHibernateTemplate()。合并(obj) 当且仅当hibernate会话中存在对象时,此操作才有效。如果稍后使用此方法,则在需要对象处于会话中时抛出异常。

对于这两种场景,我如何将会话附加到对象?我不想使用异常来控制这个问题解决方案的流程,因为一定有更优雅的解决方案……


当前回答

直截了当的回答:您可能正在寻找一个扩展的持久性上下文。这是Seam框架背后的主要原因之一…如果您特别纠结于在Spring中使用Hibernate,请查看Seam的这篇文档。

外交回答:这在Hibernate文档中有描述。如果你需要更多的说明,请参阅Hibernate的Java持久化第9.3.2节“使用分离对象”。如果您正在使用Hibernate做CRUD以外的事情,我强烈推荐您阅读这本书。

其他回答

直截了当的回答:您可能正在寻找一个扩展的持久性上下文。这是Seam框架背后的主要原因之一…如果您特别纠结于在Spring中使用Hibernate,请查看Seam的这篇文档。

外交回答:这在Hibernate文档中有描述。如果你需要更多的说明,请参阅Hibernate的Java持久化第9.3.2节“使用分离对象”。如果您正在使用Hibernate做CRUD以外的事情,我强烈推荐您阅读这本书。

我这样做在c#与NHibernate,但它应该在Java中以同样的方式工作:

public virtual void Attach()
{
    if (!HibernateSessionManager.Instance.GetSession().Contains(this))
    {
        ISession session = HibernateSessionManager.Instance.GetSession();
        using (ITransaction t = session.BeginTransaction())
        {
            session.Lock(this, NHibernate.LockMode.None);
            t.Commit();
        }
    }
}

对每个对象都调用First Lock,因为Contains总是false。问题是NHibernate通过数据库id和类型来比较对象。Contains使用equals方法,如果没有被覆盖,则通过引用进行比较。使用equals方法,它可以在没有任何异常的情况下工作:

public override bool Equals(object obj)
{
    if (this == obj) { 
        return true;
    } 
    if (GetType() != obj.GetType()) {
        return false;
    }
    if (Id != ((BaseObject)obj).Id)
    {
        return false;
    }
    return true;
}

对不起,似乎不能添加评论(还?)。

使用Hibernate 3.5.0-Final

尽管已经弃用了session# lock方法,但javadoc建议使用session# buildLockRequest(LockOptions)#lock(entity),如果您确保您的关联具有cascade=lock,惰性加载也不是问题。

我的attach方法看起来有点像

MyEntity attach(MyEntity entity) {
    if(getSession().contains(entity)) return entity;
    getSession().buildLockRequest(LockOptions.NONE).lock(entity);
    return entity;

初步测试表明它很有效。

ReplicationMode.LATEST_VERSION尝试getHibernateTemplate () .replicate(实体)

财产冬眠。Allow_refresh_detached_entity为我做了这个技巧。但这是一个普遍的规则,所以如果你只想在某些情况下这样做,那就不太合适了。我希望这能有所帮助。

在Hibernate 5.4.9上测试

SessionFactoryOptionsBuilder