Search in sources :

Example 1 with SelfDirtinessTracker

use of org.hibernate.engine.spi.SelfDirtinessTracker in project hibernate-orm by hibernate.

the class AbstractSaveEventListener method saveWithGeneratedId.

/**
 * Prepares the save call using a newly generated id.
 *
 * @param entity The entity to be saved
 * @param entityName The entity-name for the entity to be saved
 * @param anything Generally cascade-specific information.
 * @param source The session which is the source of this save event.
 * @param requiresImmediateIdAccess does the event context require
 * access to the identifier immediately after execution of this method (if
 * not, post-insert style id generators may be postponed if we are outside
 * a transaction).
 *
 * @return The id used to save the entity; may be null depending on the
 *         type of id generator used and the requiresImmediateIdAccess value
 */
protected Serializable saveWithGeneratedId(Object entity, String entityName, Object anything, EventSource source, boolean requiresImmediateIdAccess) {
    callbackRegistry.preCreate(entity);
    if (entity instanceof SelfDirtinessTracker) {
        ((SelfDirtinessTracker) entity).$$_hibernate_clearDirtyAttributes();
    }
    EntityPersister persister = source.getEntityPersister(entityName, entity);
    Serializable generatedId = persister.getIdentifierGenerator().generate(source, entity);
    if (generatedId == null) {
        throw new IdentifierGenerationException("null id generated for:" + entity.getClass());
    } else if (generatedId == IdentifierGeneratorHelper.SHORT_CIRCUIT_INDICATOR) {
        return source.getIdentifier(entity);
    } else if (generatedId == IdentifierGeneratorHelper.POST_INSERT_INDICATOR) {
        return performSave(entity, null, persister, true, anything, source, requiresImmediateIdAccess);
    } else {
        // TODO: define toString()s for generators
        if (LOG.isDebugEnabled()) {
            LOG.debugf("Generated identifier: %s, using strategy: %s", persister.getIdentifierType().toLoggableString(generatedId, source.getFactory()), persister.getIdentifierGenerator().getClass().getName());
        }
        return performSave(entity, generatedId, persister, false, anything, source, true);
    }
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) Serializable(java.io.Serializable) IdentifierGenerationException(org.hibernate.id.IdentifierGenerationException) SelfDirtinessTracker(org.hibernate.engine.spi.SelfDirtinessTracker)

Example 2 with SelfDirtinessTracker

use of org.hibernate.engine.spi.SelfDirtinessTracker in project hibernate-orm by hibernate.

the class DefaultFlushEntityEventListener method dirtyCheck.

/**
 * Perform a dirty check, and attach the results to the event
 */
