Introduce `VirtualIdEmbeddable` and `IdClassEmbeddable` + instantiators

EmbeddableInitializer fully uses EmbeddableInstantiator and value injection

Still need to
  - integrate EmbeddableInstantiator work (ComponentType/ComponentTuplizer)
  - integrate embedded forms.  `VirtualIdEmbeddable` does not really need it as it can use the id-mapping itself as the embedded form.  But `IdClassEmbedded` should really be integrated
  - integrate `VirtualKeyEmbeddable` and `VirtualKeyEmbedded` for use as inverse composite fks
  - share `#finishInit` handling for `EmbeddableMappingType`, `VirtualIdEmbeddable` and `IdClassEmbeddable`
  - ability to use the containing composite owner as the parent of a composite (legacy behavior is to always use the "first" entity
This commit is contained in:
Steve Ebersole 2021-11-30 19:34:37 -06:00
parent 82d884d65c
commit a9fce4b69d
1 changed files with 20 additions and 16 deletions

View File

@ -67,6 +67,7 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
// and every row // and every row
private final Object[] resolvedValues; private final Object[] resolvedValues;
private Boolean allValuesNull; private Boolean allValuesNull;
private Boolean stateInjected;
private Object compositeInstance; private Object compositeInstance;
@ -155,6 +156,8 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
navigablePath navigablePath
); );
stateInjected = false;
extractRowState( processingState ); extractRowState( processingState );
prepareCompositeInstance( processingState ); prepareCompositeInstance( processingState );
handleParentInjection( processingState ); handleParentInjection( processingState );
@ -165,9 +168,10 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
if ( compositeInstance instanceof HibernateProxy ) { if ( compositeInstance instanceof HibernateProxy ) {
final Initializer parentInitializer = processingState.resolveInitializer( navigablePath.getParent() ); final Initializer parentInitializer = processingState.resolveInitializer( navigablePath.getParent() );
if ( parentInitializer != this ) { if ( parentInitializer != this ) {
( (FetchParentAccess) parentInitializer ).registerResolutionListener( ( (FetchParentAccess) parentInitializer ).registerResolutionListener( (entity) -> {
(entity) -> representationEmbeddable.setPropertyValues( entity, resolvedValues ) representationEmbeddable.setPropertyValues( entity, resolvedValues );
); stateInjected = true;
} );
} }
else { else {
// At this point, createEmptyCompositesEnabled is always true, so we generate // At this point, createEmptyCompositesEnabled is always true, so we generate
@ -182,13 +186,15 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
final Object target = representationStrategy final Object target = representationStrategy
.getInstantiator() .getInstantiator()
.instantiate( valuesAccess, sessionFactory); .instantiate( valuesAccess, sessionFactory);
stateInjected = true;
( (HibernateProxy) compositeInstance ).getHibernateLazyInitializer().setImplementation( target ); ( (HibernateProxy) compositeInstance ).getHibernateLazyInitializer().setImplementation( target );
} }
} }
else if ( allValuesNull == FALSE ) { else if ( allValuesNull == FALSE && stateInjected != TRUE ) {
// todo (6.0) : i think this is still called for cases where // todo (6.0) : i think this is still called for cases where
// we have already done the "ctor injection" // we have already done the "ctor injection"
representationEmbeddable.setPropertyValues( compositeInstance, resolvedValues ); representationEmbeddable.setPropertyValues( compositeInstance, resolvedValues );
stateInjected = true;
} }
} }
} }
@ -290,8 +296,8 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
final Supplier<Object[]> valuesAccess = allValuesNull == TRUE final Supplier<Object[]> valuesAccess = allValuesNull == TRUE
? null ? null
: () -> resolvedValues; : () -> resolvedValues;
final Object instance = representationStrategy.getInstantiator().instantiate( valuesAccess, sessionFactory ); final Object instance = representationStrategy.getInstantiator().instantiate( valuesAccess, sessionFactory );
stateInjected = true;
EmbeddableLoadingLogger.INSTANCE.debugf( "Created composite instance [%s] : %s", navigablePath, instance ); EmbeddableLoadingLogger.INSTANCE.debugf( "Created composite instance [%s] : %s", navigablePath, instance );
@ -299,12 +305,6 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
} }
private void handleParentInjection(RowProcessingState processingState) { private void handleParentInjection(RowProcessingState processingState) {
final PropertyAccess parentInjectionAccess = embedded.getParentInjectionAttributePropertyAccess();
if ( parentInjectionAccess == null ) {
// embeddable defined no parent injection
return;
}
// todo (6.0) : should we initialize the composite instance if we get here and it is null (not NULL_MARKER)? // todo (6.0) : should we initialize the composite instance if we get here and it is null (not NULL_MARKER)?
// we want to avoid injection for `NULL_MARKER` // we want to avoid injection for `NULL_MARKER`
@ -316,6 +316,12 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
return; return;
} }
final PropertyAccess parentInjectionAccess = embedded.getParentInjectionAttributePropertyAccess();
if ( parentInjectionAccess == null ) {
// embeddable defined no parent injection
return;
}
final Object parent = determineParentInstance( processingState ); final Object parent = determineParentInstance( processingState );
if ( parent == null ) { if ( parent == null ) {
EmbeddableLoadingLogger.INSTANCE.debugf( EmbeddableLoadingLogger.INSTANCE.debugf(
@ -332,11 +338,7 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
compositeInstance compositeInstance
); );
parentInjectionAccess.getSetter().set( parentInjectionAccess.getSetter().set( compositeInstance, parent, sessionFactory );
compositeInstance,
parent,
sessionFactory
);
} }
private Object determineParentInstance(RowProcessingState processingState) { private Object determineParentInstance(RowProcessingState processingState) {
@ -387,6 +389,8 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
public void finishUpRow(RowProcessingState rowProcessingState) { public void finishUpRow(RowProcessingState rowProcessingState) {
compositeInstance = null; compositeInstance = null;
allValuesNull = null; allValuesNull = null;
stateInjected = null;
clearResolutionListeners(); clearResolutionListeners();
} }