use of org.hibernate.engine.spi.EntityKey in project hibernate-orm by hibernate.
the class AbstractSaveEventListener method performSave.
/**
* Prepares the save call by checking the session caches for a pre-existing
* entity and performing any lifecycle callbacks.
*
* @param entity The entity to be saved.
* @param id The id by which to save the entity.
* @param persister The entity's persister instance.
* @param useIdentityColumn Is an identity column being used?
* @param anything Generally cascade-specific information.
* @param source The session from which the event originated.
* @param requiresImmediateIdAccess does the event context require
* access to the identifier immediately afterQuery 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 performSave(Object entity, Serializable id, EntityPersister persister, boolean useIdentityColumn, Object anything, EventSource source, boolean requiresImmediateIdAccess) {
if (LOG.isTraceEnabled()) {
LOG.tracev("Saving {0}", MessageHelper.infoString(persister, id, source.getFactory()));
}
final EntityKey key;
if (!useIdentityColumn) {
key = source.generateEntityKey(id, persister);
Object old = source.getPersistenceContext().getEntity(key);
if (old != null) {
if (source.getPersistenceContext().getEntry(old).getStatus() == Status.DELETED) {
source.forceFlush(source.getPersistenceContext().getEntry(old));
} else {
throw new NonUniqueObjectException(id, persister.getEntityName());
}
}
persister.setIdentifier(entity, id, source);
} else {
key = null;
}
if (invokeSaveLifecycle(entity, persister, source)) {
//EARLY EXIT
return id;
}
return performSaveOrReplicate(entity, key, persister, useIdentityColumn, anything, source, requiresImmediateIdAccess);
}
use of org.hibernate.engine.spi.EntityKey in project hibernate-orm by hibernate.
the class DefaultDeleteEventListener method deleteEntity.
/**
* Perform the entity deletion. Well, as with most operations, does not
* really perform it; just schedules an action/execution with the
* {@link org.hibernate.engine.spi.ActionQueue} for execution during flush.
*
* @param session The originating session
* @param entity The entity to delete
* @param entityEntry The entity's entry in the {@link PersistenceContext}
* @param isCascadeDeleteEnabled Is delete cascading enabled?
* @param persister The entity persister.
* @param transientEntities A cache of already deleted entities.
*/
protected final void deleteEntity(final EventSource session, final Object entity, final EntityEntry entityEntry, final boolean isCascadeDeleteEnabled, final boolean isOrphanRemovalBeforeUpdates, final EntityPersister persister, final Set transientEntities) {
if (LOG.isTraceEnabled()) {
LOG.tracev("Deleting {0}", MessageHelper.infoString(persister, entityEntry.getId(), session.getFactory()));
}
final PersistenceContext persistenceContext = session.getPersistenceContext();
final Type[] propTypes = persister.getPropertyTypes();
final Object version = entityEntry.getVersion();
final Object[] currentState;
if (entityEntry.getLoadedState() == null) {
//ie. the entity came in from update()
currentState = persister.getPropertyValues(entity);
} else {
currentState = entityEntry.getLoadedState();
}
final Object[] deletedState = createDeletedState(persister, currentState, session);
entityEntry.setDeletedState(deletedState);
session.getInterceptor().onDelete(entity, entityEntry.getId(), deletedState, persister.getPropertyNames(), propTypes);
// beforeQuery any callbacks, etc, so subdeletions see that this deletion happened first
persistenceContext.setEntryStatus(entityEntry, Status.DELETED);
final EntityKey key = session.generateEntityKey(entityEntry.getId(), persister);
cascadeBeforeDelete(session, persister, entity, entityEntry, transientEntities);
new ForeignKeys.Nullifier(entity, true, false, session).nullifyTransientReferences(entityEntry.getDeletedState(), propTypes);
new Nullability(session).checkNullability(entityEntry.getDeletedState(), persister, true);
persistenceContext.getNullifiableEntityKeys().add(key);
if (isOrphanRemovalBeforeUpdates) {
// TODO: The removeOrphan concept is a temporary "hack" for HHH-6484. This should be removed once action/task
// ordering is improved.
session.getActionQueue().addAction(new OrphanRemovalAction(entityEntry.getId(), deletedState, version, entity, persister, isCascadeDeleteEnabled, session));
} else {
// Ensures that containing deletions happen beforeQuery sub-deletions
session.getActionQueue().addAction(new EntityDeleteAction(entityEntry.getId(), deletedState, version, entity, persister, isCascadeDeleteEnabled, session));
}
cascadeAfterDelete(session, persister, entity, transientEntities);
// the entry will be removed afterQuery the flush, and will no longer
// override the stale snapshot
// This is now handled by removeEntity() in EntityDeleteAction
//persistenceContext.removeDatabaseSnapshot(key);
}
use of org.hibernate.engine.spi.EntityKey in project hibernate-orm by hibernate.
the class DefaultSaveOrUpdateEventListener method performUpdate.
protected void performUpdate(SaveOrUpdateEvent event, Object entity, EntityPersister persister) throws HibernateException {
final boolean traceEnabled = LOG.isTraceEnabled();
if (traceEnabled && !persister.isMutable()) {
LOG.trace("Immutable instance passed to performUpdate()");
}
if (traceEnabled) {
LOG.tracev("Updating {0}", MessageHelper.infoString(persister, event.getRequestedId(), event.getSession().getFactory()));
}
final EventSource source = event.getSession();
final EntityKey key = source.generateEntityKey(event.getRequestedId(), persister);
source.getPersistenceContext().checkUniqueness(key, entity);
if (invokeUpdateLifecycle(entity, persister, source)) {
reassociate(event, event.getObject(), event.getRequestedId(), persister);
return;
}
// this is a transient object with existing persistent state not loaded by the session
new OnUpdateVisitor(source, event.getRequestedId(), entity).process(entity, persister);
// TODO: put this stuff back in to read snapshot from
// the second-level cache (needs some extra work)
/*Object[] cachedState = null;
if ( persister.hasCache() ) {
CacheEntry entry = (CacheEntry) persister.getCache()
.get( event.getRequestedId(), source.getTimestamp() );
cachedState = entry==null ?
null :
entry.getState(); //TODO: half-assemble this stuff
}*/
source.getPersistenceContext().addEntity(entity, (persister.isMutable() ? Status.MANAGED : Status.READ_ONLY), // cachedState,
null, key, persister.getVersion(entity), LockMode.NONE, true, persister, false);
persister.afterReassociate(entity, source);
if (traceEnabled) {
LOG.tracev("Updating {0}", MessageHelper.infoString(persister, event.getRequestedId(), source.getFactory()));
}
cascadeOnUpdate(event, persister, entity);
}
use of org.hibernate.engine.spi.EntityKey in project hibernate-orm by hibernate.
the class Loader method loadSequentialRowsReverse.
/**
* Loads a single logical row from the result set moving forward. This is the
* processing used from the ScrollableResults where there were collection fetches
* encountered; thus a single logical row may have multiple rows in the underlying
* result set.
*
* @param resultSet The result set from which to do the load.
* @param session The session from which the request originated.
* @param queryParameters The query parameters specified by the user.
* @param returnProxies Should proxies be generated
*
* @return The loaded "row".
*
* @throws HibernateException
*/
public Object loadSequentialRowsReverse(final ResultSet resultSet, final SharedSessionContractImplementor session, final QueryParameters queryParameters, final boolean returnProxies, final boolean isLogicallyAfterLast) throws HibernateException {
try {
if (resultSet.isFirst()) {
// don't even bother trying to read any further
return null;
}
EntityKey keyToRead = null;
// previous logical row).
if (resultSet.isAfterLast() && isLogicallyAfterLast) {
// position cursor to the last row
resultSet.last();
keyToRead = getKeyFromResultSet(0, getEntityPersisters()[0], null, resultSet, session);
} else {
// Since the result set cursor is always left at the first
// physical row afterQuery the "last processed", we need to jump
// back one position to get the key value we are interested
// in skipping
resultSet.previous();
// sequentially read the result set in reverse until we recognize
// a change in the key value. At that point, we are pointed at
// the last physical sequential row for the logical row in which
// we are interested in processing
boolean firstPass = true;
final EntityKey lastKey = getKeyFromResultSet(0, getEntityPersisters()[0], null, resultSet, session);
while (resultSet.previous()) {
EntityKey checkKey = getKeyFromResultSet(0, getEntityPersisters()[0], null, resultSet, session);
if (firstPass) {
firstPass = false;
keyToRead = checkKey;
}
if (!lastKey.equals(checkKey)) {
break;
}
}
}
// row with the key we are interested in loading
while (resultSet.previous()) {
EntityKey checkKey = getKeyFromResultSet(0, getEntityPersisters()[0], null, resultSet, session);
if (!keyToRead.equals(checkKey)) {
break;
}
}
// Finally, read ahead one row to position result set cursor
// at the first physical row we are interested in loading
resultSet.next();
// and doAfterTransactionCompletion the load
return sequentialLoad(resultSet, session, queryParameters, returnProxies, keyToRead);
} catch (SQLException sqle) {
throw factory.getJdbcServices().getSqlExceptionHelper().convert(sqle, "could not doAfterTransactionCompletion sequential read of results (forward)", getSQLString());
}
}
use of org.hibernate.engine.spi.EntityKey in project hibernate-orm by hibernate.
the class Loader method getRow.
/**
* Resolve any IDs for currently loaded objects, duplications within the
* <tt>ResultSet</tt>, etc. Instantiate empty objects to be initialized from the
* <tt>ResultSet</tt>. Return an array of objects (a row of results) and an
* array of booleans (by side-effect) that determine whether the corresponding
* object should be initialized.
*/
private Object[] getRow(final ResultSet rs, final Loadable[] persisters, final EntityKey[] keys, final Object optionalObject, final EntityKey optionalObjectKey, final LockMode[] lockModes, final List hydratedObjects, final SharedSessionContractImplementor session) throws HibernateException, SQLException {
final int cols = persisters.length;
final EntityAliases[] descriptors = getEntityAliases();
if (LOG.isDebugEnabled()) {
LOG.debugf("Result row: %s", StringHelper.toString(keys));
}
final Object[] rowResults = new Object[cols];
for (int i = 0; i < cols; i++) {
Object object = null;
EntityKey key = keys[i];
if (keys[i] == null) {
//do nothing
} else {
//If the object is already loaded, return the loaded one
object = session.getEntityUsingInterceptor(key);
if (object != null) {
//its already loaded so don't need to hydrate it
instanceAlreadyLoaded(rs, i, persisters[i], key, object, lockModes[i], session);
} else {
object = instanceNotYetLoaded(rs, i, persisters[i], descriptors[i].getRowIdAlias(), key, lockModes[i], optionalObjectKey, optionalObject, hydratedObjects, session);
}
}
rowResults[i] = object;
}
return rowResults;
}
Aggregations