Search in sources :

Example 31 with EntityEntry

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

the class SessionImpl method logRemoveOrphanBeforeUpdates.

private void logRemoveOrphanBeforeUpdates(String timing, String entityName, Object entity) {
    final EntityEntry entityEntry = persistenceContext.getEntry(entity);
    log.tracef("%s remove orphan beforeQuery updates: [%s]", timing, entityEntry == null ? entityName : MessageHelper.infoString(entityName, entityEntry.getId()));
}
Also used : EntityEntry(org.hibernate.engine.spi.EntityEntry)

Example 32 with EntityEntry

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

the class DynamicBatchingEntityLoaderBuilder method performOrderedMultiLoad.

@SuppressWarnings("unchecked")
private List performOrderedMultiLoad(OuterJoinLoadable persister, Serializable[] ids, SharedSessionContractImplementor session, MultiLoadOptions loadOptions) {
    assert loadOptions.isOrderReturnEnabled();
    final List result = CollectionHelper.arrayList(ids.length);
    final LockOptions lockOptions = (loadOptions.getLockOptions() == null) ? new LockOptions(LockMode.NONE) : loadOptions.getLockOptions();
    final int maxBatchSize;
    if (loadOptions.getBatchSize() != null && loadOptions.getBatchSize() > 0) {
        maxBatchSize = loadOptions.getBatchSize();
    } else {
        maxBatchSize = session.getJdbcServices().getJdbcEnvironment().getDialect().getDefaultBatchLoadSizingStrategy().determineOptimalBatchLoadSize(persister.getIdentifierType().getColumnSpan(session.getFactory()), ids.length);
    }
    final List<Serializable> idsInBatch = new ArrayList<>();
    final List<Integer> elementPositionsLoadedByBatch = new ArrayList<>();
    for (int i = 0; i < ids.length; i++) {
        final Serializable id = ids[i];
        final EntityKey entityKey = new EntityKey(id, persister);
        if (loadOptions.isSessionCheckingEnabled()) {
            // look for it in the Session first
            final Object managedEntity = session.getPersistenceContext().getEntity(entityKey);
            if (managedEntity != null) {
                if (!loadOptions.isReturnOfDeletedEntitiesEnabled()) {
                    final EntityEntry entry = session.getPersistenceContext().getEntry(managedEntity);
                    if (entry.getStatus() == Status.DELETED || entry.getStatus() == Status.GONE) {
                        // put a null in the result
                        result.add(i, null);
                        continue;
                    }
                }
                // if we did not hit the continue above, there is already an
                // entry in the PC for that entity, so use it...
                result.add(i, managedEntity);
                continue;
            }
        }
        // if we did not hit any of the continues above, then we need to batch
        // load the entity state.
        idsInBatch.add(ids[i]);
        if (idsInBatch.size() >= maxBatchSize) {
            performOrderedBatchLoad(idsInBatch, lockOptions, persister, session);
        }
        // Save the EntityKey instance for use later!
        result.add(i, entityKey);
        elementPositionsLoadedByBatch.add(i);
    }
    if (!idsInBatch.isEmpty()) {
        performOrderedBatchLoad(idsInBatch, lockOptions, persister, session);
    }
    for (Integer position : elementPositionsLoadedByBatch) {
        // the element value at this position in the result List should be
        // the EntityKey for that entity; reuse it!
        final EntityKey entityKey = (EntityKey) result.get(position);
        Object entity = session.getPersistenceContext().getEntity(entityKey);
        if (entity != null && !loadOptions.isReturnOfDeletedEntitiesEnabled()) {
            // make sure it is not DELETED
            final EntityEntry entry = session.getPersistenceContext().getEntry(entity);
            if (entry.getStatus() == Status.DELETED || entry.getStatus() == Status.GONE) {
                // the entity is locally deleted, and the options ask that we not return such entities...
                entity = null;
            }
        }
        result.set(position, entity);
    }
    return result;
}
Also used : EntityKey(org.hibernate.engine.spi.EntityKey) Serializable(java.io.Serializable) EntityEntry(org.hibernate.engine.spi.EntityEntry) LockOptions(org.hibernate.LockOptions) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List)

Example 33 with EntityEntry

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

the class AbstractEntityPersister method update.

/**
	 * Update an object
	 */