protected void dirtyCheck(final FlushEntityEvent event) throws HibernateException {
    final Object entity = event.getEntity();
    final Object[] values = event.getPropertyValues();
    final SessionImplementor session = event.getSession();
    final EntityEntry entry = event.getEntityEntry();
    final EntityPersister persister = entry.getPersister();
    final Serializable id = entry.getId();
    final Object[] loadedState = entry.getLoadedState();
    int[] dirtyProperties = session.getInterceptor().findDirty(entity, id, values, loadedState, persister.getPropertyNames(), persister.getPropertyTypes());
    if (dirtyProperties == null) {
        if (entity instanceof SelfDirtinessTracker) {
            if (((SelfDirtinessTracker) entity).$$_hibernate_hasDirtyAttributes()) {
                int[] dirty = persister.resolveAttributeIndexes(((SelfDirtinessTracker) entity).$$_hibernate_getDirtyAttributes());
                // HHH-12051 - filter non-updatable attributes
                // TODO: add Updateability to EnhancementContext and skip dirty tracking of those attributes
                int count = 0;
                for (int i : dirty) {
                    if (persister.getPropertyUpdateability()[i]) {
                        dirty[count++] = i;
                    }
                }
                dirtyProperties = count == 0 ? ArrayHelper.EMPTY_INT_ARRAY : count == dirty.length ? dirty : Arrays.copyOf(dirty, count);
            } else {
                dirtyProperties = ArrayHelper.EMPTY_INT_ARRAY;
            }
        } else {
            // see if the custom dirtiness strategy can tell us...
            class DirtyCheckContextImpl implements CustomEntityDirtinessStrategy.DirtyCheckContext {

                private int[] found;

                @Override
                public void doDirtyChecking(CustomEntityDirtinessStrategy.AttributeChecker attributeChecker) {
                    found = new DirtyCheckAttributeInfoImpl(event).visitAttributes(attributeChecker);
                    if (found != null && found.length == 0) {
                        found = null;
                    }
                }
            }
            DirtyCheckContextImpl context = new DirtyCheckContextImpl();
            session.getFactory().getCustomEntityDirtinessStrategy().findDirty(entity, persister, session, context);
            dirtyProperties = context.found;
        }
    }
    event.setDatabaseSnapshot(null);
    final boolean interceptorHandledDirtyCheck;
    boolean cannotDirtyCheck;
    if (dirtyProperties == null) {
        // Interceptor returned null, so do the dirtycheck ourself, if possible
        try {
            session.getEventListenerManager().dirtyCalculationStart();
            interceptorHandledDirtyCheck = false;
            // object loaded by update()
            cannotDirtyCheck = loadedState == null;
            if (!cannotDirtyCheck) {
                // dirty check against the usual snapshot of the entity
                dirtyProperties = persister.findDirty(values, loadedState, entity, session);
            } else if (entry.getStatus() == Status.DELETED && !event.getEntityEntry().isModifiableEntity()) {
                // fields should be updated.
                if (values != entry.getDeletedState()) {
                    throw new IllegalStateException("Entity has status Status.DELETED but values != entry.getDeletedState");
                }
                // Even if loadedState == null, we can dirty-check by comparing currentState and
                // entry.getDeletedState() because the only fields to be updated are those that
                // refer to transient entities that are being set to null.
                // - currentState contains the entity's current property values.
                // - entry.getDeletedState() contains the entity's current property values with
                // references to transient entities set to null.
                // - dirtyProperties will only contain properties that refer to transient entities
                final Object[] currentState = persister.getPropertyValues(event.getEntity());
                dirtyProperties = persister.findDirty(entry.getDeletedState(), currentState, entity, session);
                cannotDirtyCheck = false;
            } else {
                // dirty check against the database snapshot, if possible/necessary
                final Object[] databaseSnapshot = getDatabaseSnapshot(session, persister, id);
                if (databaseSnapshot != null) {
                    dirtyProperties = persister.findModified(databaseSnapshot, values, entity, session);
                    cannotDirtyCheck = false;
                    event.setDatabaseSnapshot(databaseSnapshot);
                }
            }
        } finally {
            session.getEventListenerManager().dirtyCalculationEnd(dirtyProperties != null);
        }
    } else {
        // the Interceptor handled the dirty checking
        cannotDirtyCheck = false;
        interceptorHandledDirtyCheck = true;
    }
    logDirtyProperties(id, dirtyProperties, persister);
    event.setDirtyProperties(dirtyProperties);
    event.setDirtyCheckHandledByInterceptor(interceptorHandledDirtyCheck);
    event.setDirtyCheckPossible(!cannotDirtyCheck);
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) Serializable(java.io.Serializable) SelfDirtinessTracker(org.hibernate.engine.spi.SelfDirtinessTracker) EntityEntry(org.hibernate.engine.spi.EntityEntry) SessionImplementor(org.hibernate.engine.spi.SessionImplementor)

Example 3 with SelfDirtinessTracker

use of org.hibernate.engine.spi.SelfDirtinessTracker in project hibernate-orm by hibernate.

the class EnhancerTestUtils method checkDirtyTracking.

/**
 * compares the dirty fields of an entity with a set of expected values
 */
public static void checkDirtyTracking(Object entityInstance, String... dirtyFields) {
    SelfDirtinessTracker selfDirtinessTracker = (SelfDirtinessTracker) entityInstance;
    assertEquals(dirtyFields.length > 0, selfDirtinessTracker.$$_hibernate_hasDirtyAttributes());
    String[] tracked = selfDirtinessTracker.$$_hibernate_getDirtyAttributes();
    assertEquals(dirtyFields.length, tracked.length);
    assertTrue(Arrays.asList(tracked).containsAll(Arrays.asList(dirtyFields)));
}
Also used : SelfDirtinessTracker(org.hibernate.engine.spi.SelfDirtinessTracker)

Example 4 with SelfDirtinessTracker

use of org.hibernate.engine.spi.SelfDirtinessTracker in project hibernate-orm by hibernate.

the class LazyAttributeLoadingInterceptor method takeCollectionSizeSnapshot.

// 
private void takeCollectionSizeSnapshot(Object target, String fieldName, Object value) {
    if (value != null && value instanceof Collection && target instanceof SelfDirtinessTracker) {
        CollectionTracker tracker = ((SelfDirtinessTracker) target).$$_hibernate_getCollectionTracker();
        if (tracker == null) {
            ((SelfDirtinessTracker) target).$$_hibernate_clearDirtyAttributes();
            tracker = ((SelfDirtinessTracker) target).$$_hibernate_getCollectionTracker();
        }
        tracker.add(fieldName, ((Collection) value).size());
    }
}
Also used : Collection(java.util.Collection) CollectionTracker(org.hibernate.bytecode.enhance.spi.CollectionTracker) SelfDirtinessTracker(org.hibernate.engine.spi.SelfDirtinessTracker)

Aggregations

SelfDirtinessTracker (org.hibernate.engine.spi.SelfDirtinessTracker)4 Serializable (java.io.Serializable)2 EntityPersister (org.hibernate.persister.entity.EntityPersister)2 Collection (java.util.Collection)1 CollectionTracker (org.hibernate.bytecode.enhance.spi.CollectionTracker)1 EntityEntry (org.hibernate.engine.spi.EntityEntry)1 SessionImplementor (org.hibernate.engine.spi.SessionImplementor)1 IdentifierGenerationException (org.hibernate.id.IdentifierGenerationException)1