回滚标识符 NHibernate

Posted

技术标签:

【中文标题】回滚标识符 NHibernate【英文标题】:Rolling back identifiers NHibernate 【发布时间】:2009-11-04 04:11:57 【问题描述】:

如果事务中止,我想让 NHibernate 回滚在事务期间保存的任何实体的标识符。我使用的是 NHibernate 2.1.0,默认情况下它不这样做。我想出了以下解决方案,它在一定程度上起作用:

public class RevertIdentifiersEventListener : DefaultSaveEventListener

    private class RevertIdentiferSynchronization : ISynchronization
    
        private IClassMetadata _classMetadata;
        private object _entity;
        private object _originalIdentifier;

        public RevertIdentiferSynchronization(IClassMetadata classMetadata, object entity)
        
            _classMetadata = classMetadata;
            _entity = entity;
            _originalIdentifier = classMetadata.GetIdentifier(entity, NHibernate.EntityMode.Poco);
        

        #region ISynchronization Members

        public void AfterCompletion(bool success)
        
            if (success == false)
            
                _classMetadata.SetIdentifier(_entity, _originalIdentifier, NHibernate.EntityMode.Poco);
            
        

        public void BeforeCompletion()
        
        

        #endregion
    


    protected override object EntityIsTransient(SaveOrUpdateEvent @event)
    
        IEntityPersister entityPersister = @event.Session.GetEntityPersister(@event.EntityName, @event.Entity);
        if (entityPersister.HasIdentifierProperty)
        
            RevertIdentiferSynchronization revertIdentiferSynchronization = new RevertIdentiferSynchronization(entityPersister.ClassMetadata, @event.Entity);
            if (@event.Session.Transaction.IsActive)
            
                @event.Session.Transaction.RegisterSynchronization(revertIdentiferSynchronization);
            
        
        return base.EntityIsTransient(@event);
    


问题在于,如果实体的保存将保存级联到关联实体,则该实体的标识符不会回滚。上面的 EntityIsTransient 不会被这些实体调用,它只会被显式调用 Save 的那些实体调用。

关于在级联时如何使其工作的任何建议?

【问题讨论】:

【参考方案1】:

我不确定您要在什么情况下中止交易,但我假设您需要这样的东西:

    using( var transaction = SessionFactory.GetSession().BeginTransaction())
    
        try
        
           session.Update(entity); // throws exception for some reason
        
        catch(Exception ex)
        
            transaction.Rollback(); // rollback the transaction
        
    

【讨论】:

她在问你回滚后做什么。我也有同样的问题。如果实体包含对新子模型的引用并且 NHibernate 尝试插入该子实体,它会更改其标识符(Guid),使其不再是新的 Guid()。我们需要以某种方式回滚子对象的标识符,以便我们知道它从未被插入。

以上是关于回滚标识符 NHibernate的主要内容,如果未能解决你的问题,请参考以下文章

即使有事务回滚,SQL 标识(自动编号)也会增加

即使使用事务回滚,SQL标识(自动编号)也会增加

spring的@Transactional(rollbackFor=Exception.class)的使用

Sql Server - 计数器列,即使事务回滚也会递增

Git-回滚操作

一起看看MySQL中的隐藏列