Пример #1
0
        /// <summary>
        /// Perform the second step of 2-phase load. Fully initialize the entity instance.
        /// After processing a JDBC result set, we "resolve" all the associations
        /// between the entities which were instantiated and had their state
        /// "hydrated" into an array
        /// </summary>
        internal static void InitializeEntity(object entity, bool readOnly, ISessionImplementor session, PreLoadEvent preLoadEvent, PostLoadEvent postLoadEvent,
                                              Action <IEntityPersister, CachePutData> cacheBatchingHandler)
        {
            //TODO: Should this be an InitializeEntityEventListener??? (watch out for performance!)

            bool statsEnabled = session.Factory.Statistics.IsStatisticsEnabled;
            var  stopWath     = new Stopwatch();

            if (statsEnabled)
            {
                stopWath.Start();
            }

            IPersistenceContext persistenceContext = session.PersistenceContext;
            EntityEntry         entityEntry        = persistenceContext.GetEntry(entity);

            if (entityEntry == null)
            {
                throw new AssertionFailure("possible non-threadsafe access to the session");
            }
            IEntityPersister persister = entityEntry.Persister;
            object           id        = entityEntry.Id;

            object[] hydratedState = entityEntry.LoadedState;

            if (log.IsDebugEnabled())
            {
                log.Debug("resolving associations for {0}", MessageHelper.InfoString(persister, id, session.Factory));
            }

            IType[] types = persister.PropertyTypes;
            var     collectionToResolveIndexes = new List <int>(hydratedState.Length);

            for (int i = 0; i < hydratedState.Length; i++)
            {
                object value = hydratedState[i];
                if (!Equals(LazyPropertyInitializer.UnfetchedProperty, value) && !(Equals(BackrefPropertyAccessor.Unknown, value)))
                {
                    if (types[i].IsCollectionType)
                    {
                        // Resolve them last, because they may depend on other properties if they use a property-ref
                        collectionToResolveIndexes.Add(i);
                        continue;
                    }

                    hydratedState[i] = types[i].ResolveIdentifier(value, session, entity);
                }
            }

            foreach (var i in collectionToResolveIndexes)
            {
                hydratedState[i] = types[i].ResolveIdentifier(hydratedState[i], session, entity);
            }

            //Must occur after resolving identifiers!
            if (session.IsEventSource)
            {
                preLoadEvent.Entity    = entity;
                preLoadEvent.State     = hydratedState;
                preLoadEvent.Id        = id;
                preLoadEvent.Persister = persister;
                IPreLoadEventListener[] listeners = session.Listeners.PreLoadEventListeners;
                for (int i = 0; i < listeners.Length; i++)
                {
                    listeners[i].OnPreLoad(preLoadEvent);
                }
            }

            persister.SetPropertyValues(entity, hydratedState);

            ISessionFactoryImplementor factory = session.Factory;

            if (persister.HasCache && session.CacheMode.HasFlag(CacheMode.Put))
            {
                if (log.IsDebugEnabled())
                {
                    log.Debug("adding entity to second-level cache: {0}", MessageHelper.InfoString(persister, id, session.Factory));
                }

                object     version = Versioning.GetVersion(hydratedState, persister);
                CacheEntry entry   =
                    CacheEntry.Create(hydratedState, persister, version, session, entity);
                CacheKey cacheKey = session.GenerateCacheKey(id, persister.IdentifierType, persister.RootEntityName);

                if (cacheBatchingHandler != null && persister.IsBatchLoadable)
                {
                    cacheBatchingHandler(
                        persister,
                        new CachePutData(
                            cacheKey,
                            persister.CacheEntryStructure.Structure(entry),
                            version,
                            persister.IsVersioned ? persister.VersionType.Comparator : null,
                            UseMinimalPuts(session, entityEntry)));
                }
                else
                {
                    bool put =
                        persister.Cache.Put(cacheKey, persister.CacheEntryStructure.Structure(entry), session.Timestamp, version,
                                            persister.IsVersioned ? persister.VersionType.Comparator : null,
                                            UseMinimalPuts(session, entityEntry));

                    if (put && factory.Statistics.IsStatisticsEnabled)
                    {
                        factory.StatisticsImplementor.SecondLevelCachePut(persister.Cache.RegionName);
                    }
                }
            }

            bool isReallyReadOnly = readOnly;

            if (!persister.IsMutable)
            {
                isReallyReadOnly = true;
            }
            else
            {
                object proxy = persistenceContext.GetProxy(entityEntry.EntityKey);
                if (proxy != null)
                {
                    // there is already a proxy for this impl
                    // only set the status to read-only if the proxy is read-only
                    isReallyReadOnly = ((INHibernateProxy)proxy).HibernateLazyInitializer.ReadOnly;
                }
            }

            if (isReallyReadOnly)
            {
                //no need to take a snapshot - this is a
                //performance optimization, but not really
                //important, except for entities with huge
                //mutable property values
                persistenceContext.SetEntryStatus(entityEntry, Status.ReadOnly);
            }
            else
            {
                //take a snapshot
                TypeHelper.DeepCopy(hydratedState, persister.PropertyTypes, persister.PropertyUpdateability, hydratedState, session);
                persistenceContext.SetEntryStatus(entityEntry, Status.Loaded);
            }

            persister.AfterInitialize(entity, session);

            if (session.IsEventSource)
            {
                postLoadEvent.Entity    = entity;
                postLoadEvent.Id        = id;
                postLoadEvent.Persister = persister;
                IPostLoadEventListener[] listeners = session.Listeners.PostLoadEventListeners;
                for (int i = 0; i < listeners.Length; i++)
                {
                    listeners[i].OnPostLoad(postLoadEvent);
                }
            }

            if (log.IsDebugEnabled())
            {
                log.Debug("done materializing entity {0}", MessageHelper.InfoString(persister, id, session.Factory));
            }

            if (statsEnabled)
            {
                stopWath.Stop();
                factory.StatisticsImplementor.LoadEntity(persister.EntityName, stopWath.Elapsed);
            }
        }