public void update(final Serializable id, final Object[] fields, final int[] dirtyFields, final boolean hasDirtyCollection, final Object[] oldFields, final Object oldVersion, final Object object, final Object rowId, final SharedSessionContractImplementor session) throws HibernateException {
    // apply any pre-update in-memory value generation
    if (getEntityMetamodel().hasPreUpdateGeneratedValues()) {
        final InMemoryValueGenerationStrategy[] strategies = getEntityMetamodel().getInMemoryValueGenerationStrategies();
        for (int i = 0; i < strategies.length; i++) {
            if (strategies[i] != null && strategies[i].getGenerationTiming().includesUpdate()) {
                fields[i] = strategies[i].getValueGenerator().generateValue((Session) session, object);
                setPropertyValue(object, i, fields[i]);
            // todo : probably best to add to dirtyFields if not-null
            }
        }
    }
    //note: dirtyFields==null means we had no snapshot, and we couldn't get one using select-beforeQuery-update
    //	  oldFields==null just means we had no snapshot to begin with (we might have used select-beforeQuery-update to get the dirtyFields)
    final boolean[] tableUpdateNeeded = getTableUpdateNeeded(dirtyFields, hasDirtyCollection);
    final int span = getTableSpan();
    final boolean[] propsToUpdate;
    final String[] updateStrings;
    EntityEntry entry = session.getPersistenceContext().getEntry(object);
    // in the process of being deleted.
    if (entry == null && !isMutable()) {
        throw new IllegalStateException("Updating immutable entity that is not in session yet!");
    }
    if ((entityMetamodel.isDynamicUpdate() && dirtyFields != null)) {
        // We need to generate the UPDATE SQL when dynamic-update="true"
        propsToUpdate = getPropertiesToUpdate(dirtyFields, hasDirtyCollection);
        // don't need to check laziness (dirty checking algorithm handles that)
        updateStrings = new String[span];
        for (int j = 0; j < span; j++) {
            updateStrings[j] = tableUpdateNeeded[j] ? generateUpdateString(propsToUpdate, j, oldFields, j == 0 && rowId != null) : null;
        }
    } else if (!isModifiableEntity(entry)) {
        // We need to generate UPDATE SQL when a non-modifiable entity (e.g., read-only or immutable)
        // needs:
        // - to have references to transient entities set to null beforeQuery being deleted
        // - to have version incremented do to a "dirty" association
        // If dirtyFields == null, then that means that there are no dirty properties to
        // to be updated; an empty array for the dirty fields needs to be passed to
        // getPropertiesToUpdate() instead of null.
        propsToUpdate = getPropertiesToUpdate((dirtyFields == null ? ArrayHelper.EMPTY_INT_ARRAY : dirtyFields), hasDirtyCollection);
        // don't need to check laziness (dirty checking algorithm handles that)
        updateStrings = new String[span];
        for (int j = 0; j < span; j++) {
            updateStrings[j] = tableUpdateNeeded[j] ? generateUpdateString(propsToUpdate, j, oldFields, j == 0 && rowId != null) : null;
        }
    } else {
        // For the case of dynamic-update="false", or no snapshot, we use the static SQL
        updateStrings = getUpdateStrings(rowId != null, hasUninitializedLazyProperties(object));
        propsToUpdate = getPropertyUpdateability(object);
    }
    for (int j = 0; j < span; j++) {
        // Now update only the tables with dirty properties (and the table with the version number)
        if (tableUpdateNeeded[j]) {
            updateOrInsert(id, fields, oldFields, j == 0 ? rowId : null, propsToUpdate, j, oldVersion, object, updateStrings[j], session);
        }
    }
}
Also used : InMemoryValueGenerationStrategy(org.hibernate.tuple.InMemoryValueGenerationStrategy) EntityEntry(org.hibernate.engine.spi.EntityEntry) Session(org.hibernate.Session)

Example 34 with EntityEntry

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

the class AbstractEntityTuplizer method determineEntityIdPersistIfNecessary.

private static Serializable determineEntityIdPersistIfNecessary(Object entity, AssociationType associationType, SharedSessionContractImplementor session, SessionFactoryImplementor sessionFactory) {
    if (entity == null) {
        return null;
    }
    if (HibernateProxy.class.isInstance(entity)) {
        // entity is a proxy, so we know it is not transient; just return ID from proxy
        return ((HibernateProxy) entity).getHibernateLazyInitializer().getIdentifier();
    }
    if (session != null) {
        final EntityEntry pcEntry = session.getPersistenceContext().getEntry(entity);
        if (pcEntry != null) {
            // entity managed; return ID.
            return pcEntry.getId();
        }
    }
    final EntityPersister persister = resolveEntityPersister(entity, associationType, session, sessionFactory);
    Serializable entityId = persister.getIdentifier(entity, session);
    if (entityId == null) {
        if (session != null) {
            // if we have a session, then follow the HHH-11328 requirements
            entityId = persistTransientEntity(entity, session);
        }
    // otherwise just let it be null HHH-11274
    } else {
        if (session != null) {
            // if the entity is in the process of being merged, it may be stored in the
            // PC already, but doesn't have an EntityEntry yet. If this is the case,
            // then don't persist even if it is transient because doing so can lead
            // to having 2 entities in the PC with the same ID (HHH-11328).
            final EntityKey entityKey = session.generateEntityKey(entityId, persister);
            if (session.getPersistenceContext().getEntity(entityKey) == null && ForeignKeys.isTransient(persister.getEntityName(), entity, null, session)) {
                // entity is transient and it is not in the PersistenceContext.
                // entity needs to be persisted.
                persistTransientEntity(entity, session);
            }
        }
    }
    return entityId;
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) EntityKey(org.hibernate.engine.spi.EntityKey) EntityEntry(org.hibernate.engine.spi.EntityEntry) Serializable(java.io.Serializable)

