private DirtyCheckAttributeInfoImpl(FlushEntityEvent event) { this.event = event; this.persister = event.getEntityEntry().getPersister(); this.numberOfAttributes = persister.getPropertyNames().length; }
private static boolean useMinimalPuts(SharedSessionContractImplementor session, EntityEntry entityEntry) { if ( session.getFactory().getSessionFactoryOptions().isMinimalPutsEnabled() ) { return session.getCacheMode() != CacheMode.REFRESH; } else { return entityEntry.getPersister().hasLazyProperties() && entityEntry.getPersister().isLazyPropertiesCacheable(); } }
@Override public Object proxyFor(Object impl) throws HibernateException { final EntityEntry e = getEntry( impl ); if ( e == null ) { return impl; } return proxyFor( e.getPersister(), e.getEntityKey(), impl ); }
/** * Perform the afterInitialize() step. This needs to be done after the collections have been properly initialized * thus a separate step. * * @param entity The entity being loaded * @param session The Session */ public static void afterInitialize( final Object entity, final SharedSessionContractImplementor session) { final PersistenceContext persistenceContext = session.getPersistenceContext(); final EntityEntry entityEntry = persistenceContext.getEntry( entity ); entityEntry.getPersister().afterInitialize( entity, session ); }
/** * process cascade save/update at the start of a flush to discover * any newly referenced entity that must be passed to saveOrUpdate(), * and also apply orphan delete */ private void prepareEntityFlushes(EventSource session, PersistenceContext persistenceContext) throws HibernateException { LOG.debug( "Processing flush-time cascades" ); final Object anything = getAnything(); //safe from concurrent modification because of how concurrentEntries() is implemented on IdentityMap for ( Map.Entry<Object,EntityEntry> me : persistenceContext.reentrantSafeEntityEntries() ) { // for ( Map.Entry me : IdentityMap.concurrentEntries( persistenceContext.getEntityEntries() ) ) { EntityEntry entry = (EntityEntry) me.getValue(); Status status = entry.getStatus(); if ( status == Status.MANAGED || status == Status.SAVING || status == Status.READ_ONLY ) { cascadeOnFlush( session, entry.getPersister(), me.getKey(), anything ); } } }
/** * Perform whatever processing is encapsulated here before completion of the transaction. * * @param session The session on which the transaction is preparing to complete. */ @Override public void doBeforeTransactionCompletion(SessionImplementor session) { final EntityPersister persister = entry.getPersister(); final Object nextVersion = persister.forceVersionIncrement( entry.getId(), entry.getVersion(), session ); entry.forceLocked( object, nextVersion ); } }
private boolean canClearEntityEntryReference(){ if( managedEntity.$$_hibernate_getEntityEntry() == null ) { return true; } if( !(managedEntity.$$_hibernate_getEntityEntry() instanceof ImmutableEntityEntry) ) { return true; } else if( managedEntity.$$_hibernate_getEntityEntry().getPersister().canUseReferenceCacheEntries() ) { return false; } return true; } }
@Override public void replaceDelayedEntityIdentityInsertKeys(EntityKey oldKey, Serializable generatedId) { final Object entity = entitiesByKey.remove( oldKey ); final EntityEntry oldEntry = entityEntryContext.removeEntityEntry( entity ); parentsByChild.clear(); final EntityKey newKey = session.generateEntityKey( generatedId, oldEntry.getPersister() ); addEntity( newKey, entity ); addEntry( entity, oldEntry.getStatus(), oldEntry.getLoadedState(), oldEntry.getRowId(), generatedId, oldEntry.getVersion(), oldEntry.getLockMode(), oldEntry.isExistsInDatabase(), oldEntry.getPersister(), oldEntry.isBeingReplicated() ); }
@Override public void forceFlush(EntityEntry entityEntry) throws HibernateException { if ( log.isDebugEnabled() ) { log.debugf( "Flushing to force deletion of re-saved object: %s", MessageHelper.infoString( entityEntry.getPersister(), entityEntry.getId(), getFactory() ) ); } if ( persistenceContext.getCascadeLevel() > 0 ) { throw new ObjectDeletedException( "deleted object would be re-saved by cascade (remove deleted object from associations)", entityEntry.getId(), entityEntry.getPersister().getEntityName() ); } checkOpenOrWaitingForAutoClose(); doFlush(); }
@Override public void doBeforeTransactionCompletion(SessionImplementor session) { final EntityPersister persister = entry.getPersister(); if ( !entry.isExistsInDatabase() ) { // HHH-9419: We cannot check for a version of an entry we ourselves deleted return; } final Object latestVersion = persister.getCurrentVersion( entry.getId(), session ); if ( !entry.getVersion().equals( latestVersion ) ) { throw new OptimisticLockException( object, "Newer version [" + latestVersion + "] of entity [" + MessageHelper.infoString( entry.getEntityName(), entry.getId() ) + "] found in database" ); } } }
protected boolean handleInterception(FlushEntityEvent event) { SessionImplementor session = event.getSession(); EntityEntry entry = event.getEntityEntry(); EntityPersister persister = entry.getPersister(); Object entity = event.getEntity(); //give the Interceptor a chance to modify property values final Object[] values = event.getPropertyValues(); final boolean intercepted = invokeInterceptor( session, entity, entry, values, persister ); //now we might need to recalculate the dirtyProperties array if ( intercepted && event.isDirtyCheckPossible() ) { dirtyCheck( event ); } return intercepted; }
/** * Performs all necessary checking to determine if an entity needs an SQL update * to synchronize its state to the database. Modifies the event by side-effect! * Note: this method is quite slow, avoid calling if possible! */ protected final boolean isUpdateNecessary(FlushEntityEvent event) throws HibernateException { EntityPersister persister = event.getEntityEntry().getPersister(); Status status = event.getEntityEntry().getStatus(); if ( !event.isDirtyCheckPossible() ) { return true; } else { int[] dirtyProperties = event.getDirtyProperties(); if ( dirtyProperties != null && dirtyProperties.length != 0 ) { return true; //TODO: suck into event class } else { return hasDirtyCollections( event, persister, status ); } } }
@Override public String bestGuessEntityName(Object object) { if ( object instanceof HibernateProxy ) { LazyInitializer initializer = ( (HibernateProxy) object ).getHibernateLazyInitializer(); // it is possible for this method to be called during flush processing, // so make certain that we do not accidentally initialize an uninitialized proxy if ( initializer.isUninitialized() ) { return initializer.getEntityName(); } object = initializer.getImplementation(); } EntityEntry entry = persistenceContext.getEntry( object ); if ( entry == null ) { return guessEntityName( object ); } else { return entry.getPersister().getEntityName(); } }
private Object[] getValues(Object entity, EntityEntry entry, boolean mightBeDirty, SessionImplementor session) { final Object[] loadedState = entry.getLoadedState(); final Status status = entry.getStatus(); final EntityPersister persister = entry.getPersister(); final Object[] values; if ( status == Status.DELETED ) { //grab its state saved at deletion values = entry.getDeletedState(); } else if ( !mightBeDirty && loadedState != null ) { values = loadedState; } else { checkId( entity, persister, entry.getId(), session ); // grab its current state values = persister.getPropertyValues( entity ); checkNaturalId( persister, entry, values, loadedState, session ); } return values; }
@Override public void lock(Serializable id, Object version, Object object, int timeout, SharedSessionContractImplementor session) { if ( !lockable.isVersioned() ) { throw new HibernateException( "[" + lockMode + "] not supported for non-versioned entities [" + lockable.getEntityName() + "]" ); } final EntityEntry entry = session.getPersistenceContext().getEntry( object ); final EntityPersister persister = entry.getPersister(); final Object nextVersion = persister.forceVersionIncrement( entry.getId(), entry.getVersion(), session ); entry.forceLocked( object, nextVersion ); }
private boolean isUpdateNecessary(final FlushEntityEvent event, final boolean mightBeDirty) { final Status status = event.getEntityEntry().getStatus(); if ( mightBeDirty || status == Status.DELETED ) { // compare to cached state (ignoring collections unless versioned) dirtyCheck( event ); if ( isUpdateNecessary( event ) ) { return true; } else { if ( SelfDirtinessTracker.class.isInstance( event.getEntity() ) ) { ( (SelfDirtinessTracker) event.getEntity() ).$$_hibernate_clearDirtyAttributes(); } event.getSession() .getFactory() .getCustomEntityDirtinessStrategy() .resetDirty( event.getEntity(), event.getEntityEntry().getPersister(), event.getSession() ); return false; } } else { return hasDirtyCollections( event, event.getEntityEntry().getPersister(), status ); } }
@Override public String getEntityName(Object object) { checkOpen(); // checkTransactionSynchStatus(); if ( object instanceof HibernateProxy ) { if ( !persistenceContext.containsProxy( object ) ) { throw new TransientObjectException( "proxy was not associated with the session" ); } object = ( (HibernateProxy) object ).getHibernateLazyInitializer().getImplementation(); } EntityEntry entry = persistenceContext.getEntry( object ); if ( entry == null ) { throwTransientObjectException( object ); } return entry.getPersister().getEntityName(); }
@Override public LockMode getCurrentLockMode(Object object) throws HibernateException { checkOpen(); checkTransactionSynchStatus(); if ( object == null ) { throw new NullPointerException( "null object passed to getCurrentLockMode()" ); } if ( object instanceof HibernateProxy ) { object = ( (HibernateProxy) object ).getHibernateLazyInitializer().getImplementation( this ); if ( object == null ) { return LockMode.NONE; } } EntityEntry e = persistenceContext.getEntry( object ); if ( e == null ) { throw new TransientObjectException( "Given object not associated with the session" ); } if ( e.getStatus() != Status.MANAGED ) { throw new ObjectDeletedException( "The given object was deleted", e.getId(), e.getPersister().getEntityName() ); } return e.getLockMode(); }
/** * PostLoad cannot occur during initializeEntity, as that call occurs *before* * the Set collections are added to the persistence context by Loader. * Without the split, LazyInitializationExceptions can occur in the Entity's * postLoad if it acts upon the collection. * * HHH-6043 * * @param entity The entity * @param session The Session * @param postLoadEvent The (re-used) post-load event */ public static void postLoad( final Object entity, final SharedSessionContractImplementor session, final PostLoadEvent postLoadEvent) { if ( session.isEventSource() ) { final PersistenceContext persistenceContext = session.getPersistenceContext(); final EntityEntry entityEntry = persistenceContext.getEntry( entity ); postLoadEvent.setEntity( entity ).setId( entityEntry.getId() ).setPersister( entityEntry.getPersister() ); final EventListenerGroup<PostLoadEventListener> listenerGroup = session.getFactory() .getServiceRegistry() .getService( EventListenerRegistry.class ) .getEventListenerGroup( EventType.POST_LOAD ); for ( PostLoadEventListener listener : listenerGroup.listeners() ) { listener.onPostLoad( postLoadEvent ); } } }
/** * Convenience method to retrieve an entities next version value */ private Object getNextVersion(FlushEntityEvent event) throws HibernateException { EntityEntry entry = event.getEntityEntry(); EntityPersister persister = entry.getPersister(); if ( persister.isVersioned() ) { Object[] values = event.getPropertyValues(); if ( entry.isBeingReplicated() ) { return Versioning.getVersion( values, persister ); } else { int[] dirtyProperties = event.getDirtyProperties(); final boolean isVersionIncrementRequired = isVersionIncrementRequired( event, entry, persister, dirtyProperties ); final Object nextVersion = isVersionIncrementRequired ? Versioning.increment( entry.getVersion(), persister.getVersionType(), event.getSession() ) : entry.getVersion(); //use the current version Versioning.setVersion( values, nextVersion, persister ); return nextVersion; } } else { return null; } }