Пример #2
0
        public override void Execute()
        {
            ISessionImplementor session = Session;
            object           id         = Id;
            IEntityPersister persister  = Persister;
            object           instance   = Instance;

            bool      statsEnabled = Session.Factory.Statistics.IsStatisticsEnabled;
            Stopwatch stopwatch    = null;

            if (statsEnabled)
            {
                stopwatch = Stopwatch.StartNew();
            }

            bool veto = PreUpdate();

            ISessionFactoryImplementor factory = Session.Factory;

            if (persister.IsVersionPropertyGenerated)
            {
                // we need to grab the version value from the entity, otherwise
                // we have issues with generated-version entities that may have
                // multiple actions queued during the same flush
                previousVersion = persister.GetVersion(instance);
            }

            CacheKey ck = null;

            if (persister.HasCache)
            {
                ck    = session.GenerateCacheKey(id, persister.IdentifierType, persister.RootEntityName);
                slock = persister.Cache.Lock(ck, previousVersion);
            }

            if (!veto)
            {
                persister.Update(id, state, dirtyFields, hasDirtyCollection, previousState, previousVersion, instance, null, session);
            }

            EntityEntry entry = Session.PersistenceContext.GetEntry(instance);

            if (entry == null)
            {
                throw new AssertionFailure("Possible nonthreadsafe access to session");
            }

            if (entry.Status == Status.Loaded || persister.IsVersionPropertyGenerated)
            {
                // get the updated snapshot of the entity state by cloning current state;
                // it is safe to copy in place, since by this time no-one else (should have)
                // has a reference  to the array
                TypeHelper.DeepCopy(state, persister.PropertyTypes, persister.PropertyCheckability, state, Session);
                if (persister.HasUpdateGeneratedProperties)
                {
                    // this entity defines property generation, so process those generated
                    // values...
                    persister.ProcessUpdateGeneratedProperties(id, instance, state, Session);
                    if (persister.IsVersionPropertyGenerated)
                    {
                        nextVersion = Versioning.GetVersion(state, persister);
                    }
                }
                // have the entity entry perform post-update processing, passing it the
                // update state and the new version (if one).
                entry.PostUpdate(instance, state, nextVersion);
            }

            if (persister.HasCache)
            {
                if (persister.IsCacheInvalidationRequired || entry.Status != Status.Loaded)
                {
                    persister.Cache.Evict(ck);
                }
                else
                {
                    CacheEntry ce = CacheEntry.Create(state, persister, nextVersion, Session, instance);
                    cacheEntry = persister.CacheEntryStructure.Structure(ce);

                    bool put = persister.Cache.Update(ck, cacheEntry, nextVersion, previousVersion);

                    if (put && factory.Statistics.IsStatisticsEnabled)
                    {
                        factory.StatisticsImplementor.SecondLevelCachePut(Persister.Cache.RegionName);
                    }
                }
            }

            PostUpdate();

            if (statsEnabled && !veto)
            {
                stopwatch.Stop();
                factory.StatisticsImplementor.UpdateEntity(Persister.EntityName, stopwatch.Elapsed);
            }
        }
        public void PutCloneToCache(AggregateRoot aggregateRootInfo)
        {
            // don't waste cycles add/trimming
            if (IsEffectivelyDisabled)
            {
                return;
            }

            var aggregateRootId    = aggregateRootInfo.Id;
            var entriesForThisRoot = _cacheEntries.GetOrAdd(aggregateRootId, id => new ConcurrentDictionary <long, CacheEntry>());

            var entrySuccessfullyAdded = entriesForThisRoot.TryAdd(aggregateRootInfo.GlobalSequenceNumberCutoff, CacheEntry.Create(aggregateRootInfo));

            if (entrySuccessfullyAdded)
            {
                Interlocked.Increment(ref _currentNumberOfCacheEntries);
            }

            PossiblyTrimCache();
        }