Example 35 with EntityEntry

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

the class UnversionedCascadeDereferencedCollectionTest method testMergeNullCollection.

@Test
@TestForIssue(jiraKey = "HHH-9777")
public void testMergeNullCollection() {
    Session s = openSession();
    s.getTransaction().begin();
    UnversionedCascadeOne one = new UnversionedCascadeOne();
    assertNull(one.getManies());
    s.save(one);
    assertNull(one.getManies());
    EntityEntry eeOne = getEntityEntry(s, one);
    assertNull(eeOne.getLoadedValue("manies"));
    s.flush();
    assertNull(one.getManies());
    assertNull(eeOne.getLoadedValue("manies"));
    s.getTransaction().commit();
    s.close();
    final String role = UnversionedCascadeOne.class.getName() + ".manies";
    s = openSession();
    s.getTransaction().begin();
    one = (UnversionedCascadeOne) s.merge(one);
    // afterQuery merging, one.getManies() should still be null;
    // the EntityEntry loaded state should contain a PersistentCollection though.
    assertNull(one.getManies());
    eeOne = getEntityEntry(s, one);
    AbstractPersistentCollection maniesEEOneStateOrig = (AbstractPersistentCollection) eeOne.getLoadedValue("manies");
    assertNotNull(maniesEEOneStateOrig);
    // Ensure maniesEEOneStateOrig has role, key, and session properly defined (even though one.manies == null)
    assertEquals(role, maniesEEOneStateOrig.getRole());
    assertEquals(one.getId(), maniesEEOneStateOrig.getKey());
    assertSame(s, maniesEEOneStateOrig.getSession());
    // Ensure there is a CollectionEntry for maniesEEOneStateOrig and that the role, persister, and key are set properly.
    CollectionEntry ceManiesOrig = getCollectionEntry(s, maniesEEOneStateOrig);
    assertNotNull(ceManiesOrig);
    assertEquals(role, ceManiesOrig.getRole());
    assertSame(sessionFactory().getCollectionPersister(role), ceManiesOrig.getLoadedPersister());
    assertEquals(one.getId(), ceManiesOrig.getKey());
    s.flush();
    // Ensure the same EntityEntry is being used.
    assertSame(eeOne, getEntityEntry(s, one));
    // Ensure one.getManies() is still null.
    assertNull(one.getManies());
    // Ensure CollectionEntry for maniesEEOneStateOrig is no longer in the PersistenceContext.
    assertNull(getCollectionEntry(s, maniesEEOneStateOrig));
    // Ensure the original CollectionEntry has role, persister, and key set to null.
    assertNull(ceManiesOrig.getRole());
    assertNull(ceManiesOrig.getLoadedPersister());
    assertNull(ceManiesOrig.getKey());
    // Ensure the PersistentCollection (that was previously returned by eeOne.getLoadedState())
    // has key and role set to null.
    assertNull(maniesEEOneStateOrig.getKey());
    assertNull(maniesEEOneStateOrig.getRole());
    // Ensure eeOne.getLoadedState() returns null for collection afterQuery flush.
    assertNull(eeOne.getLoadedValue("manies"));
    // Ensure the session in maniesEEOneStateOrig has been unset.
    assertNull(maniesEEOneStateOrig.getSession());
    s.getTransaction().commit();
    s.close();
}
Also used : EntityEntry(org.hibernate.engine.spi.EntityEntry) AbstractPersistentCollection(org.hibernate.collection.internal.AbstractPersistentCollection) CollectionEntry(org.hibernate.engine.spi.CollectionEntry) Session(org.hibernate.Session) Test(org.junit.Test) TestForIssue(org.hibernate.testing.TestForIssue)

Aggregations

EntityEntry (org.hibernate.engine.spi.EntityEntry)79 Serializable (java.io.Serializable)22 EntityPersister (org.hibernate.persister.entity.EntityPersister)21 Session (org.hibernate.Session)18 Test (org.junit.Test)17 CollectionEntry (org.hibernate.engine.spi.CollectionEntry)16 AbstractPersistentCollection (org.hibernate.collection.internal.AbstractPersistentCollection)12 EntityKey (org.hibernate.engine.spi.EntityKey)12 TestForIssue (org.hibernate.testing.TestForIssue)12 AssertionFailure (org.hibernate.AssertionFailure)11 HibernateProxy (org.hibernate.proxy.HibernateProxy)11 HibernateException (org.hibernate.HibernateException)10 EventSource (org.hibernate.event.spi.EventSource)9 PersistenceContext (org.hibernate.engine.spi.PersistenceContext)8 TransientObjectException (org.hibernate.TransientObjectException)7 PersistentCollection (org.hibernate.collection.spi.PersistentCollection)7 SessionImplementor (org.hibernate.engine.spi.SessionImplementor)6 Status (org.hibernate.engine.spi.Status)6 LazyInitializer (org.hibernate.proxy.LazyInitializer)6 EntityRegionAccessStrategy (org.hibernate.cache.spi.access.EntityRegionAccessStrategy)5