private AbstractEntityInsertAction addInsertAction( Object[] values, Serializable id, Object entity, EntityPersister persister, boolean useIdentityColumn, EventSource source, boolean shouldDelayIdentityInserts) { if (useIdentityColumn) { EntityIdentityInsertAction insert = new EntityIdentityInsertAction( values, entity, persister, isVersionIncrementDisabled(), source, shouldDelayIdentityInserts); source.getActionQueue().addAction(insert); return insert; } else { Object version = Versioning.getVersion(values, persister); EntityInsertAction insert = new EntityInsertAction( id, values, entity, version, persister, isVersionIncrementDisabled(), source); source.getActionQueue().addAction(insert); return insert; } }
@Override public void insert(Serializable id, Object[] fields, Object object, SessionImplementor session) throws HibernateException { final int span = getTableSpan(); // insert operations are always dynamic in OGM boolean[] propertiesToInsert = getPropertiesToInsert(fields); for (int j = 0; j < span; j++) { if (isInverseTable(j)) { return; } // note: it is conceptually possible that a UserType could map null to // a non-null value, so the following is arguable: if (isNullableTable(j) && isAllNull(fields, j)) { return; } if (log.isTraceEnabled()) { log.trace("Inserting entity: " + MessageHelper.infoString(this, id, getFactory())); if (j == 0 && isVersioned()) { log.trace("Version: " + Versioning.getVersion(fields, this)); } } final EntityKey key = EntityKeyBuilder.fromPersister(this, id, session); Tuple resultset = gridDialect.getTuple(key, this.getTupleContext()); // add the discriminator if (j == 0) { if (resultset != null) { throw new HibernateException( "trying to insert an already existing entity: " + MessageHelper.infoString(this, id, getFactory())); } if (discriminator.isNeeded()) { resultset = createNewResultSetIfNull(key, resultset, id, session); resultset.put(getDiscriminatorColumnName(), getDiscriminatorValue()); } } resultset = createNewResultSetIfNull(key, resultset, id, session); // dehydrate dehydrate( resultset, fields, propertiesToInsert, getPropertyColumnInsertable(), j, id, session); gridDialect.updateTuple(resultset, key, getTupleContext()); } }
/** * Perform any property value substitution that is necessary (interceptor callback, version * initialization...) * * @param entity The entity * @param id The entity identifier * @param values The snapshot entity state * @param persister The entity persister * @param source The originating session * @return True if the snapshot state changed such that reinjection of the values into the entity * is required. */ protected boolean substituteValuesIfNecessary( Object entity, Serializable id, Object[] values, EntityPersister persister, SessionImplementor source) { boolean substitute = source .getInterceptor() .onSave(entity, id, values, persister.getPropertyNames(), persister.getPropertyTypes()); // keep the existing version number in the case of replicate! if (persister.isVersioned()) { substitute = Versioning.seedVersion( values, persister.getVersionProperty(), persister.getVersionType(), source) || substitute; } return substitute; }
@Override public void execute() throws HibernateException { final Serializable id = getId(); final EntityPersister persister = getPersister(); final SessionImplementor session = getSession(); final Object instance = getInstance(); final boolean veto = preUpdate(); final SessionFactoryImplementor factory = session.getFactory(); Object previousVersion = this.previousVersion; 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); } final Object ck; if (persister.hasCache()) { final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy(); ck = cache.generateCacheKey(id, persister, factory, session.getTenantIdentifier()); lock = cache.lockItem(session, ck, previousVersion); } else { ck = null; } if (!veto) { persister.update( id, state, dirtyFields, hasDirtyCollection, previousState, previousVersion, instance, rowId, session); } final EntityEntry entry = session.getPersistenceContext().getEntry(instance); if (entry == null) { throw new AssertionFailure("possible nonthreadsafe access to session"); } if (entry.getStatus() == Status.MANAGED || 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.getPropertyTypes(), persister.getPropertyCheckability(), state, session); if (persister.hasUpdateGeneratedProperties()) { // this entity defines proeprty generation, so process those generated // values... persister.processUpdateGeneratedProperties(id, instance, state, session); if (persister.isVersionPropertyGenerated()) { nextVersion = Versioning.getVersion(state, persister); } } // have the entity entry doAfterTransactionCompletion 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.getStatus() != Status.MANAGED) { persister.getCacheAccessStrategy().remove(session, ck); } else { // TODO: inefficient if that cache is just going to ignore the updated state! final CacheEntry ce = persister.buildCacheEntry(instance, state, nextVersion, getSession()); cacheEntry = persister.getCacheEntryStructure().structure(ce); final boolean put = cacheUpdate(persister, previousVersion, ck); if (put && factory.getStatistics().isStatisticsEnabled()) { factory .getStatisticsImplementor() .secondLevelCachePut(getPersister().getCacheAccessStrategy().getRegion().getName()); } } } session .getPersistenceContext() .getNaturalIdHelper() .manageSharedNaturalIdCrossReference( persister, id, state, previousNaturalIdValues, CachedNaturalIdValueSource.UPDATE); postUpdate(); if (factory.getStatistics().isStatisticsEnabled() && !veto) { factory.getStatisticsImplementor().updateEntity(getPersister().getEntityName()); } }
@Override public void execute() throws HibernateException { nullifyTransientReferencesIfNotAlready(); final EntityPersister persister = getPersister(); final SessionImplementor session = getSession(); final Object instance = getInstance(); final Serializable id = getId(); final boolean 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, getState(), instance, session); final EntityEntry entry = session.getPersistenceContext().getEntry(instance); if (entry == null) { throw new AssertionFailure("possible non-threadsafe access to session"); } entry.postInsert(getState()); if (persister.hasInsertGeneratedProperties()) { persister.processInsertGeneratedProperties(id, instance, getState(), session); if (persister.isVersionPropertyGenerated()) { version = Versioning.getVersion(getState(), persister); } entry.postUpdate(instance, getState(), version); } getSession().getPersistenceContext().registerInsertedKey(getPersister(), getId()); } final SessionFactoryImplementor factory = getSession().getFactory(); if (isCachePutEnabled(persister, session)) { final CacheEntry ce = persister.buildCacheEntry(instance, getState(), version, session); cacheEntry = persister.getCacheEntryStructure().structure(ce); final CacheKey ck = session.generateCacheKey( id, persister.getIdentifierType(), persister.getRootEntityName()); final boolean put = persister.getCacheAccessStrategy().insert(ck, cacheEntry, version); if (put && factory.getStatistics().isStatisticsEnabled()) { factory .getStatisticsImplementor() .secondLevelCachePut(getPersister().getCacheAccessStrategy().getRegion().getName()); } } handleNaturalIdPostSaveNotifications(id); postInsert(); if (factory.getStatistics().isStatisticsEnabled() && !veto) { factory.getStatisticsImplementor().insertEntity(getPersister().getEntityName()); } markExecuted(); }