/** * Based on configured options, will either return a pre-existing proxy, generate a new proxy, or * perform an actual load. * * @return The result of the proxy/load operation. * @throws HibernateException */ protected Object proxyOrLoad( final LoadEvent event, final EntityPersister persister, final EntityKey keyToLoad, final LoadEventListener.LoadType options) throws HibernateException { if (log.isTraceEnabled()) { log.trace( "loading entity: " + MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory())); } if (!persister.hasProxy()) { // this class has no proxies (so do a shortcut) return load(event, persister, keyToLoad, options); } else { final PersistenceContext persistenceContext = event.getSession().getPersistenceContext(); // look for a proxy Object proxy = persistenceContext.getProxy(keyToLoad); if (proxy != null) { return returnNarrowedProxy(event, persister, keyToLoad, options, persistenceContext, proxy); } else { if (options.isAllowProxyCreation()) { return createProxyIfNecessary(event, persister, keyToLoad, options, persistenceContext); } else { // return a newly loaded object return load(event, persister, keyToLoad, options); } } } }
@SuppressWarnings("unchecked") @Override /** * Handle the given delete event. This is the cascaded form. * * @param event The delete event. * @param transientEntities The cache of entities already deleted * @throws HibernateException */ public void onDelete(DeleteEvent event, Set transientEntities) throws HibernateException { final EventSource source = event.getSession(); final PersistenceContext persistenceContext = source.getPersistenceContext(); Object entity = persistenceContext.unproxyAndReassociate(event.getObject()); EntityEntry entityEntry = persistenceContext.getEntry(entity); final EntityPersister persister = source.getEntityPersister(event.getEntityName(), entity); final Object version; if (persister.isVersioned()) { version = persister.getVersion(entity, source.getEntityMode()); // Make sure version has not changed on deleted entities if ((entity instanceof TimelineEntity) && !((TimelineEntity) entity).isNew()) { if (!persister.getVersionType().isEqual(version, entityEntry.getVersion())) { throw new StaleObjectStateException(persister.getEntityName(), entityEntry.getId()); } } } super.onDelete(event, transientEntities); }
/** * Given that there is no pre-existing proxy. Check if the entity is already loaded. If it is, * return the entity, otherwise create and return a proxy. */ private Object createProxyIfNecessary( final LoadEvent event, final EntityPersister persister, final EntityKey keyToLoad, final LoadEventListener.LoadType options, final PersistenceContext persistenceContext) { Object existing = persistenceContext.getEntity(keyToLoad); if (existing != null) { // return existing object or initialized proxy (unless deleted) log.trace("entity found in session cache"); if (options.isCheckDeleted()) { EntityEntry entry = persistenceContext.getEntry(existing); throwObjectDeletedIfNecessary(event, entry); } return existing; } else { log.trace("creating new proxy for entity"); // return new uninitialized proxy Object proxy = persister.createProxy(event.getEntityId(), event.getSession()); persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey(keyToLoad); persistenceContext.addProxy(keyToLoad, proxy); return proxy; } }
/** Given that there is a pre-existing proxy. Initialize it if necessary; narrow if necessary. */ private Object returnNarrowedProxy( final LoadEvent event, final EntityPersister persister, final EntityKey keyToLoad, final LoadEventListener.LoadType options, final PersistenceContext persistenceContext, final Object proxy) { log.trace("entity proxy found in session cache"); LazyInitializer li = ((HibernateProxy) proxy).getHibernateLazyInitializer(); if (li.isUnwrap()) { return li.getImplementation(); } // return existing or narrowed proxy Object impl = options.isAllowProxyCreation() ? null : load(event, persister, keyToLoad, options); return persistenceContext.narrowProxy(proxy, persister, keyToLoad, impl); }
private Object assembleCacheEntry( final CacheEntry entry, final Serializable id, final EntityPersister persister, final LoadEvent event) throws HibernateException { final Object optionalObject = event.getInstanceToLoad(); final EventSource session = event.getSession(); final SessionFactoryImplementor factory = session.getFactory(); if (log.isTraceEnabled()) { log.trace( "assembling entity from second-level cache: " + MessageHelper.infoString(persister, id, factory)); } EntityPersister subclassPersister = factory.getEntityPersister(entry.getSubclass()); Object result = optionalObject == null ? session.instantiate(subclassPersister, id) : optionalObject; // make it circular-reference safe TwoPhaseLoad.addUninitializedCachedEntity( new EntityKey(id, subclassPersister, session.getEntityMode()), result, subclassPersister, LockMode.NONE, entry.areLazyPropertiesUnfetched(), entry.getVersion(), session); Type[] types = subclassPersister.getPropertyTypes(); Object[] values = entry.assemble( result, id, subclassPersister, session.getInterceptor(), session); // intializes result by side-effect TypeFactory.deepCopy( values, types, subclassPersister.getPropertyUpdateability(), values, session); Object version = Versioning.getVersion(values, subclassPersister); if (log.isTraceEnabled()) log.trace("Cached Version: " + version); final PersistenceContext persistenceContext = session.getPersistenceContext(); persistenceContext.addEntry( result, Status.MANAGED, values, null, id, version, LockMode.NONE, true, subclassPersister, false, entry.areLazyPropertiesUnfetched()); subclassPersister.afterInitialize(result, entry.areLazyPropertiesUnfetched(), session); persistenceContext.initializeNonLazyCollections(); // upgrade the lock if necessary: // lock(result, lockMode); // PostLoad is needed for EJB3 // TODO: reuse the PostLoadEvent... PostLoadEvent postLoadEvent = new PostLoadEvent(session).setEntity(result).setId(id).setPersister(persister); PostLoadEventListener[] listeners = session.getListeners().getPostLoadEventListeners(); for (int i = 0; i < listeners.length; i++) { listeners[i].onPostLoad(postLoadEvent); } return result; }
public void execute() throws HibernateException { Serializable id = getId(); EntityPersister persister = getPersister(); SessionImplementor session = getSession(); Object instance = getInstance(); boolean veto = preDelete(); Object version = this.version; 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 version = persister.getVersion(instance, session.getEntityMode()); } final CacheKey ck; if (persister.hasCache()) { ck = new CacheKey( id, persister.getIdentifierType(), persister.getRootEntityName(), session.getEntityMode(), session.getFactory()); lock = persister.getCacheAccessStrategy().lockItem(ck, version); } else { ck = null; } if (!isCascadeDeleteEnabled && !veto) { persister.delete(id, version, instance, session); } // postDelete: // After actually deleting a row, record the fact that the instance no longer // exists on the database (needed for identity-column key generation), and // remove it from the session cache final PersistenceContext persistenceContext = session.getPersistenceContext(); EntityEntry entry = persistenceContext.removeEntry(instance); if (entry == null) { throw new AssertionFailure("possible nonthreadsafe access to session"); } entry.postDelete(); persistenceContext.removeEntity(entry.getEntityKey()); persistenceContext.removeProxy(entry.getEntityKey()); if (persister.hasCache()) { persister.getCacheAccessStrategy().remove(ck); } postDelete(); if (getSession().getFactory().getStatistics().isStatisticsEnabled() && !veto) { getSession() .getFactory() .getStatisticsImplementor() .deleteEntity(getPersister().getEntityName()); } }