mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-07 11:48:18 +00:00
HHH-18959 remove unused ResolveNaturalIdEvent stuff
this has all been obsolete since Hibernate 6.0
This commit is contained in:
parent
18c56775da
commit
07ecda306a
@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
||||||
* Copyright Red Hat Inc. and Hibernate Authors
|
|
||||||
*/
|
|
||||||
package org.hibernate.event.internal;
|
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.engine.spi.NaturalIdResolutions;
|
|
||||||
import org.hibernate.event.spi.EventSource;
|
|
||||||
import org.hibernate.event.spi.ResolveNaturalIdEvent;
|
|
||||||
import org.hibernate.event.spi.ResolveNaturalIdEventListener;
|
|
||||||
import org.hibernate.internal.CoreLogging;
|
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
|
||||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
|
||||||
|
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
|
||||||
import static java.util.concurrent.TimeUnit.NANOSECONDS;
|
|
||||||
import static org.hibernate.pretty.MessageHelper.infoString;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines the default load event listeners used by hibernate for loading entities
|
|
||||||
* in response to generated load events.
|
|
||||||
*
|
|
||||||
* @author Eric Dalquist
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class DefaultResolveNaturalIdEventListener implements ResolveNaturalIdEventListener {
|
|
||||||
|
|
||||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DefaultResolveNaturalIdEventListener.class );
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResolveNaturalId(ResolveNaturalIdEvent event) throws HibernateException {
|
|
||||||
event.setEntityId( resolveNaturalId( event ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Coordinates the efforts to load a given entity. First, an attempt is
|
|
||||||
* made to load the entity from the session-level cache. If not found there,
|
|
||||||
* an attempt is made to locate it in second-level cache. Lastly, an
|
|
||||||
* attempt is made to load it directly from the datasource.
|
|
||||||
*
|
|
||||||
* @param event The load event
|
|
||||||
*
|
|
||||||
* @return The loaded entity, or null.
|
|
||||||
*/
|
|
||||||
protected Object resolveNaturalId(final ResolveNaturalIdEvent event) {
|
|
||||||
final EntityPersister persister = event.getEntityPersister();
|
|
||||||
|
|
||||||
if ( LOG.isTraceEnabled() ) {
|
|
||||||
LOG.trace( "Attempting to resolve: " + infoString( persister ) + "#" + event.getNaturalIdValues() );
|
|
||||||
}
|
|
||||||
|
|
||||||
final Object entityId = resolveFromCache( event );
|
|
||||||
if ( entityId != null ) {
|
|
||||||
if ( LOG.isTraceEnabled() ) {
|
|
||||||
LOG.trace( "Resolved object in cache: " + infoString( persister ) + "#" + event.getNaturalIdValues() );
|
|
||||||
}
|
|
||||||
return entityId;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ( LOG.isTraceEnabled() ) {
|
|
||||||
LOG.trace( "Object not resolved in any cache: "+ infoString( persister ) + "#" + event.getNaturalIdValues() );
|
|
||||||
}
|
|
||||||
return loadFromDatasource( event );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to resolve the entity id corresponding to the event's natural id values from the session
|
|
||||||
*
|
|
||||||
* @param event The load event
|
|
||||||
*
|
|
||||||
* @return The entity from the cache, or null.
|
|
||||||
*/
|
|
||||||
protected Object resolveFromCache(ResolveNaturalIdEvent event) {
|
|
||||||
return getNaturalIdResolutions( event)
|
|
||||||
.findCachedIdByNaturalId( event.getOrderedNaturalIdValues(), event.getEntityPersister() );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs the process of loading an entity from the configured
|
|
||||||
* underlying datasource.
|
|
||||||
*
|
|
||||||
* @param event The load event
|
|
||||||
*
|
|
||||||
* @return The object loaded from the datasource, or null if not found.
|
|
||||||
*/
|
|
||||||
protected Object loadFromDatasource(ResolveNaturalIdEvent event) {
|
|
||||||
final EventSource session = event.getSession();
|
|
||||||
final EntityPersister entityPersister = event.getEntityPersister();
|
|
||||||
final StatisticsImplementor statistics = event.getFactory().getStatistics();
|
|
||||||
final boolean statisticsEnabled = statistics.isStatisticsEnabled();
|
|
||||||
final long startTime = statisticsEnabled ? System.nanoTime() : 0;
|
|
||||||
|
|
||||||
final Object pk = entityPersister.loadEntityIdByNaturalId(
|
|
||||||
event.getOrderedNaturalIdValues(),
|
|
||||||
event.getLockOptions(),
|
|
||||||
session
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( statisticsEnabled ) {
|
|
||||||
final long endTime = System.nanoTime();
|
|
||||||
final long milliseconds = MILLISECONDS.convert( endTime - startTime, NANOSECONDS );
|
|
||||||
statistics.naturalIdQueryExecuted( entityPersister.getRootEntityName(), milliseconds );
|
|
||||||
}
|
|
||||||
|
|
||||||
//PK can be null if the entity doesn't exist
|
|
||||||
if ( pk != null ) {
|
|
||||||
getNaturalIdResolutions( event )
|
|
||||||
.cacheResolutionFromLoad( pk, event.getOrderedNaturalIdValues(), entityPersister );
|
|
||||||
}
|
|
||||||
return pk;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static NaturalIdResolutions getNaturalIdResolutions(ResolveNaturalIdEvent event) {
|
|
||||||
return event.getSession().getPersistenceContextInternal().getNaturalIdResolutions();
|
|
||||||
}
|
|
||||||
}
|
|
@ -29,7 +29,6 @@
|
|||||||
import org.hibernate.event.internal.DefaultPreLoadEventListener;
|
import org.hibernate.event.internal.DefaultPreLoadEventListener;
|
||||||
import org.hibernate.event.internal.DefaultRefreshEventListener;
|
import org.hibernate.event.internal.DefaultRefreshEventListener;
|
||||||
import org.hibernate.event.internal.DefaultReplicateEventListener;
|
import org.hibernate.event.internal.DefaultReplicateEventListener;
|
||||||
import org.hibernate.event.internal.DefaultResolveNaturalIdEventListener;
|
|
||||||
import org.hibernate.event.internal.PostDeleteEventListenerStandardImpl;
|
import org.hibernate.event.internal.PostDeleteEventListenerStandardImpl;
|
||||||
import org.hibernate.event.internal.PostInsertEventListenerStandardImpl;
|
import org.hibernate.event.internal.PostInsertEventListenerStandardImpl;
|
||||||
import org.hibernate.event.internal.PostUpdateEventListenerStandardImpl;
|
import org.hibernate.event.internal.PostUpdateEventListenerStandardImpl;
|
||||||
@ -75,7 +74,6 @@
|
|||||||
import static org.hibernate.event.spi.EventType.PRE_UPSERT;
|
import static org.hibernate.event.spi.EventType.PRE_UPSERT;
|
||||||
import static org.hibernate.event.spi.EventType.REFRESH;
|
import static org.hibernate.event.spi.EventType.REFRESH;
|
||||||
import static org.hibernate.event.spi.EventType.REPLICATE;
|
import static org.hibernate.event.spi.EventType.REPLICATE;
|
||||||
import static org.hibernate.event.spi.EventType.RESOLVE_NATURAL_ID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard implementation of EventListenerRegistry
|
* Standard implementation of EventListenerRegistry
|
||||||
@ -240,9 +238,6 @@ private void applyStandardListeners() {
|
|||||||
// load listeners
|
// load listeners
|
||||||
prepareListeners( LOAD, new DefaultLoadEventListener() );
|
prepareListeners( LOAD, new DefaultLoadEventListener() );
|
||||||
|
|
||||||
// resolve natural-id listeners
|
|
||||||
prepareListeners( RESOLVE_NATURAL_ID, new DefaultResolveNaturalIdEventListener() );
|
|
||||||
|
|
||||||
// load-collection listeners
|
// load-collection listeners
|
||||||
prepareListeners( INIT_COLLECTION, new DefaultInitializeCollectionEventListener() );
|
prepareListeners( INIT_COLLECTION, new DefaultInitializeCollectionEventListener() );
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ public final class EventType<T> {
|
|||||||
private static final AtomicInteger STANDARD_TYPE_COUNTER = new AtomicInteger();
|
private static final AtomicInteger STANDARD_TYPE_COUNTER = new AtomicInteger();
|
||||||
|
|
||||||
public static final EventType<LoadEventListener> LOAD = create( "load", LoadEventListener.class );
|
public static final EventType<LoadEventListener> LOAD = create( "load", LoadEventListener.class );
|
||||||
public static final EventType<ResolveNaturalIdEventListener> RESOLVE_NATURAL_ID = create( "resolve-natural-id", ResolveNaturalIdEventListener.class );
|
|
||||||
|
|
||||||
public static final EventType<InitializeCollectionEventListener> INIT_COLLECTION = create( "load-collection", InitializeCollectionEventListener.class );
|
public static final EventType<InitializeCollectionEventListener> INIT_COLLECTION = create( "load-collection", InitializeCollectionEventListener.class );
|
||||||
|
|
||||||
|
@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
||||||
* Copyright Red Hat Inc. and Hibernate Authors
|
|
||||||
*/
|
|
||||||
package org.hibernate.event.spi;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.LockMode;
|
|
||||||
import org.hibernate.LockOptions;
|
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines an event class for the resolving of an entity id from the entity's natural-id
|
|
||||||
*
|
|
||||||
* @author Eric Dalquist
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class ResolveNaturalIdEvent extends AbstractEvent {
|
|
||||||
public static final LockMode DEFAULT_LOCK_MODE = LockMode.NONE;
|
|
||||||
|
|
||||||
private final EntityPersister entityPersister;
|
|
||||||
private final Map<String, Object> naturalIdValues;
|
|
||||||
private final Object[] orderedNaturalIdValues;
|
|
||||||
private final LockOptions lockOptions;
|
|
||||||
|
|
||||||
private Object entityId;
|
|
||||||
|
|
||||||
public ResolveNaturalIdEvent(Map<String, Object> naturalIdValues, EntityPersister entityPersister, EventSource source) {
|
|
||||||
this( naturalIdValues, entityPersister, LockOptions.NONE, source );
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResolveNaturalIdEvent(
|
|
||||||
Map<String, Object> naturalIdValues,
|
|
||||||
EntityPersister entityPersister,
|
|
||||||
LockOptions lockOptions,
|
|
||||||
EventSource source) {
|
|
||||||
super( source );
|
|
||||||
|
|
||||||
if ( entityPersister == null ) {
|
|
||||||
throw new IllegalArgumentException( "EntityPersister is required for loading" );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! entityPersister.hasNaturalIdentifier() ) {
|
|
||||||
throw new HibernateException( "Entity did not define a natural-id" );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( naturalIdValues == null || naturalIdValues.isEmpty() ) {
|
|
||||||
throw new IllegalArgumentException( "natural-id to load is required" );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( entityPersister.getNaturalIdentifierProperties().length != naturalIdValues.size() ) {
|
|
||||||
throw new HibernateException(
|
|
||||||
String.format(
|
|
||||||
"Entity [%s] defines its natural-id with %d properties but only %d were specified",
|
|
||||||
entityPersister.getEntityName(),
|
|
||||||
entityPersister.getNaturalIdentifierProperties().length,
|
|
||||||
naturalIdValues.size()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( lockOptions.getLockMode() == LockMode.WRITE ) {
|
|
||||||
throw new IllegalArgumentException( "Invalid lock mode for loading" );
|
|
||||||
}
|
|
||||||
else if ( lockOptions.getLockMode() == null ) {
|
|
||||||
lockOptions.setLockMode( DEFAULT_LOCK_MODE );
|
|
||||||
}
|
|
||||||
|
|
||||||
this.entityPersister = entityPersister;
|
|
||||||
this.naturalIdValues = naturalIdValues;
|
|
||||||
this.lockOptions = lockOptions;
|
|
||||||
|
|
||||||
int[] naturalIdPropertyPositions = entityPersister.getNaturalIdentifierProperties();
|
|
||||||
orderedNaturalIdValues = new Object[naturalIdPropertyPositions.length];
|
|
||||||
int i = 0;
|
|
||||||
for ( int position : naturalIdPropertyPositions ) {
|
|
||||||
final String propertyName = entityPersister.getPropertyNames()[position];
|
|
||||||
if ( ! naturalIdValues.containsKey( propertyName ) ) {
|
|
||||||
throw new HibernateException(
|
|
||||||
String.format( "No value specified for natural-id property %s#%s", getEntityName(), propertyName )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
orderedNaturalIdValues[i++] = naturalIdValues.get( entityPersister.getPropertyNames()[position] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Object> getNaturalIdValues() {
|
|
||||||
return Collections.unmodifiableMap( naturalIdValues );
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object[] getOrderedNaturalIdValues() {
|
|
||||||
return orderedNaturalIdValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EntityPersister getEntityPersister() {
|
|
||||||
return entityPersister;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEntityName() {
|
|
||||||
return getEntityPersister().getEntityName();
|
|
||||||
}
|
|
||||||
|
|
||||||
public LockOptions getLockOptions() {
|
|
||||||
return lockOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getEntityId() {
|
|
||||||
return entityId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEntityId(Object entityId) {
|
|
||||||
this.entityId = entityId;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
||||||
* Copyright Red Hat Inc. and Hibernate Authors
|
|
||||||
*/
|
|
||||||
package org.hibernate.event.spi;
|
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines the contract for handling of resolve natural id events generated from a session.
|
|
||||||
*
|
|
||||||
* @author Eric Dalquist
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public interface ResolveNaturalIdEventListener {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the given resolve natural id event.
|
|
||||||
*
|
|
||||||
* @param event The resolve natural id event to be handled.
|
|
||||||
*
|
|
||||||
* @throws HibernateException Indicates a problem resolving natural id to primary key
|
|
||||||
*/
|
|
||||||
void onResolveNaturalId(ResolveNaturalIdEvent event) throws HibernateException;
|
|
||||||
|
|
||||||
}
|
|
@ -117,7 +117,6 @@ public final class FastSessionServices {
|
|||||||
public final EventListenerGroup<PreUpsertEventListener> eventListenerGroup_PRE_UPSERT;
|
public final EventListenerGroup<PreUpsertEventListener> eventListenerGroup_PRE_UPSERT;
|
||||||
public final EventListenerGroup<RefreshEventListener> eventListenerGroup_REFRESH;
|
public final EventListenerGroup<RefreshEventListener> eventListenerGroup_REFRESH;
|
||||||
public final EventListenerGroup<ReplicateEventListener> eventListenerGroup_REPLICATE;
|
public final EventListenerGroup<ReplicateEventListener> eventListenerGroup_REPLICATE;
|
||||||
public final EventListenerGroup<ResolveNaturalIdEventListener> eventListenerGroup_RESOLVE_NATURAL_ID;
|
|
||||||
|
|
||||||
// Fields used only from within this package
|
// Fields used only from within this package
|
||||||
final boolean disallowOutOfTransactionUpdateOperations;
|
final boolean disallowOutOfTransactionUpdateOperations;
|
||||||
@ -196,7 +195,6 @@ public final class FastSessionServices {
|
|||||||
this.eventListenerGroup_PRE_UPSERT = listeners( eventListenerRegistry, EventType.PRE_UPSERT );
|
this.eventListenerGroup_PRE_UPSERT = listeners( eventListenerRegistry, EventType.PRE_UPSERT );
|
||||||
this.eventListenerGroup_REFRESH = listeners( eventListenerRegistry, EventType.REFRESH );
|
this.eventListenerGroup_REFRESH = listeners( eventListenerRegistry, EventType.REFRESH );
|
||||||
this.eventListenerGroup_REPLICATE = listeners( eventListenerRegistry, EventType.REPLICATE );
|
this.eventListenerGroup_REPLICATE = listeners( eventListenerRegistry, EventType.REPLICATE );
|
||||||
this.eventListenerGroup_RESOLVE_NATURAL_ID = listeners( eventListenerRegistry, EventType.RESOLVE_NATURAL_ID );
|
|
||||||
|
|
||||||
//Other highly useful constants:
|
//Other highly useful constants:
|
||||||
this.dialect = jdbcServices.getJdbcEnvironment().getDialect();
|
this.dialect = jdbcServices.getJdbcEnvironment().getDialect();
|
||||||
|
@ -104,8 +104,6 @@
|
|||||||
import org.hibernate.event.spi.RefreshEventListener;
|
import org.hibernate.event.spi.RefreshEventListener;
|
||||||
import org.hibernate.event.spi.ReplicateEvent;
|
import org.hibernate.event.spi.ReplicateEvent;
|
||||||
import org.hibernate.event.spi.ReplicateEventListener;
|
import org.hibernate.event.spi.ReplicateEventListener;
|
||||||
import org.hibernate.event.spi.ResolveNaturalIdEvent;
|
|
||||||
import org.hibernate.event.spi.ResolveNaturalIdEventListener;
|
|
||||||
import org.hibernate.loader.internal.CacheLoadHelper;
|
import org.hibernate.loader.internal.CacheLoadHelper;
|
||||||
import org.hibernate.resource.transaction.spi.TransactionObserver;
|
import org.hibernate.resource.transaction.spi.TransactionObserver;
|
||||||
import org.hibernate.event.monitor.spi.EventMonitor;
|
import org.hibernate.event.monitor.spi.EventMonitor;
|
||||||
@ -1286,14 +1284,6 @@ private void fireLoadNoChecks(final LoadEvent event, final LoadType loadType) {
|
|||||||
.fireEventOnEachListener( event, loadType, LoadEventListener::onLoad );
|
.fireEventOnEachListener( event, loadType, LoadEventListener::onLoad );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fireResolveNaturalId(final ResolveNaturalIdEvent event) {
|
|
||||||
checkOpenOrWaitingForAutoClose();
|
|
||||||
pulseTransactionCoordinator();
|
|
||||||
fastSessionServices.eventListenerGroup_RESOLVE_NATURAL_ID
|
|
||||||
.fireEventOnEachListener( event, ResolveNaturalIdEventListener::onResolveNaturalId );
|
|
||||||
delayedAfterCompletion();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// refresh() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// refresh() operations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -74,34 +74,29 @@ public T load(Object naturalIdValue) {
|
|||||||
return doLoad( entityPersister().getNaturalIdMapping().normalizeInput( naturalIdValue) );
|
return doLoad( entityPersister().getNaturalIdMapping().normalizeInput( naturalIdValue) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that the given natural id is "simple".
|
||||||
|
* <p>
|
||||||
|
* We allow compound natural id "simple" loading if all the values are passed as an array,
|
||||||
|
* list, or map. We assume an array is properly ordered following the attribute ordering.
|
||||||
|
* For lists, just like arrays, we assume the user has ordered them properly; for maps,
|
||||||
|
* the key is expected to be the attribute name.
|
||||||
|
*/
|
||||||
private void verifySimplicity(Object naturalIdValue) {
|
private void verifySimplicity(Object naturalIdValue) {
|
||||||
assert naturalIdValue != null;
|
assert naturalIdValue != null;
|
||||||
|
if ( !hasSimpleNaturalId
|
||||||
if ( hasSimpleNaturalId ) {
|
&& !naturalIdValue.getClass().isArray()
|
||||||
// implicitly
|
&& !(naturalIdValue instanceof List)
|
||||||
return;
|
&& !(naturalIdValue instanceof Map) ) {
|
||||||
|
throw new HibernateException(
|
||||||
|
String.format(
|
||||||
|
Locale.ROOT,
|
||||||
|
"Cannot interpret natural-id value [%s] for compound natural-id: %s",
|
||||||
|
naturalIdValue,
|
||||||
|
entityPersister().getEntityName()
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( naturalIdValue.getClass().isArray() ) {
|
|
||||||
// we allow compound natural-id "simple" loading all the values are passed as an array
|
|
||||||
// (we assume the array is properly ordered following the mapping-model attribute ordering)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( naturalIdValue instanceof List || naturalIdValue instanceof Map ) {
|
|
||||||
// also allowed. For Lists, just like arrays, we assume the user has ordered them properly;
|
|
||||||
// for Maps, the key is expected to be the attribute name
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new HibernateException(
|
|
||||||
String.format(
|
|
||||||
Locale.ROOT,
|
|
||||||
"Cannot interpret natural-id value [%s] for compound natural-id: %s",
|
|
||||||
naturalIdValue,
|
|
||||||
entityPersister().getEntityName()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.cache.MutableCacheKeyBuilder;
|
import org.hibernate.cache.MutableCacheKeyBuilder;
|
||||||
import org.hibernate.engine.spi.PersistenceContext;
|
import org.hibernate.engine.spi.PersistenceContext;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.internal.util.IndexedConsumer;
|
import org.hibernate.internal.util.IndexedConsumer;
|
||||||
import org.hibernate.loader.ast.internal.CompoundNaturalIdLoader;
|
import org.hibernate.loader.ast.internal.CompoundNaturalIdLoader;
|
||||||
@ -22,7 +21,6 @@
|
|||||||
import org.hibernate.loader.ast.spi.NaturalIdLoader;
|
import org.hibernate.loader.ast.spi.NaturalIdLoader;
|
||||||
import org.hibernate.metamodel.UnsupportedMappingException;
|
import org.hibernate.metamodel.UnsupportedMappingException;
|
||||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.AttributeMetadata;
|
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
import org.hibernate.metamodel.mapping.MappingType;
|
import org.hibernate.metamodel.mapping.MappingType;
|
||||||
@ -89,7 +87,6 @@ public CompoundNaturalIdMapping(
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
this.jdbcMappings = jdbcMappings;
|
this.jdbcMappings = jdbcMappings;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -97,13 +94,10 @@ public CompoundNaturalIdMapping(
|
|||||||
|
|
||||||
private static boolean isMutable(List<SingularAttributeMapping> attributes) {
|
private static boolean isMutable(List<SingularAttributeMapping> attributes) {
|
||||||
for ( int i = 0; i < attributes.size(); i++ ) {
|
for ( int i = 0; i < attributes.size(); i++ ) {
|
||||||
final SingularAttributeMapping attributeMapping = attributes.get( i );
|
if ( attributes.get( i ).getAttributeMetadata().isUpdatable() ) {
|
||||||
final AttributeMetadata metadata = attributeMapping.getAttributeMetadata();
|
|
||||||
if ( metadata.isUpdatable() ) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,41 +106,34 @@ public Object[] extractNaturalIdFromEntityState(Object[] state) {
|
|||||||
if ( state == null ) {
|
if ( state == null ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
else if ( state.length == attributes.size() ) {
|
||||||
if ( state.length == attributes.size() ) {
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
final Object[] values = new Object[ attributes.size() ];
|
final Object[] values = new Object[attributes.size()];
|
||||||
|
for ( int i = 0; i <= attributes.size() - 1; i++ ) {
|
||||||
for ( int i = 0; i <= attributes.size() - 1; i++ ) {
|
final SingularAttributeMapping attributeMapping = attributes.get( i );
|
||||||
final SingularAttributeMapping attributeMapping = attributes.get( i );
|
values[i] = state[attributeMapping.getStateArrayPosition()];
|
||||||
values[ i ] = state[ attributeMapping.getStateArrayPosition() ];
|
}
|
||||||
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
return values;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object[] extractNaturalIdFromEntity(Object entity) {
|
public Object[] extractNaturalIdFromEntity(Object entity) {
|
||||||
final Object[] values = new Object[ attributes.size() ];
|
final Object[] values = new Object[ attributes.size() ];
|
||||||
|
|
||||||
for ( int i = 0; i < attributes.size(); i++ ) {
|
for ( int i = 0; i < attributes.size(); i++ ) {
|
||||||
values[i] = attributes.get( i ).getPropertyAccess().getGetter().get( entity );
|
values[i] = attributes.get( i ).getPropertyAccess().getGetter().get( entity );
|
||||||
}
|
}
|
||||||
|
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings( "rawtypes" )
|
|
||||||
public Object[] normalizeInput(Object incoming) {
|
public Object[] normalizeInput(Object incoming) {
|
||||||
if ( incoming instanceof Object[] ) {
|
if ( incoming instanceof Object[] array ) {
|
||||||
return (Object[]) incoming;
|
return array;
|
||||||
}
|
}
|
||||||
|
else if ( incoming instanceof Map<?,?> valueMap ) {
|
||||||
if ( incoming instanceof Map ) {
|
|
||||||
final Map valueMap = (Map) incoming;
|
|
||||||
final List<SingularAttributeMapping> attributes = getNaturalIdAttributes();
|
final List<SingularAttributeMapping> attributes = getNaturalIdAttributes();
|
||||||
final Object[] values = new Object[ attributes.size() ];
|
final Object[] values = new Object[ attributes.size() ];
|
||||||
for ( int i = 0; i < attributes.size(); i++ ) {
|
for ( int i = 0; i < attributes.size(); i++ ) {
|
||||||
@ -154,30 +141,28 @@ public Object[] normalizeInput(Object incoming) {
|
|||||||
}
|
}
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
throw new UnsupportedMappingException( "Do not know how to normalize compound natural-id value : " + incoming );
|
throw new UnsupportedMappingException( "Could not normalize compound natural-id value: " + incoming );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void validateInternalForm(Object naturalIdValue) {
|
public void validateInternalForm(Object naturalIdValue) {
|
||||||
if ( naturalIdValue == null ) {
|
if ( naturalIdValue != null ) {
|
||||||
return;
|
// should be an array, with a size equal to the number of attributes making up this compound natural-id
|
||||||
}
|
if ( naturalIdValue instanceof Object[] values ) {
|
||||||
|
if ( values.length != attributes.size() ) {
|
||||||
// should be an array, with a size equal to the number of attributes making up this compound natural-id
|
throw new IllegalArgumentException(
|
||||||
if ( naturalIdValue instanceof Object[] ) {
|
"Natural-id value [" + naturalIdValue + "] did not contain the expected number of elements ["
|
||||||
final Object[] values = (Object[]) naturalIdValue;
|
+ attributes.size() + "]"
|
||||||
if ( values.length != attributes.size() ) {
|
);
|
||||||
throw new IllegalArgumentException(
|
}
|
||||||
"Natural-id value [" + naturalIdValue + "] did not contain the expected number of elements ["
|
}
|
||||||
+ attributes.size() + "]"
|
else {
|
||||||
);
|
throw new IllegalArgumentException(
|
||||||
|
"Natural-id value [" + naturalIdValue + "] was not an array as expected" );
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalArgumentException( "Natural-id value [" + naturalIdValue + "] was not an array as expected" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -185,71 +170,65 @@ public int calculateHashCode(Object value) {
|
|||||||
if ( value == null ) {
|
if ( value == null ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Object[] values = (Object[]) value;
|
else {
|
||||||
int hashcode = 0;
|
final Object[] values = (Object[]) value;
|
||||||
for ( int i = 0; i < attributes.size(); i++ ) {
|
int hashcode = 0;
|
||||||
final Object o = values[i];
|
for ( int i = 0; i < attributes.size(); i++ ) {
|
||||||
if ( o != null ) {
|
final Object o = values[i];
|
||||||
hashcode = 27 * hashcode + ( (JavaType) attributes.get( i ).getExpressibleJavaType() ).extractHashCode( o );
|
if ( o != null ) {
|
||||||
|
hashcode = 27 * hashcode
|
||||||
|
+ ((JavaType) attributes.get( i ).getExpressibleJavaType()).extractHashCode( o );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return hashcode;
|
||||||
}
|
}
|
||||||
return hashcode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void verifyFlushState(Object id, Object[] currentState, Object[] loadedState, SharedSessionContractImplementor session) {
|
public void verifyFlushState(Object id, Object[] currentState, Object[] loadedState, SharedSessionContractImplementor session) {
|
||||||
if ( isMutable() ) {
|
if ( !isMutable() ) {
|
||||||
// EARLY EXIT!!!
|
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
||||||
// the natural id is mutable (!immutable), no need to do the checks
|
final EntityPersister persister = getDeclaringType().getEntityPersister();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
final Object[] naturalId = extractNaturalIdFromEntityState( currentState );
|
||||||
final EntityPersister persister = getDeclaringType().getEntityPersister();
|
final Object snapshot = loadedState == null
|
||||||
|
? persistenceContext.getNaturalIdSnapshot( id, persister )
|
||||||
|
: persister.getNaturalIdMapping().extractNaturalIdFromEntityState( loadedState );
|
||||||
|
final Object[] previousNaturalId = (Object[]) snapshot;
|
||||||
|
assert naturalId.length == getNaturalIdAttributes().size();
|
||||||
|
assert previousNaturalId.length == naturalId.length;
|
||||||
|
|
||||||
final Object[] naturalId = extractNaturalIdFromEntityState( currentState );
|
for ( int i = 0; i < getNaturalIdAttributes().size(); i++ ) {
|
||||||
|
final SingularAttributeMapping attributeMapping = getNaturalIdAttributes().get( i );
|
||||||
final Object snapshot = loadedState == null
|
final boolean updatable = attributeMapping.getAttributeMetadata().isUpdatable();
|
||||||
? persistenceContext.getNaturalIdSnapshot( id, persister )
|
if ( !updatable ) {
|
||||||
: persister.getNaturalIdMapping().extractNaturalIdFromEntityState( loadedState );
|
final Object currentValue = naturalId[i];
|
||||||
final Object[] previousNaturalId = (Object[]) snapshot;
|
final Object previousValue = previousNaturalId[i];
|
||||||
|
if ( !attributeMapping.areEqual( currentValue, previousValue, session ) ) {
|
||||||
assert naturalId.length == getNaturalIdAttributes().size();
|
throw new HibernateException(
|
||||||
assert previousNaturalId.length == naturalId.length;
|
String.format(
|
||||||
|
"An immutable attribute [%s] within compound natural identifier of entity %s was altered from `%s` to `%s`",
|
||||||
for ( int i = 0; i < getNaturalIdAttributes().size(); i++ ) {
|
attributeMapping.getAttributeName(),
|
||||||
final SingularAttributeMapping attributeMapping = getNaturalIdAttributes().get( i );
|
persister.getEntityName(),
|
||||||
|
previousValue,
|
||||||
final boolean updatable = attributeMapping.getAttributeMetadata().isUpdatable();
|
currentValue
|
||||||
if ( updatable ) {
|
)
|
||||||
// property is updatable (mutable), there is nothing to check
|
);
|
||||||
continue;
|
}
|
||||||
}
|
}
|
||||||
|
// else property is updatable (mutable), there is nothing to check
|
||||||
final Object currentValue = naturalId[ i ];
|
|
||||||
final Object previousValue = previousNaturalId[ i ];
|
|
||||||
|
|
||||||
if ( ! attributeMapping.areEqual( currentValue, previousValue, session ) ) {
|
|
||||||
throw new HibernateException(
|
|
||||||
String.format(
|
|
||||||
"An immutable attribute [%s] within compound natural identifier of entity %s was altered from `%s` to `%s`",
|
|
||||||
attributeMapping.getAttributeName(),
|
|
||||||
persister.getEntityName(),
|
|
||||||
previousValue,
|
|
||||||
currentValue
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// otherwise the natural id is mutable (!immutable), no need to do the checks
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean areEqual(Object one, Object other, SharedSessionContractImplementor session) {
|
public boolean areEqual(Object one, Object other, SharedSessionContractImplementor session) {
|
||||||
final Object[] one1 = (Object[]) one;
|
final Object[] oneArray = (Object[]) one;
|
||||||
final Object[] other1 = (Object[]) other;
|
final Object[] otherArray = (Object[]) other;
|
||||||
final List<SingularAttributeMapping> naturalIdAttributes = getNaturalIdAttributes();
|
final List<SingularAttributeMapping> naturalIdAttributes = getNaturalIdAttributes();
|
||||||
for ( int i = 0; i < naturalIdAttributes.size(); i++ ) {
|
for ( int i = 0; i < naturalIdAttributes.size(); i++ ) {
|
||||||
if ( !naturalIdAttributes.get( i ).areEqual( one1[i], other1[i], session ) ) {
|
if ( !naturalIdAttributes.get( i ).areEqual( oneArray[i], otherArray[i], session ) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -305,18 +284,14 @@ public boolean hasPartitionedSelectionMapping() {
|
|||||||
public <T> DomainResult<T> createDomainResult(NavigablePath navigablePath, TableGroup tableGroup, String resultVariable, DomainResultCreationState creationState) {
|
public <T> DomainResult<T> createDomainResult(NavigablePath navigablePath, TableGroup tableGroup, String resultVariable, DomainResultCreationState creationState) {
|
||||||
assert navigablePath.getLocalName().equals( NaturalIdMapping.PART_NAME );
|
assert navigablePath.getLocalName().equals( NaturalIdMapping.PART_NAME );
|
||||||
|
|
||||||
final SessionFactoryImplementor sessionFactory = creationState.getSqlAstCreationState().getCreationContext().getSessionFactory();
|
final JavaType<Object[]> jtd =
|
||||||
|
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
|
||||||
final JavaType<Object[]> jtd = sessionFactory
|
.getTypeConfiguration().getJavaTypeRegistry()
|
||||||
.getTypeConfiguration()
|
.getDescriptor( Object[].class );
|
||||||
.getJavaTypeRegistry()
|
|
||||||
.getDescriptor( Object[].class );
|
|
||||||
|
|
||||||
// register the table group under `...{natural-id}` as well
|
// register the table group under `...{natural-id}` as well
|
||||||
creationState.getSqlAstCreationState().getFromClauseAccess().resolveTableGroup(
|
creationState.getSqlAstCreationState().getFromClauseAccess()
|
||||||
navigablePath,
|
.resolveTableGroup( navigablePath, np -> tableGroup );
|
||||||
(np) -> tableGroup
|
|
||||||
);
|
|
||||||
|
|
||||||
return (DomainResult<T>) new DomainResultImpl(
|
return (DomainResult<T>) new DomainResultImpl(
|
||||||
navigablePath,
|
navigablePath,
|
||||||
@ -352,15 +327,14 @@ public <X, Y> int breakDownJdbcValues(
|
|||||||
int span = 0;
|
int span = 0;
|
||||||
if ( domainValue == null ) {
|
if ( domainValue == null ) {
|
||||||
for ( int i = 0; i < attributes.size(); i++ ) {
|
for ( int i = 0; i < attributes.size(); i++ ) {
|
||||||
span += attributes.get( i ).breakDownJdbcValues( null, offset + span, x, y, valueConsumer, session );
|
span += attributes.get( i )
|
||||||
|
.breakDownJdbcValues( null, offset + span, x, y, valueConsumer, session );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert domainValue instanceof Object[];
|
assert domainValue instanceof Object[];
|
||||||
|
|
||||||
final Object[] values = (Object[]) domainValue;
|
final Object[] values = (Object[]) domainValue;
|
||||||
assert values.length == attributes.size();
|
assert values.length == attributes.size();
|
||||||
|
|
||||||
for ( int i = 0; i < attributes.size(); i++ ) {
|
for ( int i = 0; i < attributes.size(); i++ ) {
|
||||||
span += attributes.get( i ).breakDownJdbcValues(
|
span += attributes.get( i ).breakDownJdbcValues(
|
||||||
values[i],
|
values[i],
|
||||||
@ -412,19 +386,16 @@ public Object disassemble(Object value, SharedSessionContractImplementor session
|
|||||||
if ( value == null ) {
|
if ( value == null ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
assert value instanceof Object[];
|
else {
|
||||||
|
assert value instanceof Object[];
|
||||||
final Object[] incoming = (Object[]) value;
|
final Object[] incoming = (Object[]) value;
|
||||||
assert incoming.length == attributes.size();
|
assert incoming.length == attributes.size();
|
||||||
|
final Object[] outgoing = new Object[incoming.length];
|
||||||
final Object[] outgoing = new Object[ incoming.length ];
|
for ( int i = 0; i < attributes.size(); i++ ) {
|
||||||
|
outgoing[i] = attributes.get( i ).disassemble( incoming[i], session );
|
||||||
for ( int i = 0; i < attributes.size(); i++ ) {
|
}
|
||||||
final SingularAttributeMapping attribute = attributes.get( i );
|
return outgoing;
|
||||||
outgoing[ i ] = attribute.disassemble( incoming[ i ], session );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return outgoing;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -436,10 +407,8 @@ public void addToCacheKey(MutableCacheKeyBuilder cacheKey, Object value, SharedS
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert value instanceof Object[];
|
assert value instanceof Object[];
|
||||||
|
|
||||||
final Object[] values = (Object[]) value;
|
final Object[] values = (Object[]) value;
|
||||||
assert values.length == attributes.size();
|
assert values.length == attributes.size();
|
||||||
|
|
||||||
for ( int i = 0; i < attributes.size(); i++ ) {
|
for ( int i = 0; i < attributes.size(); i++ ) {
|
||||||
attributes.get( i ).addToCacheKey( cacheKey, values[i], session );
|
attributes.get( i ).addToCacheKey( cacheKey, values[i], session );
|
||||||
}
|
}
|
||||||
@ -505,10 +474,8 @@ public <X, Y> int forEachJdbcValue(
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert value instanceof Object[];
|
assert value instanceof Object[];
|
||||||
|
|
||||||
final Object[] incoming = (Object[]) value;
|
final Object[] incoming = (Object[]) value;
|
||||||
assert incoming.length == attributes.size();
|
assert incoming.length == attributes.size();
|
||||||
|
|
||||||
for ( int i = 0; i < attributes.size(); i++ ) {
|
for ( int i = 0; i < attributes.size(); i++ ) {
|
||||||
final SingularAttributeMapping attribute = attributes.get( i );
|
final SingularAttributeMapping attribute = attributes.get( i );
|
||||||
span += attribute.forEachJdbcValue( incoming[i], span + offset, x, y, valuesConsumer, session );
|
span += attribute.forEachJdbcValue( incoming[i], span + offset, x, y, valuesConsumer, session );
|
||||||
@ -575,7 +542,6 @@ public DomainResultImpl(
|
|||||||
this.naturalIdMapping = naturalIdMapping;
|
this.naturalIdMapping = naturalIdMapping;
|
||||||
this.arrayJtd = arrayJtd;
|
this.arrayJtd = arrayJtd;
|
||||||
this.resultVariable = resultVariable;
|
this.resultVariable = resultVariable;
|
||||||
|
|
||||||
this.fetches = creationState.visitFetches( this );
|
this.fetches = creationState.visitFetches( this );
|
||||||
this.hasJoinFetches = this.fetches.hasJoinFetches();
|
this.hasJoinFetches = this.fetches.hasJoinFetches();
|
||||||
this.containsCollectionFetches = this.fetches.containsCollectionFetches();
|
this.containsCollectionFetches = this.fetches.containsCollectionFetches();
|
||||||
@ -593,13 +559,7 @@ public String getResultVariable() {
|
|||||||
public DomainResultAssembler<Object[]> createResultAssembler(
|
public DomainResultAssembler<Object[]> createResultAssembler(
|
||||||
InitializerParent<?> parent,
|
InitializerParent<?> parent,
|
||||||
AssemblerCreationState creationState) {
|
AssemblerCreationState creationState) {
|
||||||
return new AssemblerImpl(
|
return new AssemblerImpl( fetches, arrayJtd, creationState );
|
||||||
fetches,
|
|
||||||
navigablePath,
|
|
||||||
naturalIdMapping,
|
|
||||||
arrayJtd,
|
|
||||||
creationState
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -655,15 +615,9 @@ public boolean containsCollectionFetches() {
|
|||||||
|
|
||||||
private static class AssemblerImpl implements DomainResultAssembler<Object[]> {
|
private static class AssemblerImpl implements DomainResultAssembler<Object[]> {
|
||||||
private final JavaType<Object[]> jtd;
|
private final JavaType<Object[]> jtd;
|
||||||
|
|
||||||
private final DomainResultAssembler<?>[] subAssemblers;
|
private final DomainResultAssembler<?>[] subAssemblers;
|
||||||
|
|
||||||
private AssemblerImpl(
|
private AssemblerImpl(ImmutableFetchList fetches, JavaType<Object[]> jtd, AssemblerCreationState creationState) {
|
||||||
ImmutableFetchList fetches,
|
|
||||||
NavigablePath navigablePath,
|
|
||||||
CompoundNaturalIdMapping naturalIdMapping,
|
|
||||||
JavaType<Object[]> jtd,
|
|
||||||
AssemblerCreationState creationState) {
|
|
||||||
this.jtd = jtd;
|
this.jtd = jtd;
|
||||||
this.subAssemblers = new DomainResultAssembler[fetches.size()];
|
this.subAssemblers = new DomainResultAssembler[fetches.size()];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -672,14 +626,8 @@ private AssemblerImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private AssemblerImpl(JavaType<Object[]> jtd, DomainResultAssembler<?>[] subAssemblers) {
|
|
||||||
this.jtd = jtd;
|
|
||||||
this.subAssemblers = subAssemblers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object[] assemble(
|
public Object[] assemble(RowProcessingState rowProcessingState) {
|
||||||
RowProcessingState rowProcessingState) {
|
|
||||||
final Object[] result = new Object[ subAssemblers.length ];
|
final Object[] result = new Object[ subAssemblers.length ];
|
||||||
for ( int i = 0; i < subAssemblers.length; i++ ) {
|
for ( int i = 0; i < subAssemblers.length; i++ ) {
|
||||||
result[ i ] = subAssemblers[i].assemble( rowProcessingState );
|
result[ i ] = subAssemblers[i].assemble( rowProcessingState );
|
||||||
@ -710,7 +658,6 @@ public <X> void forEachResultAssembler(BiConsumer<Initializer<?>, X> consumer, X
|
|||||||
public JavaType<Object[]> getAssembledJavaType() {
|
public JavaType<Object[]> getAssembledJavaType() {
|
||||||
return jtd;
|
return jtd;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.cache.MutableCacheKeyBuilder;
|
import org.hibernate.cache.MutableCacheKeyBuilder;
|
||||||
import org.hibernate.engine.spi.PersistenceContext;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.internal.util.IndexedConsumer;
|
import org.hibernate.internal.util.IndexedConsumer;
|
||||||
@ -42,8 +42,8 @@
|
|||||||
/**
|
/**
|
||||||
* Single-attribute NaturalIdMapping implementation
|
* Single-attribute NaturalIdMapping implementation
|
||||||
*/
|
*/
|
||||||
public class SimpleNaturalIdMapping extends AbstractNaturalIdMapping implements JavaType.CoercionContext,
|
public class SimpleNaturalIdMapping extends AbstractNaturalIdMapping
|
||||||
BasicValuedMapping {
|
implements JavaType.CoercionContext, BasicValuedMapping {
|
||||||
private final SingularAttributeMapping attribute;
|
private final SingularAttributeMapping attribute;
|
||||||
private final SessionFactoryImplementor sessionFactory;
|
private final SessionFactoryImplementor sessionFactory;
|
||||||
private final TypeConfiguration typeConfiguration;
|
private final TypeConfiguration typeConfiguration;
|
||||||
@ -52,15 +52,10 @@ public SimpleNaturalIdMapping(
|
|||||||
SingularAttributeMapping attribute,
|
SingularAttributeMapping attribute,
|
||||||
EntityMappingType declaringType,
|
EntityMappingType declaringType,
|
||||||
MappingModelCreationProcess creationProcess) {
|
MappingModelCreationProcess creationProcess) {
|
||||||
super(
|
super( declaringType, attribute.getAttributeMetadata().isUpdatable() );
|
||||||
declaringType,
|
|
||||||
attribute.getAttributeMetadata().isUpdatable()
|
|
||||||
);
|
|
||||||
this.attribute = attribute;
|
this.attribute = attribute;
|
||||||
|
|
||||||
this.sessionFactory = creationProcess.getCreationContext().getSessionFactory();
|
this.sessionFactory = creationProcess.getCreationContext().getSessionFactory();
|
||||||
this.typeConfiguration = creationProcess.getCreationContext().getTypeConfiguration();
|
this.typeConfiguration = creationProcess.getCreationContext().getTypeConfiguration();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SingularAttributeMapping getAttribute() {
|
public SingularAttributeMapping getAttribute() {
|
||||||
@ -73,30 +68,24 @@ public void verifyFlushState(
|
|||||||
Object[] currentState,
|
Object[] currentState,
|
||||||
Object[] loadedState,
|
Object[] loadedState,
|
||||||
SharedSessionContractImplementor session) {
|
SharedSessionContractImplementor session) {
|
||||||
if ( isMutable() ) {
|
if ( !isMutable() ) {
|
||||||
// EARLY EXIT!!!
|
final EntityPersister persister = getDeclaringType().getEntityPersister();
|
||||||
// the natural id is mutable (!immutable), no need to do the checks
|
final Object naturalId = extractNaturalIdFromEntityState( currentState );
|
||||||
return;
|
final Object snapshot = loadedState == null
|
||||||
}
|
? session.getPersistenceContextInternal().getNaturalIdSnapshot( id, persister )
|
||||||
|
: persister.getNaturalIdMapping().extractNaturalIdFromEntityState( loadedState );
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
if ( !areEqual( naturalId, snapshot, session ) ) {
|
||||||
final EntityPersister persister = getDeclaringType().getEntityPersister();
|
throw new HibernateException(
|
||||||
|
String.format(
|
||||||
final Object naturalId = extractNaturalIdFromEntityState( currentState );
|
"An immutable natural identifier of entity %s was altered from `%s` to `%s`",
|
||||||
final Object snapshot = loadedState == null
|
persister.getEntityName(),
|
||||||
? persistenceContext.getNaturalIdSnapshot( id, persister )
|
snapshot,
|
||||||
: persister.getNaturalIdMapping().extractNaturalIdFromEntityState( loadedState );
|
naturalId
|
||||||
|
)
|
||||||
if ( !areEqual( naturalId, snapshot, session ) ) {
|
);
|
||||||
throw new HibernateException(
|
}
|
||||||
String.format(
|
|
||||||
"An immutable natural identifier of entity %s was altered from `%s` to `%s`",
|
|
||||||
persister.getEntityName(),
|
|
||||||
snapshot,
|
|
||||||
naturalId
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
// otherwise, the natural id is mutable (!immutable), no need to do the checks
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -104,12 +93,12 @@ public Object extractNaturalIdFromEntityState(Object[] state) {
|
|||||||
if ( state == null ) {
|
if ( state == null ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
else if ( state.length == 1 ) {
|
||||||
if ( state.length == 1 ) {
|
|
||||||
return state[0];
|
return state[0];
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
return state[attribute.getStateArrayPosition()];
|
return state[attribute.getStateArrayPosition()];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -119,65 +108,61 @@ public Object extractNaturalIdFromEntity(Object entity) {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void validateInternalForm(Object naturalIdValue) {
|
public void validateInternalForm(Object naturalIdValue) {
|
||||||
if ( naturalIdValue == null ) {
|
if ( naturalIdValue != null ) {
|
||||||
return;
|
final Class<?> naturalIdValueClass = naturalIdValue.getClass();
|
||||||
}
|
if ( naturalIdValueClass.isArray() && !naturalIdValueClass.getComponentType().isPrimitive() ) {
|
||||||
|
// be flexible
|
||||||
final Class<?> naturalIdValueClass = naturalIdValue.getClass();
|
final Object[] values = (Object[]) naturalIdValue;
|
||||||
if ( naturalIdValueClass.isArray() && !naturalIdValueClass.getComponentType().isPrimitive() ) {
|
if ( values.length == 1 ) {
|
||||||
// be flexible
|
naturalIdValue = values[0];
|
||||||
final Object[] values = (Object[]) naturalIdValue;
|
}
|
||||||
if ( values.length == 1 ) {
|
|
||||||
naturalIdValue = values[0];
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ( !getJavaType().getJavaTypeClass().isInstance( naturalIdValue ) ) {
|
if ( !getJavaType().getJavaTypeClass().isInstance( naturalIdValue ) ) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
String.format(
|
String.format(
|
||||||
Locale.ROOT,
|
Locale.ROOT,
|
||||||
"Incoming natural-id value [%s (`%s`)] is not of expected type [`%s`] and could not be coerced",
|
"Incoming natural-id value [%s (`%s`)] is not of expected type [`%s`] and could not be coerced",
|
||||||
naturalIdValue,
|
naturalIdValue,
|
||||||
naturalIdValueClass.getName(),
|
naturalIdValueClass.getName(),
|
||||||
getJavaType().getTypeName()
|
getJavaType().getTypeName()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int calculateHashCode(Object value) {
|
public int calculateHashCode(Object value) {
|
||||||
//noinspection unchecked
|
//noinspection rawtypes,unchecked
|
||||||
return value == null ? 0 : ( (JavaType<Object>) getJavaType() ).extractHashCode( value );
|
return value == null ? 0 : ( (JavaType) getJavaType() ).extractHashCode( value );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object normalizeInput(Object incoming) {
|
public Object normalizeInput(Object incoming) {
|
||||||
return normalizeIncomingValue( incoming );
|
final Object normalizedValue = normalizedValue( incoming );
|
||||||
|
return isLoadByIdComplianceEnabled()
|
||||||
|
? normalizedValue
|
||||||
|
: getJavaType().coerce( normalizedValue, this );
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
private Object normalizedValue(Object incoming) {
|
||||||
public Object normalizeIncomingValue(Object naturalIdToLoad) {
|
if ( incoming instanceof Map<?,?> valueMap ) {
|
||||||
final Object normalizedValue;
|
|
||||||
if ( naturalIdToLoad instanceof Map ) {
|
|
||||||
final Map valueMap = (Map) naturalIdToLoad;
|
|
||||||
assert valueMap.size() == 1;
|
assert valueMap.size() == 1;
|
||||||
assert valueMap.containsKey( getAttribute().getAttributeName() );
|
assert valueMap.containsKey( getAttribute().getAttributeName() );
|
||||||
normalizedValue = valueMap.get( getAttribute().getAttributeName() );
|
return valueMap.get( getAttribute().getAttributeName() );
|
||||||
}
|
}
|
||||||
else if ( naturalIdToLoad instanceof Object[] ) {
|
else if ( incoming instanceof Object[] values ) {
|
||||||
final Object[] values = (Object[]) naturalIdToLoad;
|
|
||||||
assert values.length == 1;
|
assert values.length == 1;
|
||||||
normalizedValue = values[0];
|
return values[0];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
normalizedValue = naturalIdToLoad;
|
return incoming;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( getTypeConfiguration().getJpaCompliance().isLoadByIdComplianceEnabled() ) {
|
private boolean isLoadByIdComplianceEnabled() {
|
||||||
return normalizedValue;
|
return getTypeConfiguration().getJpaCompliance().isLoadByIdComplianceEnabled();
|
||||||
}
|
|
||||||
return getJavaType().coerce( normalizedValue, this );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -301,11 +286,13 @@ public NaturalIdLoader<?> makeLoader(EntityMappingType entityDescriptor) {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MultiNaturalIdLoader<?> makeMultiLoader(EntityMappingType entityDescriptor) {
|
public MultiNaturalIdLoader<?> makeMultiLoader(EntityMappingType entityDescriptor) {
|
||||||
boolean supportsSqlArrayType = supportsSqlArrayType( sessionFactory.getFastSessionServices().jdbcServices.getDialect() );
|
return supportsSqlArrayType( getDialect() ) && attribute instanceof BasicAttributeMapping
|
||||||
if ( supportsSqlArrayType && attribute instanceof BasicAttributeMapping ) {
|
? new MultiNaturalIdLoaderArrayParam<>( entityDescriptor )
|
||||||
return new MultiNaturalIdLoaderArrayParam<>( entityDescriptor );
|
: new MultiNaturalIdLoaderInPredicate<>( entityDescriptor );
|
||||||
}
|
}
|
||||||
return new MultiNaturalIdLoaderInPredicate<>( entityDescriptor );
|
|
||||||
|
private Dialect getDialect() {
|
||||||
|
return sessionFactory.getFastSessionServices().jdbcServices.getDialect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user