use of org.hibernate.event.internal.EntityState in project hibernate-reactive by hibernate.
the class DefaultReactiveMergeEventListener method reactiveOnMerge.
/**
* Handle the given merge event.
*
* @param event The merge event to be handled.
*/
@Override
public CompletionStage<Void> reactiveOnMerge(MergeEvent event, MergeContext copyCache) throws HibernateException {
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 voidFuture();
} else {
entity = li.getImplementation();
}
} else if (original instanceof PersistentAttributeInterceptable) {
final PersistentAttributeInterceptable interceptable = (PersistentAttributeInterceptable) original;
final PersistentAttributeInterceptor interceptor = interceptable.$$_hibernate_getInterceptor();
if (interceptor instanceof EnhancementAsProxyLazinessInterceptor) {
final EnhancementAsProxyLazinessInterceptor proxyInterceptor = (EnhancementAsProxyLazinessInterceptor) interceptor;
LOG.trace("Ignoring uninitialized enhanced-proxy");
// no need to go async, AFAICT ?
event.setResult(source.load(proxyInterceptor.getEntityName(), (Serializable) proxyInterceptor.getIdentifier()));
// EARLY EXIT!
return voidFuture();
} else {
entity = original;
}
} 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...
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
EntityEntry entry = persistenceContext.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 = persistenceContext.getEntity(key);
entry = persistenceContext.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 = DETACHED;
}
}
}
if (entityState == null) {
entityState = EntityState.getEntityState(entity, event.getEntityName(), entry, source, false);
}
switch(entityState) {
case DETACHED:
return entityIsDetached(event, copyCache);
case TRANSIENT:
return entityIsTransient(event, copyCache);
case PERSISTENT:
return entityIsPersistent(event, copyCache);
default:
// DELETED
throw new ObjectDeletedException("deleted instance passed to merge", null, EventUtil.getLoggableName(event.getEntityName(), entity));
}
}
}
return voidFuture();
}
use of org.hibernate.event.internal.EntityState in project hibernate-reactive by hibernate.
the class DefaultReactivePersistEventListener method reactiveOnPersist.
/**
* Handle the given create event.
*
* @param event The create event to be handled.
*/
public CompletionStage<Void> reactiveOnPersist(PersistEvent event, IdentitySet createCache) throws HibernateException {
final SessionImplementor source = event.getSession();
final Object object = event.getObject();
final Object entity;
if (object instanceof HibernateProxy) {
LazyInitializer li = ((HibernateProxy) object).getHibernateLazyInitializer();
if (li.isUninitialized()) {
if (li.getSession() == source) {
// NOTE EARLY EXIT!
return voidFuture();
} else {
return failedFuture(new PersistentObjectException("uninitialized proxy passed to persist()"));
}
}
entity = li.getImplementation();
} else {
entity = object;
}
final String entityName;
if (event.getEntityName() != null) {
entityName = event.getEntityName();
} else {
entityName = source.bestGuessEntityName(entity);
event.setEntityName(entityName);
}
final EntityEntry entityEntry = source.getPersistenceContextInternal().getEntry(entity);
EntityState entityState = EntityState.getEntityState(entity, entityName, entityEntry, source, true);
if (entityState == EntityState.DETACHED) {
// JPA 2, in its version of a "foreign generated", allows the id attribute value
// to be manually set by the user, even though this manual value is irrelevant.
// The issue is that this causes problems with the Hibernate unsaved-value strategy
// which comes into play here in determining detached/transient state.
//
// Detect if we have this situation and if so null out the id value and calculate the
// entity state again.
// NOTE: entityEntry must be null to get here, so we cannot use any of its values
EntityPersister persister = source.getFactory().getMetamodel().entityPersister(entityName);
if (persister.getIdentifierGenerator() instanceof ForeignGenerator) {
if (LOG.isDebugEnabled() && persister.getIdentifier(entity, source) != null) {
LOG.debug("Resetting entity id attribute to null for foreign generator");
}
persister.setIdentifier(entity, null, source);
entityState = EntityState.getEntityState(entity, entityName, entityEntry, source, true);
}
}
switch(entityState) {
case DETACHED:
{
return failedFuture(new PersistentObjectException("detached entity passed to persist: " + EventUtil.getLoggableName(event.getEntityName(), entity)));
}
case PERSISTENT:
{
return entityIsPersistent(event, createCache);
}
case TRANSIENT:
{
return entityIsTransient(event, createCache);
}
case DELETED:
{
entityEntry.setStatus(Status.MANAGED);
entityEntry.setDeletedState(null);
event.getSession().getActionQueue().unScheduleDeletion(entityEntry, event.getObject());
return entityIsDeleted(event, createCache);
}
default:
{
return failedFuture(new ObjectDeletedException("deleted entity passed to persist", null, EventUtil.getLoggableName(event.getEntityName(), entity)));
}
}
}
Aggregations