Пример #4
0
        public override void Execute()
        {
            IEntityPersister    persister = Persister;
            ISessionImplementor session   = Session;
            object instance = Instance;
            object id       = Id;

            bool      statsEnabled = Session.Factory.Statistics.IsStatisticsEnabled;
            Stopwatch stopwatch    = null;

            if (statsEnabled)
            {
                stopwatch = Stopwatch.StartNew();
            }

            bool veto = PreInsert();

            // Don't need to lock the cache here, since if someone
            // else inserted the same pk first, the insert would fail
            if (!veto)
            {
                persister.Insert(id, State, instance, Session);

                EntityEntry entry = Session.PersistenceContext.GetEntry(instance);
                if (entry == null)
                {
                    throw new AssertionFailure("Possible nonthreadsafe access to session");
                }

                entry.PostInsert();

                if (persister.HasInsertGeneratedProperties)
                {
                    persister.ProcessInsertGeneratedProperties(id, instance, State, Session);
                    if (persister.IsVersionPropertyGenerated)
                    {
                        version = Versioning.GetVersion(State, persister);
                    }
                    entry.PostUpdate(instance, State, version);
                }
            }

            ISessionFactoryImplementor factory = Session.Factory;

            if (IsCachePutEnabled(persister))
            {
                CacheEntry ce = CacheEntry.Create(State, persister, persister.HasUninitializedLazyProperties(instance), version, session, instance);
                cacheEntry = persister.CacheEntryStructure.Structure(ce);

                CacheKey ck  = Session.GenerateCacheKey(id, persister.IdentifierType, persister.RootEntityName);
                bool     put = persister.Cache.Insert(ck, cacheEntry, version);

                if (put && factory.Statistics.IsStatisticsEnabled)
                {
                    factory.StatisticsImplementor.SecondLevelCachePut(Persister.Cache.RegionName);
                }
            }

            PostInsert();

            if (statsEnabled && !veto)
            {
                stopwatch.Stop();
                factory.StatisticsImplementor.InsertEntity(Persister.EntityName, stopwatch.Elapsed);
            }
        }
Пример #5
0
        public override void Execute()
        {
            IEntityPersister    persister = Persister;
            ISessionImplementor session   = Session;
            object instance = Instance;
            object id       = Id;

            bool      statsEnabled = Session.Factory.Statistics.IsStatisticsEnabled;
            Stopwatch stopwatch    = null;

            if (statsEnabled)
            {
                stopwatch = Stopwatch.StartNew();
            }

            bool veto = PreInsert();

            var wasDelayed = false;

            // Don't need to lock the cache here, since if someone
            // else inserted the same pk first, the insert would fail
            if (!veto)
            {
                // The identifier may be a foreign delayed identifier, which at this point should have been resolved.
                if (id is DelayedPostInsertIdentifier delayed)
                {
                    wasDelayed = true;
                    id         = delayed.ActualId ??
                                 throw new InvalidOperationException(
                                           $"The delayed foreign identifier {delayed} has not been resolved before insertion of a {instance}");
                }
                persister.Insert(id, State, instance, Session);

                EntityEntry entry = Session.PersistenceContext.GetEntry(instance);
                if (entry == null)
                {
                    throw new AssertionFailure("Possible nonthreadsafe access to session");
                }

                entry.PostInsert();
                if (wasDelayed)
                {
                    Session.PersistenceContext.ReplaceDelayedEntityIdentityInsertKeys(entry.EntityKey, id);
                }

                if (persister.HasInsertGeneratedProperties)
                {
                    persister.ProcessInsertGeneratedProperties(id, instance, State, Session);
                    if (persister.IsVersionPropertyGenerated)
                    {
                        version = Versioning.GetVersion(State, persister);
                    }
                    entry.PostUpdate(instance, State, version);
                }
            }

            ISessionFactoryImplementor factory = Session.Factory;

            if (IsCachePutEnabled(persister))
            {
                CacheEntry ce = CacheEntry.Create(State, persister, version, session, instance);
                cacheEntry = persister.CacheEntryStructure.Structure(ce);

                CacheKey ck  = Session.GenerateCacheKey(id, persister.IdentifierType, persister.RootEntityName);
                bool     put = persister.Cache.Insert(ck, cacheEntry, version);

                if (put && factory.Statistics.IsStatisticsEnabled)
                {
                    factory.StatisticsImplementor.SecondLevelCachePut(Persister.Cache.RegionName);
                }
            }

            PostInsert();

            if (statsEnabled && !veto)
            {
                stopwatch.Stop();
                factory.StatisticsImplementor.InsertEntity(Persister.EntityName, stopwatch.Elapsed);
            }
        }