use of org.hibernate.persister.entity.EntityPersister 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()) {
dirtyProperties = persister.resolveAttributeIndexes(((SelfDirtinessTracker) entity).$$_hibernate_getDirtyAttributes());
} else {
dirtyProperties = new int[0];
}
} else {
// see if the custom dirtiness strategy can tell us...
class DirtyCheckContextImpl implements CustomEntityDirtinessStrategy.DirtyCheckContext {
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) 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);
}
use of org.hibernate.persister.entity.EntityPersister in project hibernate-orm by hibernate.
the class DefaultMergeEventListener method onMerge.
/**
* Handle the given merge event.
*
* @param event The merge event to be handled.
*
* @throws HibernateException
*/
public void onMerge(MergeEvent event, Map copiedAlready) throws HibernateException {
final MergeContext copyCache = (MergeContext) copiedAlready;
final EventSource source = event.getSession();
final Object original = event.getOriginal();
if (original != null) {
final Object entity;
if (original instanceof HibernateProxy) {
LazyInitializer li = ((HibernateProxy) original).getHibernateLazyInitializer();
if (li.isUninitialized()) {
LOG.trace("Ignoring uninitialized proxy");
event.setResult(source.load(li.getEntityName(), li.getIdentifier()));
//EARLY EXIT!
return;
} else {
entity = li.getImplementation();
}
} else {
entity = original;
}
if (copyCache.containsKey(entity) && (copyCache.isOperatedOn(entity))) {
LOG.trace("Already in merge process");
event.setResult(entity);
} else {
if (copyCache.containsKey(entity)) {
LOG.trace("Already in copyCache; setting in merge process");
copyCache.setOperatedOn(entity, true);
}
event.setEntity(entity);
EntityState entityState = null;
// Check the persistence context for an entry relating to this
// entity to be merged...
EntityEntry entry = source.getPersistenceContext().getEntry(entity);
if (entry == null) {
EntityPersister persister = source.getEntityPersister(event.getEntityName(), entity);
Serializable id = persister.getIdentifier(entity, source);
if (id != null) {
final EntityKey key = source.generateEntityKey(id, persister);
final Object managedEntity = source.getPersistenceContext().getEntity(key);
entry = source.getPersistenceContext().getEntry(managedEntity);
if (entry != null) {
// we have specialized case of a detached entity from the
// perspective of the merge operation. Specifically, we
// have an incoming entity instance which has a corresponding
// entry in the current persistence context, but registered
// under a different entity instance
entityState = EntityState.DETACHED;
}
}
}
if (entityState == null) {
entityState = getEntityState(entity, event.getEntityName(), entry, source);
}
switch(entityState) {
case DETACHED:
entityIsDetached(event, copyCache);
break;
case TRANSIENT:
entityIsTransient(event, copyCache);
break;
case PERSISTENT:
entityIsPersistent(event, copyCache);
break;
default:
//DELETED
throw new ObjectDeletedException("deleted instance passed to merge", null, getLoggableName(event.getEntityName(), entity));
}
}
}
}
use of org.hibernate.persister.entity.EntityPersister in project hibernate-orm by hibernate.
the class DefaultPersistEventListener method entityIsPersistent.
@SuppressWarnings({ "unchecked" })
protected void entityIsPersistent(PersistEvent event, Map createCache) {
LOG.trace("Ignoring persistent instance");
final EventSource source = event.getSession();
//TODO: check that entry.getIdentifier().equals(requestedId)
final Object entity = source.getPersistenceContext().unproxy(event.getObject());
final EntityPersister persister = source.getEntityPersister(event.getEntityName(), entity);
if (createCache.put(entity, entity) == null) {
justCascade(createCache, source, entity, persister);
}
}
use of org.hibernate.persister.entity.EntityPersister in project hibernate-orm by hibernate.
the class DefaultPostLoadEventListener method onPostLoad.
@Override
public void onPostLoad(PostLoadEvent event) {
final Object entity = event.getEntity();
final EntityEntry entry = event.getSession().getPersistenceContext().getEntry(entity);
if (entry == null) {
throw new AssertionFailure("possible non-threadsafe access to the session");
}
final LockMode lockMode = entry.getLockMode();
if (LockMode.PESSIMISTIC_FORCE_INCREMENT.equals(lockMode)) {
final EntityPersister persister = entry.getPersister();
final Object nextVersion = persister.forceVersionIncrement(entry.getId(), entry.getVersion(), event.getSession());
entry.forceLocked(entity, nextVersion);
} else if (LockMode.OPTIMISTIC_FORCE_INCREMENT.equals(lockMode)) {
final EntityIncrementVersionProcess incrementVersion = new EntityIncrementVersionProcess(entity, entry);
event.getSession().getActionQueue().registerProcess(incrementVersion);
} else if (LockMode.OPTIMISTIC.equals(lockMode)) {
final EntityVerifyVersionProcess verifyVersion = new EntityVerifyVersionProcess(entity, entry);
event.getSession().getActionQueue().registerProcess(verifyVersion);
}
if (event.getPersister().implementsLifecycle()) {
//log.debug( "calling onLoad()" );
((Lifecycle) event.getEntity()).onLoad(event.getSession(), event.getId());
}
}
use of org.hibernate.persister.entity.EntityPersister in project hibernate-orm by hibernate.
the class DefaultRefreshEventListener method onRefresh.
/**
* Handle the given refresh event.
*
* @param event The refresh event to be handled.
*/
public void onRefresh(RefreshEvent event, Map refreshedAlready) {
final EventSource source = event.getSession();
boolean isTransient;
if (event.getEntityName() != null) {
isTransient = !source.contains(event.getEntityName(), event.getObject());
} else {
isTransient = !source.contains(event.getObject());
}
if (source.getPersistenceContext().reassociateIfUninitializedProxy(event.getObject())) {
if (isTransient) {
source.setReadOnly(event.getObject(), source.isDefaultReadOnly());
}
return;
}
final Object object = source.getPersistenceContext().unproxyAndReassociate(event.getObject());
if (refreshedAlready.containsKey(object)) {
LOG.trace("Already refreshed");
return;
}
final EntityEntry e = source.getPersistenceContext().getEntry(object);
final EntityPersister persister;
final Serializable id;
if (e == null) {
persister = source.getEntityPersister(event.getEntityName(), object);
//refresh() does not pass an entityName
id = persister.getIdentifier(object, event.getSession());
if (LOG.isTraceEnabled()) {
LOG.tracev("Refreshing transient {0}", MessageHelper.infoString(persister, id, source.getFactory()));
}
final EntityKey key = source.generateEntityKey(id, persister);
if (source.getPersistenceContext().getEntry(key) != null) {
throw new PersistentObjectException("attempted to refresh transient instance when persistent instance was already associated with the Session: " + MessageHelper.infoString(persister, id, source.getFactory()));
}
} else {
if (LOG.isTraceEnabled()) {
LOG.tracev("Refreshing ", MessageHelper.infoString(e.getPersister(), e.getId(), source.getFactory()));
}
if (!e.isExistsInDatabase()) {
throw new UnresolvableObjectException(e.getId(), "this instance does not yet exist as a row in the database");
}
persister = e.getPersister();
id = e.getId();
}
// cascade the refresh prior to refreshing this entity
refreshedAlready.put(object, object);
Cascade.cascade(CascadingActions.REFRESH, CascadePoint.BEFORE_REFRESH, source, persister, object, refreshedAlready);
if (e != null) {
final EntityKey key = source.generateEntityKey(id, persister);
source.getPersistenceContext().removeEntity(key);
if (persister.hasCollections()) {
new EvictVisitor(source).process(object, persister);
}
}
if (persister.hasCache()) {
Object previousVersion = null;
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(object);
}
final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy();
final Object ck = cache.generateCacheKey(id, persister, source.getFactory(), source.getTenantIdentifier());
final SoftLock lock = cache.lockItem(source, ck, previousVersion);
source.getActionQueue().registerProcess(new AfterTransactionCompletionProcess() {
@Override
public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) {
cache.unlockItem(session, ck, lock);
}
});
cache.remove(source, ck);
}
evictCachedCollections(persister, id, source);
String previousFetchProfile = source.getLoadQueryInfluencers().getInternalFetchProfile();
source.getLoadQueryInfluencers().setInternalFetchProfile("refresh");
Object result = persister.load(id, object, event.getLockOptions(), source);
// If it was transient, then set it to the default for the source.
if (result != null) {
if (!persister.isMutable()) {
// this is probably redundant; it should already be read-only
source.setReadOnly(result, true);
} else {
source.setReadOnly(result, (e == null ? source.isDefaultReadOnly() : e.isReadOnly()));
}
}
source.getLoadQueryInfluencers().setInternalFetchProfile(previousFetchProfile);
UnresolvableObjectException.throwIfNull(result, id, persister.getEntityName());
}
Aggregations