use of org.hibernate.reactive.session.ReactiveSession in project hibernate-reactive by hibernate.
the class DefaultReactiveMergeEventListener method fetchAndCopyValues.
private CompletionStage<Void> fetchAndCopyValues(final EntityPersister persister, final Object entity, final Object target, final SessionImplementor source, final MergeContext mergeContext) {
CompletionStage<Void> stage;
if (entity == target) {
// If entity == target, then nothing needs to be fetched.
stage = voidFuture();
} else {
ReactiveSession session = source.unwrap(ReactiveSession.class);
final Object[] mergeState = persister.getPropertyValues(entity);
final Object[] managedState = persister.getPropertyValues(target);
// Cascade-merge mappings do not determine what needs to be fetched.
// The value only needs to be fetched if the incoming value (mergeState[i])
// is initialized, but its corresponding managed state is not initialized.
// Initialization must be done before copyValues() executes.
stage = loop(0, mergeState.length, i -> Hibernate.isInitialized(mergeState[i]) && !Hibernate.isInitialized(managedState[i]), i -> session.reactiveFetch(managedState[i], true));
}
return stage.thenCompose(v -> copyValues(persister, entity, target, source, mergeContext));
}
use of org.hibernate.reactive.session.ReactiveSession in project hibernate-reactive by hibernate.
the class ReactiveAbstractEntityPersister method generateValue.
default CompletionStage<?> generateValue(Object owner, SharedSessionContractImplementor session, InMemoryValueGenerationStrategy valueGenerationStrategy) {
final ValueGenerator<?> valueGenerator = valueGenerationStrategy.getValueGenerator();
if (valueGenerator instanceof StageValueGenerator) {
final StageSessionFactoryImpl stageFactory = new StageSessionFactoryImpl((SessionFactoryImpl) session.getFactory());
final Stage.Session stageSession = new StageSessionImpl((ReactiveSession) session, stageFactory);
return ((StageValueGenerator<?>) valueGenerator).generateValue(stageSession, owner);
}
if (valueGenerator instanceof MutinyValueGenerator) {
MutinySessionFactoryImpl mutinyFactory = new MutinySessionFactoryImpl((SessionFactoryImpl) session.getFactory());
Mutiny.Session mutinySession = new MutinySessionImpl((ReactiveSession) session, mutinyFactory);
return ((MutinyValueGenerator<?>) valueGenerator).generateValue(mutinySession, owner).subscribeAsCompletionStage();
}
// annotations. We need an alternative for Hibernate Reactive.
return completedFuture(valueGenerationStrategy.getValueGenerator().generateValue((Session) session, owner));
}
use of org.hibernate.reactive.session.ReactiveSession in project hibernate-reactive by hibernate.
the class DefaultReactivePostLoadEventListener method onPostLoad.
@Override
public void onPostLoad(PostLoadEvent event) {
final Object entity = event.getEntity();
callbackRegistry.postLoad(entity);
final SessionImplementor session = event.getSession();
final EntityEntry entry = session.getPersistenceContextInternal().getEntry(entity);
if (entry == null) {
throw new AssertionFailure("possible non-threadsafe access to the session");
}
LockMode lockMode = entry.getLockMode();
if (LockMode.OPTIMISTIC_FORCE_INCREMENT.equals(lockMode)) {
((ReactiveSession) session).getReactiveActionQueue().registerProcess(new ReactiveEntityIncrementVersionProcess(entity));
} else if (LockMode.OPTIMISTIC.equals(lockMode)) {
((ReactiveSession) session).getReactiveActionQueue().registerProcess(new ReactiveEntityVerifyVersionProcess(entity));
}
}
use of org.hibernate.reactive.session.ReactiveSession in project hibernate-reactive by hibernate.
the class AbstractReactiveSaveEventListener method reactiveSaveWithGeneratedId.
/**
* Prepares the save call using a newly generated id.
*
* @param entity The entity to be saved
* @param entityName The entity-name for the entity to be saved
* @param context Generally cascade-specific information.
* @param source The session which is the source of this save event.
* @param requiresImmediateIdAccess does the event context require
* access to the identifier immediately after 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 CompletionStage<Void> reactiveSaveWithGeneratedId(Object entity, String entityName, C context, EventSource source, boolean requiresImmediateIdAccess) {
callbackRegistry.preCreate(entity);
if (entity instanceof SelfDirtinessTracker) {
((SelfDirtinessTracker) entity).$$_hibernate_clearDirtyAttributes();
}
EntityPersister persister = source.getEntityPersister(entityName, entity);
boolean autoincrement = persister.isIdentifierAssignedByInsert();
return generateId(entity, persister, (ReactiveSession) source, source.getSession()).thenCompose(id -> reactivePerformSave(entity, autoincrement ? null : assignIdIfNecessary(id, entity, persister, source.getSession()), persister, autoincrement, context, source, !autoincrement || requiresImmediateIdAccess));
}
use of org.hibernate.reactive.session.ReactiveSession in project hibernate-reactive by hibernate.
the class Cascade method cascadeLogicalOneToOneOrphanRemoval.
private void cascadeLogicalOneToOneOrphanRemoval(final int componentPathStackDepth, final Object child, final Type type, final CascadeStyle style, final String propertyName, final boolean isCascadeDeleteEnabled) throws HibernateException {
// potentially we need to handle orphan deletes for one-to-ones here...
if (isLogicalOneToOne(type)) {
// orphan checking
if (style.hasOrphanDelete() && action.deleteOrphans()) {
// value is orphaned if loaded state for this property shows not null
// because it is currently null.
final PersistenceContext persistenceContext = eventSource.getPersistenceContextInternal();
final EntityEntry entry = persistenceContext.getEntry(parent);
if (entry != null && entry.getStatus() != Status.SAVING) {
Object loadedValue;
if (componentPathStackDepth == 0) {
// association defined on entity
loadedValue = entry.getLoadedValue(propertyName);
} else {
// association defined on component
// todo : this is currently unsupported because of the fact that
// we do not know the loaded state of this value properly
// and doing so would be very difficult given how components and
// entities are loaded (and how 'loaded state' is put into the
// EntityEntry). Solutions here are to either:
// 1) properly account for components as a 2-phase load construct
// 2) just assume the association was just now orphaned and
// issue the orphan delete. This would require a special
// set of SQL statements though since we do not know the
// orphaned value, something a delete with a subquery to
// match the owner.
// final EntityType entityType = (EntityType) type;
// final String getPropertyPath = composePropertyPath( entityType.getPropertyName() );
loadedValue = null;
}
// entity is managed (without first nulling and manually flushing).
if (child == null || (loadedValue != null && child != loadedValue)) {
EntityEntry valueEntry = persistenceContext.getEntry(loadedValue);
if (valueEntry == null && loadedValue instanceof HibernateProxy) {
// un-proxy and re-associate for cascade operation
// useful for @OneToOne defined as FetchType.LAZY
loadedValue = persistenceContext.unproxyAndReassociate(loadedValue);
valueEntry = persistenceContext.getEntry(loadedValue);
// associated one-to-one.
if (child == loadedValue) {
// do nothing
return;
}
}
if (valueEntry != null) {
EntityPersister persister = valueEntry.getPersister();
String entityName = persister.getEntityName();
if (LOG.isTraceEnabled()) {
LOG.tracev("Deleting orphaned entity instance: {0}", infoString(entityName, persister.getIdentifier(loadedValue, eventSource)));
}
final Object loaded = loadedValue;
if (type.isAssociationType() && ((AssociationType) type).getForeignKeyDirection().equals(ForeignKeyDirection.TO_PARENT)) {
// If FK direction is to-parent, we must remove the orphan *before* the queued update(s)
// occur. Otherwise, replacing the association on a managed entity, without manually
// nulling and flushing, causes FK constraint violations.
stage = stage.thenCompose(v -> ((ReactiveSession) eventSource).reactiveRemoveOrphanBeforeUpdates(entityName, loaded));
} else {
// Else, we must delete after the updates.
stage = stage.thenCompose(v -> ((ReactiveSession) eventSource).reactiveRemove(entityName, loaded, isCascadeDeleteEnabled, new IdentitySet()));
}
}
}
}
}
}
}
Aggregations