use of org.hibernate.event.spi.EventSource 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.event.spi.EventSource 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());
}
use of org.hibernate.event.spi.EventSource in project hibernate-orm by hibernate.
the class DefaultReplicateEventListener method onReplicate.
/**
* Handle the given replicate event.
*
* @param event The replicate event to be handled.
*
* @throws TransientObjectException An invalid attempt to replicate a transient entity.
*/
public void onReplicate(ReplicateEvent event) {
final EventSource source = event.getSession();
if (source.getPersistenceContext().reassociateIfUninitializedProxy(event.getObject())) {
LOG.trace("Uninitialized proxy passed to replicate()");
return;
}
Object entity = source.getPersistenceContext().unproxyAndReassociate(event.getObject());
if (source.getPersistenceContext().isEntryFor(entity)) {
LOG.trace("Ignoring persistent instance passed to replicate()");
//hum ... should we cascade anyway? throw an exception? fine like it is?
return;
}
EntityPersister persister = source.getEntityPersister(event.getEntityName(), entity);
// get the id from the object
/*if ( persister.isUnsaved(entity, source) ) {
throw new TransientObjectException("transient instance passed to replicate()");
}*/
Serializable id = persister.getIdentifier(entity, source);
if (id == null) {
throw new TransientObjectException("instance with null id passed to replicate()");
}
final ReplicationMode replicationMode = event.getReplicationMode();
final Object oldVersion;
if (replicationMode == ReplicationMode.EXCEPTION) {
//always do an INSERT, and let it fail by constraint violation
oldVersion = null;
} else {
//what is the version on the database?
oldVersion = persister.getCurrentVersion(id, source);
}
final boolean traceEnabled = LOG.isTraceEnabled();
if (oldVersion != null) {
if (traceEnabled) {
LOG.tracev("Found existing row for {0}", MessageHelper.infoString(persister, id, source.getFactory()));
}
/// HHH-2378
final Object realOldVersion = persister.isVersioned() ? oldVersion : null;
boolean canReplicate = replicationMode.shouldOverwriteCurrentVersion(entity, realOldVersion, persister.getVersion(entity), persister.getVersionType());
// else do nothing (don't even reassociate object!)
if (canReplicate) {
performReplication(entity, id, realOldVersion, persister, replicationMode, source);
} else if (traceEnabled) {
LOG.trace("No need to replicate");
}
//TODO: would it be better to do a refresh from db?
} else {
// no existing row - do an insert
if (traceEnabled) {
LOG.tracev("No existing row, replicating new instance {0}", MessageHelper.infoString(persister, id, source.getFactory()));
}
// prefer re-generation of identity!
final boolean regenerate = persister.isIdentifierAssignedByInsert();
final EntityKey key = regenerate ? null : source.generateEntityKey(id, persister);
performSaveOrReplicate(entity, key, persister, regenerate, replicationMode, source, true);
}
}
use of org.hibernate.event.spi.EventSource in project hibernate-orm by hibernate.
the class DefaultLoadEventListener method assembleCacheEntry.
private Object assembleCacheEntry(final StandardCacheEntryImpl entry, final Serializable id, final EntityPersister persister, final LoadEvent event) throws HibernateException {
final Object optionalObject = event.getInstanceToLoad();
final EventSource session = event.getSession();
final SessionFactoryImplementor factory = session.getFactory();
if (traceEnabled) {
LOG.tracev("Assembling entity from second-level cache: {0}", MessageHelper.infoString(persister, id, factory));
}
EntityPersister subclassPersister = factory.getEntityPersister(entry.getSubclass());
Object result = optionalObject == null ? session.instantiate(subclassPersister, id) : optionalObject;
// make it circular-reference safe
final EntityKey entityKey = session.generateEntityKey(id, subclassPersister);
TwoPhaseLoad.addUninitializedCachedEntity(entityKey, result, subclassPersister, LockMode.NONE, entry.getVersion(), session);
Type[] types = subclassPersister.getPropertyTypes();
Object[] values = entry.assemble(result, id, subclassPersister, session.getInterceptor(), session);
// intializes result by side-effect
TypeHelper.deepCopy(values, types, subclassPersister.getPropertyUpdateability(), values, session);
Object version = Versioning.getVersion(values, subclassPersister);
LOG.tracev("Cached Version: {0}", version);
final PersistenceContext persistenceContext = session.getPersistenceContext();
boolean isReadOnly = session.isDefaultReadOnly();
if (persister.isMutable()) {
Object proxy = persistenceContext.getProxy(entityKey);
if (proxy != null) {
// there is already a proxy for this impl
// only set the status to read-only if the proxy is read-only
isReadOnly = ((HibernateProxy) proxy).getHibernateLazyInitializer().isReadOnly();
}
} else {
isReadOnly = true;
}
persistenceContext.addEntry(result, (isReadOnly ? Status.READ_ONLY : Status.MANAGED), values, null, id, version, LockMode.NONE, true, subclassPersister, false);
subclassPersister.afterInitialize(result, session);
persistenceContext.initializeNonLazyCollections();
// upgrade the lock if necessary:
//lock(result, lockMode);
//PostLoad is needed for EJB3
//TODO: reuse the PostLoadEvent...
PostLoadEvent postLoadEvent = event.getPostLoadEvent().setEntity(result).setId(id).setPersister(persister);
for (PostLoadEventListener listener : postLoadEventListeners(session)) {
listener.onPostLoad(postLoadEvent);
}
return result;
}
use of org.hibernate.event.spi.EventSource in project hibernate-orm by hibernate.
the class DefaultMergeEventListener method entityIsDetached.
protected void entityIsDetached(MergeEvent event, Map copyCache) {
LOG.trace("Merging detached instance");
final Object entity = event.getEntity();
final EventSource source = event.getSession();
final EntityPersister persister = source.getEntityPersister(event.getEntityName(), entity);
final String entityName = persister.getEntityName();
Serializable id = event.getRequestedId();
if (id == null) {
id = persister.getIdentifier(entity, source);
} else {
// check that entity id = requestedId
Serializable entityId = persister.getIdentifier(entity, source);
if (!persister.getIdentifierType().isEqual(id, entityId, source.getFactory())) {
throw new HibernateException("merge requested with id not matching id of passed entity");
}
}
String previousFetchProfile = source.getLoadQueryInfluencers().getInternalFetchProfile();
source.getLoadQueryInfluencers().setInternalFetchProfile("merge");
//we must clone embedded composite identifiers, or
//we will get back the same instance that we pass in
final Serializable clonedIdentifier = (Serializable) persister.getIdentifierType().deepCopy(id, source.getFactory());
final Object result = source.get(entityName, clonedIdentifier);
source.getLoadQueryInfluencers().setInternalFetchProfile(previousFetchProfile);
if (result == null) {
//TODO: we should throw an exception if we really *know* for sure
// that this is a detached instance, rather than just assuming
//throw new StaleObjectStateException(entityName, id);
// we got here because we assumed that an instance
// with an assigned id was detached, when it was
// really persistent
entityIsTransient(event, copyCache);
} else {
//beforeQuery cascade!
((MergeContext) copyCache).put(entity, result, true);
final Object target = source.getPersistenceContext().unproxy(result);
if (target == entity) {
throw new AssertionFailure("entity was not detached");
} else if (!source.getEntityName(target).equals(entityName)) {
throw new WrongClassException("class of the given object did not match class of persistent copy", event.getRequestedId(), entityName);
} else if (isVersionChanged(entity, source, persister, target)) {
if (source.getFactory().getStatistics().isStatisticsEnabled()) {
source.getFactory().getStatisticsImplementor().optimisticFailure(entityName);
}
throw new StaleObjectStateException(entityName, id);
}
// cascade first, so that all unsaved objects get their
// copy created beforeQuery we actually copy
cascadeOnMerge(source, persister, entity, copyCache);
copyValues(persister, entity, target, source, copyCache);
//copyValues works by reflection, so explicitly mark the entity instance dirty
markInterceptorDirty(entity, target, persister);
event.setResult(result);
}
}
Aggregations