|
7 | 7 |
|
8 | 8 | import java.io.Serializable;
|
9 | 9 | import java.util.Iterator;
|
| 10 | +import java.util.List; |
10 | 11 | import java.util.Map;
|
11 | 12 | import java.util.concurrent.CompletionStage;
|
12 | 13 | import java.util.function.BiConsumer;
|
|
30 | 31 | import org.hibernate.engine.spi.SessionImplementor;
|
31 | 32 | import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
32 | 33 | import org.hibernate.engine.spi.Status;
|
| 34 | +import org.hibernate.event.service.spi.EventListenerGroup; |
| 35 | +import org.hibernate.event.spi.PostLoadEvent; |
| 36 | +import org.hibernate.event.spi.PostLoadEventListener; |
33 | 37 | import org.hibernate.persister.collection.CollectionPersister;
|
34 | 38 | import org.hibernate.persister.entity.EntityPersister;
|
| 39 | +import org.hibernate.reactive.engine.impl.ReactiveCallbackImpl; |
35 | 40 | import org.hibernate.reactive.logging.impl.Log;
|
36 | 41 | import org.hibernate.reactive.persister.entity.impl.ReactiveEntityPersister;
|
37 | 42 | import org.hibernate.reactive.session.ReactiveSession;
|
| 43 | +import org.hibernate.sql.exec.spi.Callback; |
38 | 44 | import org.hibernate.sql.results.graph.entity.EntityInitializer;
|
39 | 45 | import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingState;
|
40 | 46 | import org.hibernate.sql.results.spi.LoadContexts;
|
41 | 47 |
|
42 | 48 | import static java.lang.invoke.MethodHandles.lookup;
|
43 | 49 | import static org.hibernate.reactive.logging.impl.LoggerFactory.make;
|
44 | 50 | import static org.hibernate.reactive.util.impl.CompletionStages.completedFuture;
|
| 51 | +import static org.hibernate.reactive.util.impl.CompletionStages.loop; |
45 | 52 | import static org.hibernate.reactive.util.impl.CompletionStages.voidFuture;
|
46 | 53 |
|
47 | 54 | /**
|
@@ -456,7 +463,7 @@ public EntityHolder removeEntityHolder(EntityKey key) {
|
456 | 463 |
|
457 | 464 | @Override
|
458 | 465 | public void postLoad(JdbcValuesSourceProcessingState processingState, Consumer<EntityHolder> loadedConsumer) {
|
459 |
| - delegate.postLoad( processingState, loadedConsumer ); |
| 466 | + throw LOG.nonReactiveMethodCall( "reactivePostLoad(JdbcValuesSourceProcessingState, Consumer<EntityHolder>) )" ); |
460 | 467 | }
|
461 | 468 |
|
462 | 469 | @Internal
|
@@ -710,4 +717,82 @@ public Iterator<Object> managedEntitiesIterator() {
|
710 | 717 | public NaturalIdResolutions getNaturalIdResolutions() {
|
711 | 718 | return delegate.getNaturalIdResolutions();
|
712 | 719 | }
|
| 720 | + |
| 721 | + /** |
| 722 | + * Reactive version of {@link StatefulPersistenceContext#postLoad(JdbcValuesSourceProcessingState, Consumer)} |
| 723 | + */ |
| 724 | + public CompletionStage<Void> reactivePostLoad( |
| 725 | + JdbcValuesSourceProcessingState processingState, |
| 726 | + Consumer<EntityHolder> holderConsumer) { |
| 727 | + final ReactiveCallbackImpl callback = (ReactiveCallbackImpl) processingState |
| 728 | + .getExecutionContext().getCallback(); |
| 729 | + return processHolders( |
| 730 | + holderConsumer, |
| 731 | + processingState.getLoadingEntityHolders(), |
| 732 | + getSession().getFactory().getEventListenerGroups().eventListenerGroup_POST_LOAD, |
| 733 | + processingState.getPostLoadEvent(), |
| 734 | + callback |
| 735 | + ).thenCompose( v -> processHolders( |
| 736 | + holderConsumer, |
| 737 | + processingState.getReloadedEntityHolders(), |
| 738 | + null, |
| 739 | + null, |
| 740 | + callback |
| 741 | + ) ); |
| 742 | + } |
| 743 | + |
| 744 | + private CompletionStage<Void> processHolders( |
| 745 | + Consumer<EntityHolder> holderConsumer, |
| 746 | + List<EntityHolder> loadingEntityHolders, |
| 747 | + EventListenerGroup<PostLoadEventListener> listenerGroup, |
| 748 | + PostLoadEvent postLoadEvent, |
| 749 | + ReactiveCallbackImpl callback) { |
| 750 | + if ( loadingEntityHolders != null ) { |
| 751 | + return loop( loadingEntityHolders, |
| 752 | + holder -> processLoadedEntityHolder( |
| 753 | + holder, |
| 754 | + listenerGroup, |
| 755 | + postLoadEvent, |
| 756 | + callback, |
| 757 | + holderConsumer |
| 758 | + ) |
| 759 | + ).thenAccept( v -> loadingEntityHolders.clear() ); |
| 760 | + } |
| 761 | + return voidFuture(); |
| 762 | + } |
| 763 | + |
| 764 | + /** |
| 765 | + * Reactive version of {@link StatefulPersistenceContext#processLoadedEntityHolder(EntityHolder, EventListenerGroup, PostLoadEvent, Callback, Consumer)} |
| 766 | + */ |
| 767 | + private CompletionStage<Void> processLoadedEntityHolder( |
| 768 | + EntityHolder holder, |
| 769 | + EventListenerGroup<PostLoadEventListener> listenerGroup, |
| 770 | + PostLoadEvent postLoadEvent, |
| 771 | + ReactiveCallbackImpl callback, |
| 772 | + Consumer<EntityHolder> holderConsumer) { |
| 773 | + if ( holderConsumer != null ) { |
| 774 | + holderConsumer.accept( holder ); |
| 775 | + } |
| 776 | + if ( holder.getEntity() == null ) { |
| 777 | + // It's possible that we tried to load an entity and found out it doesn't exist, |
| 778 | + // in which case we added an entry with a null proxy and entity. |
| 779 | + // Remove that empty entry on post load to avoid unwanted side effects |
| 780 | + getEntitiesByKey().remove( holder.getEntityKey() ); |
| 781 | + } |
| 782 | + else { |
| 783 | + if ( postLoadEvent != null ) { |
| 784 | + postLoadEvent.reset(); |
| 785 | + postLoadEvent.setEntity( holder.getEntity() ) |
| 786 | + .setId( holder.getEntityKey().getIdentifier() ) |
| 787 | + .setPersister( holder.getDescriptor() ); |
| 788 | + listenerGroup.fireEventOnEachListener( postLoadEvent, PostLoadEventListener::onPostLoad ); |
| 789 | + if ( callback != null ) { |
| 790 | + return callback |
| 791 | + .invokeReactiveLoadActions( holder.getEntity(), holder.getDescriptor(), getSession() ) |
| 792 | + .thenAccept( v -> holder.resetEntityInitialier() ); |
| 793 | + } |
| 794 | + } |
| 795 | + } |
| 796 | + return voidFuture(); |
| 797 | + } |
713 | 798 | }
|
0 commit comments