use of org.hibernate.persister.entity.EntityPersister 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.persister.entity.EntityPersister 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.persister.entity.EntityPersister in project hibernate-orm by hibernate.
the class DefaultLockEventListener method onLock.
/**
* Handle the given lock event.
*
* @param event The lock event to be handled.
* @throws HibernateException
*/
public void onLock(LockEvent event) throws HibernateException {
if (event.getObject() == null) {
throw new NullPointerException("attempted to lock null");
}
if (event.getLockMode() == LockMode.WRITE) {
throw new HibernateException("Invalid lock mode for lock()");
}
if (event.getLockMode() == LockMode.UPGRADE_SKIPLOCKED) {
LOG.explicitSkipLockedLockCombo();
}
SessionImplementor source = event.getSession();
Object entity = source.getPersistenceContext().unproxyAndReassociate(event.getObject());
//TODO: if object was an uninitialized proxy, this is inefficient,
// resulting in two SQL selects
EntityEntry entry = source.getPersistenceContext().getEntry(entity);
if (entry == null) {
final EntityPersister persister = source.getEntityPersister(event.getEntityName(), entity);
final Serializable id = persister.getIdentifier(entity, source);
if (!ForeignKeys.isNotTransient(event.getEntityName(), entity, Boolean.FALSE, source)) {
throw new TransientObjectException("cannot lock an unsaved transient instance: " + persister.getEntityName());
}
entry = reassociate(event, entity, id, persister);
cascadeOnLock(event, persister, entity);
}
upgradeLock(entity, entry, event.getLockOptions(), event.getSession());
}
use of org.hibernate.persister.entity.EntityPersister 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);
}
}
use of org.hibernate.persister.entity.EntityPersister in project hibernate-orm by hibernate.
the class DefaultMergeEventListener method entityIsTransient.
protected void entityIsTransient(MergeEvent event, Map copyCache) {
LOG.trace("Merging transient instance");
final Object entity = event.getEntity();
final EventSource source = event.getSession();
final String entityName = event.getEntityName();
final EntityPersister persister = source.getEntityPersister(entityName, entity);
final Serializable id = persister.hasIdentifierProperty() ? persister.getIdentifier(entity, source) : null;
if (copyCache.containsKey(entity)) {
persister.setIdentifier(copyCache.get(entity), id, source);
} else {
//beforeQuery cascade!
((MergeContext) copyCache).put(entity, source.instantiate(persister, id), true);
}
final Object copy = copyCache.get(entity);
// cascade first, so that all unsaved objects get their
// copy created beforeQuery we actually copy
//cascadeOnMerge(event, persister, entity, copyCache, Cascades.CASCADE_BEFORE_MERGE);
super.cascadeBeforeSave(source, persister, entity, copyCache);
copyValues(persister, entity, copy, source, copyCache, ForeignKeyDirection.FROM_PARENT);
saveTransientEntity(copy, entityName, event.getRequestedId(), source, copyCache);
// cascade first, so that all unsaved objects get their
// copy created beforeQuery we actually copy
super.cascadeAfterSave(source, persister, entity, copyCache);
copyValues(persister, entity, copy, source, copyCache, ForeignKeyDirection.TO_PARENT);
event.setResult(copy);
}
Aggregations