Clean up various legacy "read path" contracts
* Type#nullSafeGet * Type#hydrate * Type#resolve * Type#getSemiResolvedType * Type#semiResolve * related
This commit is contained in:
parent
3d27f61221
commit
cf36d17fac
|
@ -6,40 +6,12 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.engine.internal;
|
package org.hibernate.engine.internal;
|
||||||
|
|
||||||
import org.hibernate.AssertionFailure;
|
|
||||||
import org.hibernate.CacheMode;
|
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
|
||||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
|
||||||
import org.hibernate.cache.spi.entry.CacheEntry;
|
|
||||||
import org.hibernate.engine.profile.Fetch;
|
|
||||||
import org.hibernate.engine.profile.FetchProfile;
|
|
||||||
import org.hibernate.engine.spi.EntityEntry;
|
|
||||||
import org.hibernate.engine.spi.EntityKey;
|
import org.hibernate.engine.spi.EntityKey;
|
||||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
|
||||||
import org.hibernate.engine.spi.PersistenceContext;
|
|
||||||
import org.hibernate.engine.spi.SessionEventListenerManager;
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.engine.spi.Status;
|
import org.hibernate.engine.spi.Status;
|
||||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
|
||||||
import org.hibernate.event.spi.PostLoadEvent;
|
|
||||||
import org.hibernate.event.spi.PostLoadEventListener;
|
|
||||||
import org.hibernate.event.spi.PreLoadEvent;
|
|
||||||
import org.hibernate.event.spi.PreLoadEventListener;
|
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.pretty.MessageHelper;
|
|
||||||
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
|
|
||||||
import org.hibernate.proxy.HibernateProxy;
|
|
||||||
import org.hibernate.stat.internal.StatsHelper;
|
|
||||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
|
||||||
import org.hibernate.type.EntityType;
|
import org.hibernate.type.EntityType;
|
||||||
import org.hibernate.type.Type;
|
|
||||||
import org.hibernate.type.TypeHelper;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functionality relating to the Hibernate two-phase loading process, that may be reused by persisters
|
* Functionality relating to the Hibernate two-phase loading process, that may be reused by persisters
|
||||||
|
@ -48,482 +20,11 @@ import org.jboss.logging.Logger;
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
public final class TwoPhaseLoad {
|
public final class TwoPhaseLoad {
|
||||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
|
||||||
CoreMessageLogger.class,
|
|
||||||
TwoPhaseLoad.class.getName()
|
|
||||||
);
|
|
||||||
|
|
||||||
private TwoPhaseLoad() {
|
private TwoPhaseLoad() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register the "hydrated" state of an entity instance, after the first step of 2-phase loading.
|
|
||||||
*
|
|
||||||
* Add the "hydrated state" (an array) of an uninitialized entity to the session. We don't try
|
|
||||||
* to resolve any associations yet, because there might be other entities waiting to be
|
|
||||||
* read from the JDBC result set we are currently processing
|
|
||||||
*
|
|
||||||
* @param persister The persister for the hydrated entity
|
|
||||||
* @param id The entity identifier
|
|
||||||
* @param values The entity values
|
|
||||||
* @param rowId The rowId for the entity
|
|
||||||
* @param object An optional instance for the entity being loaded
|
|
||||||
* @param lockMode The lock mode
|
|
||||||
* @param session The Session
|
|
||||||
*/
|
|
||||||
public static void postHydrate(
|
|
||||||
final EntityPersister persister,
|
|
||||||
final Object id,
|
|
||||||
final Object[] values,
|
|
||||||
final Object rowId,
|
|
||||||
final Object object,
|
|
||||||
final LockMode lockMode,
|
|
||||||
final SharedSessionContractImplementor session) {
|
|
||||||
final Object version = Versioning.getVersion( values, persister );
|
|
||||||
session.getPersistenceContextInternal().addEntry(
|
|
||||||
object,
|
|
||||||
Status.LOADING,
|
|
||||||
values,
|
|
||||||
rowId,
|
|
||||||
id,
|
|
||||||
version,
|
|
||||||
lockMode,
|
|
||||||
true,
|
|
||||||
persister,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( version != null && LOG.isTraceEnabled() ) {
|
|
||||||
final String versionStr = persister.isVersioned()
|
|
||||||
? persister.getVersionType().toLoggableString( version, session.getFactory() )
|
|
||||||
: "null";
|
|
||||||
LOG.tracef( "Version: %s", versionStr );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform the second step of 2-phase load. Fully initialize the entity
|
|
||||||
* instance.
|
|
||||||
* <p/>
|
|
||||||
* After processing a JDBC result set, we "resolve" all the associations
|
|
||||||
* between the entities which were instantiated and had their state
|
|
||||||
* "hydrated" into an array
|
|
||||||
*
|
|
||||||
* @param entity The entity being loaded
|
|
||||||
* @param readOnly Is the entity being loaded as read-only
|
|
||||||
* @param session The Session
|
|
||||||
* @param preLoadEvent The (re-used) pre-load event
|
|
||||||
*/
|
|
||||||
public static void initializeEntity(
|
|
||||||
final Object entity,
|
|
||||||
final boolean readOnly,
|
|
||||||
final SharedSessionContractImplementor session,
|
|
||||||
final PreLoadEvent preLoadEvent) {
|
|
||||||
initializeEntity( entity, readOnly, session, preLoadEvent, EntityResolver.DEFAULT );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform the second step of 2-phase load. Fully initialize the entity
|
|
||||||
* instance.
|
|
||||||
* <p/>
|
|
||||||
* After processing a JDBC result set, we "resolve" all the associations
|
|
||||||
* between the entities which were instantiated and had their state
|
|
||||||
* "hydrated" into an array
|
|
||||||
*
|
|
||||||
* @param entity The entity being loaded
|
|
||||||
* @param readOnly Is the entity being loaded as read-only
|
|
||||||
* @param session The Session
|
|
||||||
* @param preLoadEvent The (re-used) pre-load event
|
|
||||||
* @param entityResolver the resolver used for to-one entity associations
|
|
||||||
* (not used when an entity is a bytecode-enhanced lazy entity)
|
|
||||||
*/
|
|
||||||
public static void initializeEntity(
|
|
||||||
final Object entity,
|
|
||||||
final boolean readOnly,
|
|
||||||
final SharedSessionContractImplementor session,
|
|
||||||
final PreLoadEvent preLoadEvent,
|
|
||||||
final EntityResolver entityResolver) {
|
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
|
||||||
final EntityEntry entityEntry = persistenceContext.getEntry( entity );
|
|
||||||
if ( entityEntry == null ) {
|
|
||||||
throw new AssertionFailure( "possible non-threadsafe access to the session" );
|
|
||||||
}
|
|
||||||
initializeEntityEntryLoadedState( entity, entityEntry, session, entityResolver );
|
|
||||||
initializeEntityFromEntityEntryLoadedState( entity, entityEntry, readOnly, session, preLoadEvent );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void initializeEntityEntryLoadedState(
|
|
||||||
final Object entity,
|
|
||||||
final EntityEntry entityEntry,
|
|
||||||
final SharedSessionContractImplementor session,
|
|
||||||
final EntityResolver entityResolver) throws HibernateException {
|
|
||||||
final EntityPersister persister = entityEntry.getPersister();
|
|
||||||
final Object id = entityEntry.getId();
|
|
||||||
final Object[] hydratedState = entityEntry.getLoadedState();
|
|
||||||
|
|
||||||
final boolean debugEnabled = LOG.isDebugEnabled();
|
|
||||||
|
|
||||||
if ( debugEnabled ) {
|
|
||||||
LOG.debugf(
|
|
||||||
"Resolving attributes for %s",
|
|
||||||
MessageHelper.infoString( persister, id, session.getFactory() )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
String entityName = persister.getEntityName();
|
|
||||||
String[] propertyNames = persister.getPropertyNames();
|
|
||||||
final Type[] types = persister.getPropertyTypes();
|
|
||||||
for ( int i = 0; i < hydratedState.length; i++ ) {
|
|
||||||
final Object value = hydratedState[i];
|
|
||||||
if ( debugEnabled ) {
|
|
||||||
LOG.debugf(
|
|
||||||
"Processing attribute `%s` : value = %s",
|
|
||||||
propertyNames[i],
|
|
||||||
value == LazyPropertyInitializer.UNFETCHED_PROPERTY ? "<un-fetched>" : value == PropertyAccessStrategyBackRefImpl.UNKNOWN ? "<unknown>" : value
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( value == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
|
|
||||||
if ( debugEnabled ) {
|
|
||||||
LOG.debugf( "Resolving <un-fetched> attribute : `%s`", propertyNames[i] );
|
|
||||||
}
|
|
||||||
|
|
||||||
// IMPLEMENTATION NOTE: This is a lazy property on a bytecode-enhanced entity.
|
|
||||||
// hydratedState[i] needs to remain LazyPropertyInitializer.UNFETCHED_PROPERTY so that
|
|
||||||
// setPropertyValues() below (ultimately AbstractEntityTuplizer#setPropertyValues) works properly
|
|
||||||
// No resolution is necessary, unless the lazy property is a collection.
|
|
||||||
if ( types[i].isCollectionType() ) {
|
|
||||||
// IMPLEMENTATION NOTE: this is a lazy collection property on a bytecode-enhanced entity.
|
|
||||||
// HHH-10989: We need to resolve the collection so that a CollectionReference is added to StatefulPersistentContext.
|
|
||||||
// As mentioned above, hydratedState[i] needs to remain LazyPropertyInitializer.UNFETCHED_PROPERTY
|
|
||||||
// so do not assign the resolved, uninitialized PersistentCollection back to hydratedState[i].
|
|
||||||
Boolean overridingEager = getOverridingEager( session, entityName, propertyNames[i], types[i], debugEnabled );
|
|
||||||
types[i].resolve( value, session, entity, overridingEager );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( value != PropertyAccessStrategyBackRefImpl.UNKNOWN ) {
|
|
||||||
if ( debugEnabled ) {
|
|
||||||
final boolean isLazyEnhanced = persister.getBytecodeEnhancementMetadata()
|
|
||||||
.getLazyAttributesMetadata()
|
|
||||||
.getLazyAttributeNames()
|
|
||||||
.contains( propertyNames[i] );
|
|
||||||
LOG.debugf( "Attribute (`%s`) - enhanced for lazy-loading? - %s", propertyNames[i], isLazyEnhanced );
|
|
||||||
}
|
|
||||||
|
|
||||||
// we know value != LazyPropertyInitializer.UNFETCHED_PROPERTY
|
|
||||||
Boolean overridingEager = getOverridingEager( session, entityName, propertyNames[i], types[i], debugEnabled );
|
|
||||||
hydratedState[i] = types[i].isEntityType()
|
|
||||||
? entityResolver.resolve( (EntityType) types[i], value, session, entity, overridingEager )
|
|
||||||
: types[i].resolve( value, session, entity, overridingEager );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ( debugEnabled ) {
|
|
||||||
LOG.debugf( "Skipping <unknown> attribute : `%s`", propertyNames[i] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void initializeEntityFromEntityEntryLoadedState(
|
|
||||||
final Object entity,
|
|
||||||
final EntityEntry entityEntry,
|
|
||||||
final boolean readOnly,
|
|
||||||
final SharedSessionContractImplementor session,
|
|
||||||
final PreLoadEvent preLoadEvent) throws HibernateException {
|
|
||||||
|
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
|
||||||
final EntityPersister persister = entityEntry.getPersister();
|
|
||||||
final Object id = entityEntry.getId();
|
|
||||||
final Object[] hydratedState = entityEntry.getLoadedState();
|
|
||||||
|
|
||||||
final boolean debugEnabled = LOG.isDebugEnabled();
|
|
||||||
|
|
||||||
//Must occur after resolving identifiers!
|
|
||||||
if ( session.isEventSource() ) {
|
|
||||||
preLoadEvent.setEntity( entity ).setState( hydratedState ).setId( id ).setPersister( persister );
|
|
||||||
session.getFactory().getFastSessionServices()
|
|
||||||
.eventListenerGroup_PRE_LOAD.fireEventOnEachListener( preLoadEvent, PreLoadEventListener::onPreLoad );
|
|
||||||
}
|
|
||||||
|
|
||||||
persister.setPropertyValues( entity, hydratedState );
|
|
||||||
|
|
||||||
final SessionFactoryImplementor factory = session.getFactory();
|
|
||||||
final StatisticsImplementor statistics = factory.getStatistics();
|
|
||||||
|
|
||||||
if ( persister.canWriteToCache() && session.getCacheMode().isPutEnabled() ) {
|
|
||||||
if ( debugEnabled ) {
|
|
||||||
LOG.debugf(
|
|
||||||
"Adding entity to second-level cache: %s",
|
|
||||||
MessageHelper.infoString( persister, id, session.getFactory() )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Object version = Versioning.getVersion( hydratedState, persister );
|
|
||||||
final CacheEntry entry = persister.buildCacheEntry( entity, hydratedState, version, session );
|
|
||||||
final EntityDataAccess cache = persister.getCacheAccessStrategy();
|
|
||||||
final Object cacheKey = cache.generateCacheKey( id, persister, factory, session.getTenantIdentifier() );
|
|
||||||
|
|
||||||
// explicit handling of caching for rows just inserted and then somehow forced to be read
|
|
||||||
// from the database *within the same transaction*. usually this is done by
|
|
||||||
// 1) Session#refresh, or
|
|
||||||
// 2) Session#clear + some form of load
|
|
||||||
//
|
|
||||||
// we need to be careful not to clobber the lock here in the cache so that it can be rolled back if need be
|
|
||||||
if ( session.getPersistenceContextInternal().wasInsertedDuringTransaction( persister, id ) ) {
|
|
||||||
cache.update(
|
|
||||||
session,
|
|
||||||
cacheKey,
|
|
||||||
persister.getCacheEntryStructure().structure( entry ),
|
|
||||||
version,
|
|
||||||
version
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
|
|
||||||
try {
|
|
||||||
eventListenerManager.cachePutStart();
|
|
||||||
final boolean put = cache.putFromLoad(
|
|
||||||
session,
|
|
||||||
cacheKey,
|
|
||||||
persister.getCacheEntryStructure().structure( entry ),
|
|
||||||
version,
|
|
||||||
useMinimalPuts( session, entityEntry )
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( put && statistics.isStatisticsEnabled() ) {
|
|
||||||
statistics.entityCachePut(
|
|
||||||
StatsHelper.INSTANCE.getRootEntityRole( persister ),
|
|
||||||
cache.getRegion().getName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
eventListenerManager.cachePutEnd();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( persister.hasNaturalIdentifier() ) {
|
|
||||||
persistenceContext.getNaturalIdResolutions().cacheResolutionFromLoad(
|
|
||||||
id,
|
|
||||||
persister.getNaturalIdMapping().extractNaturalIdFromEntityState( hydratedState, session ),
|
|
||||||
persister
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isReallyReadOnly = readOnly;
|
|
||||||
if ( !persister.isMutable() ) {
|
|
||||||
isReallyReadOnly = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final Object proxy = persistenceContext.getProxy( entityEntry.getEntityKey() );
|
|
||||||
if ( proxy != null ) {
|
|
||||||
// there is already a proxy for this impl
|
|
||||||
// only set the status to read-only if the proxy is read-only
|
|
||||||
isReallyReadOnly = ( (HibernateProxy) proxy ).getHibernateLazyInitializer().isReadOnly();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( isReallyReadOnly ) {
|
|
||||||
//no need to take a snapshot - this is a
|
|
||||||
//performance optimization, but not really
|
|
||||||
//important, except for entities with huge
|
|
||||||
//mutable property values
|
|
||||||
persistenceContext.setEntryStatus( entityEntry, Status.READ_ONLY );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//take a snapshot
|
|
||||||
TypeHelper.deepCopy(
|
|
||||||
hydratedState,
|
|
||||||
persister.getPropertyTypes(),
|
|
||||||
persister.getPropertyUpdateability(),
|
|
||||||
//after setting values to object
|
|
||||||
hydratedState,
|
|
||||||
session
|
|
||||||
);
|
|
||||||
persistenceContext.setEntryStatus( entityEntry, Status.MANAGED );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( debugEnabled ) {
|
|
||||||
LOG.debugf(
|
|
||||||
"Done materializing entity %s",
|
|
||||||
MessageHelper.infoString( persister, id, session.getFactory() )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( statistics.isStatisticsEnabled() ) {
|
|
||||||
statistics.loadEntity( persister.getEntityName() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform the afterInitialize() step. This needs to be done after the collections have been properly initialized
|
|
||||||
* thus a separate step.
|
|
||||||
*
|
|
||||||
* @param entity The entity being loaded
|
|
||||||
* @param session The Session
|
|
||||||
*/
|
|
||||||
public static void afterInitialize(
|
|
||||||
final Object entity,
|
|
||||||
final SharedSessionContractImplementor session) {
|
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
|
||||||
final EntityEntry entityEntry = persistenceContext.getEntry( entity );
|
|
||||||
|
|
||||||
entityEntry.getPersister().afterInitialize( entity, session );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if eager of the association is overridden (i.e. skipping metamodel strategy), including (order sensitive):
|
|
||||||
* <ol>
|
|
||||||
* <li>fetch graph</li>
|
|
||||||
* <li>fetch profile</li>
|
|
||||||
* </ol>
|
|
||||||
*
|
|
||||||
* @param session session
|
|
||||||
* @param entityName entity name
|
|
||||||
* @param associationName association name
|
|
||||||
* @param associationType association type
|
|
||||||
* @param isDebugEnabled if debug log level enabled
|
|
||||||
* @return null if there is no overriding, true if it is overridden to eager and false if it is overridden to lazy
|
|
||||||
*/
|
|
||||||
private static Boolean getOverridingEager(
|
|
||||||
final SharedSessionContractImplementor session,
|
|
||||||
final String entityName,
|
|
||||||
final String associationName,
|
|
||||||
final Type associationType,
|
|
||||||
final boolean isDebugEnabled) {
|
|
||||||
// Performance: check type.isCollectionType() first, as type.isAssociationType() is megamorphic
|
|
||||||
if ( associationType.isCollectionType() || associationType.isAssociationType() ) {
|
|
||||||
|
|
||||||
// we can return false invariably for if the entity has been covered by entity graph,
|
|
||||||
// its associated JOIN has been present in the SQL generated and hence it would be loaded anyway
|
|
||||||
if ( session.isEnforcingFetchGraph() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check 'fetch profile' next; skip 'metamodel' if 'fetch profile' takes effect
|
|
||||||
final Boolean overridingEager = isEagerFetchProfile( session, entityName, associationName );
|
|
||||||
|
|
||||||
if ( overridingEager != null ) {
|
|
||||||
//This method is very hot, and private so let's piggy back on the fact that the caller already knows the debugging state.
|
|
||||||
if ( isDebugEnabled ) {
|
|
||||||
LOG.debugf(
|
|
||||||
"Overriding eager fetching using active fetch profile. EntityName: %s, associationName: %s, eager fetching: %s",
|
|
||||||
entityName,
|
|
||||||
associationName,
|
|
||||||
overridingEager
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return overridingEager;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// let 'metamodel' decide eagerness
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Boolean isEagerFetchProfile(SharedSessionContractImplementor session, String entityName, String associationName) {
|
|
||||||
LoadQueryInfluencers loadQueryInfluencers = session.getLoadQueryInfluencers();
|
|
||||||
|
|
||||||
// Performance: avoid concatenating entityName + "." + associationName when there is no need,
|
|
||||||
// as otherwise this section becomes an hot allocation point.
|
|
||||||
if ( loadQueryInfluencers.hasEnabledFetchProfiles() ) {
|
|
||||||
final String role = entityName + '.' + associationName;
|
|
||||||
final SessionFactoryImplementor factory = session.getFactory();
|
|
||||||
for ( String fetchProfileName : loadQueryInfluencers.getEnabledFetchProfileNames() ) {
|
|
||||||
FetchProfile fp = factory.getFetchProfile( fetchProfileName );
|
|
||||||
Fetch fetch = fp.getFetchByRole( role );
|
|
||||||
if ( fetch != null && Fetch.Style.JOIN == fetch.getStyle() ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method will be removed.
|
|
||||||
* @deprecated Use {@link #postLoad(Object, SharedSessionContractImplementor, PostLoadEvent)}
|
|
||||||
* instead.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static void postLoad(
|
|
||||||
final Object entity,
|
|
||||||
final SharedSessionContractImplementor session,
|
|
||||||
final PostLoadEvent postLoadEvent,
|
|
||||||
final Iterable<PostLoadEventListener> postLoadEventListeners) {
|
|
||||||
postLoad( entity, session, postLoadEvent );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PostLoad cannot occur during initializeEntity, as that call occurs *before*
|
|
||||||
* the Set collections are added to the persistence context by Loader.
|
|
||||||
* Without the split, LazyInitializationExceptions can occur in the Entity's
|
|
||||||
* postLoad if it acts upon the collection.
|
|
||||||
*
|
|
||||||
* HHH-6043
|
|
||||||
*
|
|
||||||
* @param entity The entity
|
|
||||||
* @param session The Session
|
|
||||||
* @param postLoadEvent The (re-used) post-load event
|
|
||||||
*/
|
|
||||||
public static void postLoad(
|
|
||||||
final Object entity,
|
|
||||||
final SharedSessionContractImplementor session,
|
|
||||||
final PostLoadEvent postLoadEvent) {
|
|
||||||
if ( session.isEventSource() ) {
|
|
||||||
final EntityEntry entityEntry = session.getPersistenceContextInternal().getEntry( entity );
|
|
||||||
|
|
||||||
postLoadEvent.setEntity( entity ).setId( entityEntry.getId() ).setPersister( entityEntry.getPersister() );
|
|
||||||
|
|
||||||
session.getFactory().getFastSessionServices().firePostLoadEvent( postLoadEvent );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean useMinimalPuts(SharedSessionContractImplementor session, EntityEntry entityEntry) {
|
|
||||||
if ( session.getFactory().getSessionFactoryOptions().isMinimalPutsEnabled() ) {
|
|
||||||
return session.getCacheMode() != CacheMode.REFRESH;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final EntityPersister persister = entityEntry.getPersister();
|
|
||||||
return persister.hasLazyProperties()
|
|
||||||
&& persister.isLazyPropertiesCacheable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an uninitialized instance of an entity class, as a placeholder to ensure object
|
|
||||||
* identity. Must be called before <tt>postHydrate()</tt>.
|
|
||||||
*
|
|
||||||
* Create a "temporary" entry for a newly instantiated entity. The entity is uninitialized,
|
|
||||||
* but we need the mapping from id to instance in order to guarantee uniqueness.
|
|
||||||
*
|
|
||||||
* @param key The entity key
|
|
||||||
* @param object The entity instance
|
|
||||||
* @param persister The entity persister
|
|
||||||
* @param lockMode The lock mode
|
|
||||||
* @param session The Session
|
|
||||||
*/
|
|
||||||
public static void addUninitializedEntity(
|
|
||||||
final EntityKey key,
|
|
||||||
final Object object,
|
|
||||||
final EntityPersister persister,
|
|
||||||
final LockMode lockMode,
|
|
||||||
final SharedSessionContractImplementor session) {
|
|
||||||
session.getPersistenceContextInternal().addEntity(
|
|
||||||
object,
|
|
||||||
Status.LOADING,
|
|
||||||
null,
|
|
||||||
key,
|
|
||||||
null,
|
|
||||||
lockMode,
|
|
||||||
true,
|
|
||||||
persister,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Same as {@link #addUninitializedEntity}, but here for an entity from the second level cache
|
|
||||||
*
|
*
|
||||||
* @param key The entity key
|
* @param key The entity key
|
||||||
* @param object The entity instance
|
* @param object The entity instance
|
||||||
|
@ -551,23 +52,4 @@ public final class TwoPhaseLoad {
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementations determine how a to-one associations is resolved.
|
|
||||||
*
|
|
||||||
* @see #initializeEntity(Object, boolean, SharedSessionContractImplementor, PreLoadEvent, EntityResolver)
|
|
||||||
*/
|
|
||||||
public interface EntityResolver {
|
|
||||||
|
|
||||||
Object resolve(
|
|
||||||
EntityType entityType,
|
|
||||||
Object value,
|
|
||||||
SharedSessionContractImplementor session,
|
|
||||||
Object owner,
|
|
||||||
Boolean overridingEager
|
|
||||||
);
|
|
||||||
|
|
||||||
EntityResolver DEFAULT = (entityType, value, session, owner, overridingEager) ->
|
|
||||||
entityType.resolve( value, session, owner, overridingEager );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,14 +36,14 @@ public class EntityUniqueKey implements Serializable {
|
||||||
public EntityUniqueKey(
|
public EntityUniqueKey(
|
||||||
final String entityName,
|
final String entityName,
|
||||||
final String uniqueKeyName,
|
final String uniqueKeyName,
|
||||||
final Object semiResolvedKey,
|
final Object key,
|
||||||
final Type keyType,
|
final Type keyType,
|
||||||
final EntityMode entityMode,
|
final EntityMode entityMode,
|
||||||
final SessionFactoryImplementor factory) {
|
final SessionFactoryImplementor factory) {
|
||||||
this.uniqueKeyName = uniqueKeyName;
|
this.uniqueKeyName = uniqueKeyName;
|
||||||
this.entityName = entityName;
|
this.entityName = entityName;
|
||||||
this.key = semiResolvedKey;
|
this.key = key;
|
||||||
this.keyType = keyType.getSemiResolvedType( factory );
|
this.keyType = keyType;
|
||||||
this.entityMode = entityMode;
|
this.entityMode = entityMode;
|
||||||
this.hashCode = generateHashCode( factory );
|
this.hashCode = generateHashCode( factory );
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,8 @@ public class EvictVisitor extends AbstractVisitor {
|
||||||
collection = (PersistentCollection) value;
|
collection = (PersistentCollection) value;
|
||||||
}
|
}
|
||||||
else if ( value == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
|
else if ( value == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
|
||||||
collection = (PersistentCollection) type.resolve( value, session, this.owner );
|
final Object keyOfOwner = type.getKeyOfOwner( owner, session );
|
||||||
|
collection = (PersistentCollection) type.getCollection( keyOfOwner, session, owner, Boolean.FALSE );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return; //EARLY EXIT!
|
return; //EARLY EXIT!
|
||||||
|
|
|
@ -11,6 +11,7 @@ import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
||||||
import org.hibernate.collection.spi.PersistentCollection;
|
import org.hibernate.collection.spi.PersistentCollection;
|
||||||
import org.hibernate.engine.internal.Collections;
|
import org.hibernate.engine.internal.Collections;
|
||||||
import org.hibernate.event.spi.EventSource;
|
import org.hibernate.event.spi.EventSource;
|
||||||
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.type.CollectionType;
|
import org.hibernate.type.CollectionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,7 +42,8 @@ public class FlushVisitor extends AbstractVisitor {
|
||||||
coll = session.getPersistenceContextInternal().getCollectionHolder(collection);
|
coll = session.getPersistenceContextInternal().getCollectionHolder(collection);
|
||||||
}
|
}
|
||||||
else if ( collection == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
|
else if ( collection == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
|
||||||
coll = (PersistentCollection) type.resolve( collection, session, owner );
|
final Object keyOfOwner = type.getKeyOfOwner( owner, session );
|
||||||
|
coll = (PersistentCollection) type.getCollection( keyOfOwner, session, owner, Boolean.FALSE );
|
||||||
}
|
}
|
||||||
else if ( collection instanceof PersistentCollection ) {
|
else if ( collection instanceof PersistentCollection ) {
|
||||||
coll = (PersistentCollection) collection;
|
coll = (PersistentCollection) collection;
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.util.Properties;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.id.insert.AbstractSelectingDelegate;
|
import org.hibernate.id.insert.AbstractSelectingDelegate;
|
||||||
|
@ -92,13 +93,16 @@ public class SelectGenerator extends AbstractPostInsertGenerator implements Conf
|
||||||
Dialect dialect,
|
Dialect dialect,
|
||||||
String suppliedUniqueKeyPropertyName) {
|
String suppliedUniqueKeyPropertyName) {
|
||||||
super( persister );
|
super( persister );
|
||||||
this.persister = persister;
|
|
||||||
this.dialect = dialect;
|
|
||||||
this.uniqueKeyPropertyName = determineNameOfPropertyToUse( persister, suppliedUniqueKeyPropertyName );
|
|
||||||
|
|
||||||
idSelectString = persister.getSelectByUniqueKeyString( uniqueKeyPropertyName );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
uniqueKeyType = persister.getPropertyType( uniqueKeyPropertyName );
|
|
||||||
idType = persister.getIdentifierType();
|
// this.persister = persister;
|
||||||
|
// this.dialect = dialect;
|
||||||
|
// this.uniqueKeyPropertyName = determineNameOfPropertyToUse( persister, suppliedUniqueKeyPropertyName );
|
||||||
|
//
|
||||||
|
// idSelectString = persister.getSelectByUniqueKeyString( uniqueKeyPropertyName );
|
||||||
|
// uniqueKeyType = persister.getPropertyType( uniqueKeyPropertyName );
|
||||||
|
// idType = persister.getIdentifierType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert() {
|
public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert() {
|
||||||
|
@ -130,12 +134,14 @@ public class SelectGenerator extends AbstractPostInsertGenerator implements Conf
|
||||||
uniqueKeyPropertyName
|
uniqueKeyPropertyName
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return idType.nullSafeGet(
|
|
||||||
rs,
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
persister.getRootTableKeyColumnNames(),
|
// return idType.nullSafeGet(
|
||||||
session,
|
// rs,
|
||||||
entity
|
// persister.getRootTableKeyColumnNames(),
|
||||||
);
|
// session,
|
||||||
|
// entity
|
||||||
|
// );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -986,23 +986,6 @@ public abstract class AbstractCollectionPersister
|
||||||
return elementClass;
|
return elementClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object readElement(ResultSet rs, Object owner, String[] aliases, SharedSessionContractImplementor session)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
return getElementType().nullSafeGet( rs, aliases, session, owner );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object readIndex(ResultSet rs, String[] aliases, SharedSessionContractImplementor session)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
Object index = getIndexType().nullSafeGet( rs, aliases, session, null );
|
|
||||||
if ( index == null ) {
|
|
||||||
throw new HibernateException( "null index column for collection: " + navigableRole.getFullPath() );
|
|
||||||
}
|
|
||||||
index = decrementIndexByBase( index );
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object decrementIndexByBase(Object index) {
|
protected Object decrementIndexByBase(Object index) {
|
||||||
if ( baseIndex != 0 ) {
|
if ( baseIndex != 0 ) {
|
||||||
index = (Integer)index - baseIndex;
|
index = (Integer)index - baseIndex;
|
||||||
|
@ -1010,31 +993,6 @@ public abstract class AbstractCollectionPersister
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object readIdentifier(ResultSet rs, String alias, SharedSessionContractImplementor session)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
Object id = getIdentifierType().nullSafeGet( rs, alias, session, null );
|
|
||||||
if ( id == null ) {
|
|
||||||
throw new HibernateException( "null identifier column for collection: " + navigableRole.getFullPath() );
|
|
||||||
}
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object readKey(ResultSet rs, String[] aliases, SharedSessionContractImplementor session)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
// First hydrate the collection key to check if it is null.
|
|
||||||
// Don't bother resolving the collection key if the hydrated value is null.
|
|
||||||
|
|
||||||
// Implementation note: if collection key is a composite value, then resolving a null value will
|
|
||||||
// result in instantiating an empty composite if AvailableSettings#CREATE_EMPTY_COMPOSITES_ENABLED
|
|
||||||
// is true. By not resolving a null value for a composite key, we avoid the overhead of instantiating
|
|
||||||
// an empty composite, checking if it is equivalent to null (it should be), then ultimately throwing
|
|
||||||
// out the empty value.
|
|
||||||
final Object hydratedKey = getKeyType().hydrate( rs, aliases, session, null );
|
|
||||||
return hydratedKey == null ? null : getKeyType().resolve( hydratedKey, session, null );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the key to a JDBC <tt>PreparedStatement</tt>
|
* Write the key to a JDBC <tt>PreparedStatement</tt>
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -126,31 +126,6 @@ public interface CollectionPersister extends CollectionDefinition {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the key from a row of the JDBC <tt>ResultSet</tt>
|
|
||||||
*/
|
|
||||||
Object readKey(ResultSet rs, String[] keyAliases, SharedSessionContractImplementor session)
|
|
||||||
throws HibernateException, SQLException;
|
|
||||||
/**
|
|
||||||
* Read the element from a row of the JDBC <tt>ResultSet</tt>
|
|
||||||
*/
|
|
||||||
Object readElement(
|
|
||||||
ResultSet rs,
|
|
||||||
Object owner,
|
|
||||||
String[] columnAliases,
|
|
||||||
SharedSessionContractImplementor session) throws SQLException;
|
|
||||||
/**
|
|
||||||
* Read the index from a row of the JDBC <tt>ResultSet</tt>
|
|
||||||
*/
|
|
||||||
Object readIndex(ResultSet rs, String[] columnAliases, SharedSessionContractImplementor session) throws SQLException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the identifier from a row of the JDBC <tt>ResultSet</tt>
|
|
||||||
*/
|
|
||||||
Object readIdentifier(
|
|
||||||
ResultSet rs,
|
|
||||||
String columnAlias,
|
|
||||||
SharedSessionContractImplementor session) throws SQLException;
|
|
||||||
/**
|
/**
|
||||||
* Is this an array or primitive values?
|
* Is this an array or primitive values?
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -107,25 +107,6 @@ public class DiscriminatorType<T> extends AbstractType implements BasicType<T>,
|
||||||
return (T) get( discriminatorValue, options.getSession() );
|
return (T) get( discriminatorValue, options.getSession() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object nullSafeGet(
|
|
||||||
ResultSet rs,
|
|
||||||
String[] names,
|
|
||||||
SharedSessionContractImplementor session,
|
|
||||||
Object owner) throws HibernateException, SQLException {
|
|
||||||
return nullSafeGet( rs, names[0], session, owner );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object nullSafeGet(
|
|
||||||
ResultSet rs,
|
|
||||||
String name,
|
|
||||||
SharedSessionContractImplementor session,
|
|
||||||
Object owner) throws HibernateException, SQLException {
|
|
||||||
final Object discriminatorValue = underlyingType.nullSafeGet( rs, name, session, owner );
|
|
||||||
return get( discriminatorValue, session );
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object get(Object discriminatorValue, SharedSessionContractImplementor session) {
|
private Object get(Object discriminatorValue, SharedSessionContractImplementor session) {
|
||||||
final String entityName = persister.getSubclassForDiscriminatorValue( discriminatorValue );
|
final String entityName = persister.getSubclassForDiscriminatorValue( discriminatorValue );
|
||||||
if ( entityName == null ) {
|
if ( entityName == null ) {
|
||||||
|
|
|
@ -251,8 +251,7 @@ public abstract class AbstractStandardBasicType<T>
|
||||||
return isDirty( oldHydratedState, currentState );
|
return isDirty( oldHydratedState, currentState );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private final Object nullSafeGet(
|
||||||
public final Object nullSafeGet(
|
|
||||||
ResultSet rs,
|
ResultSet rs,
|
||||||
String[] names,
|
String[] names,
|
||||||
SharedSessionContractImplementor session,
|
SharedSessionContractImplementor session,
|
||||||
|
@ -260,8 +259,7 @@ public abstract class AbstractStandardBasicType<T>
|
||||||
return nullSafeGet( rs, names[0], session );
|
return nullSafeGet( rs, names[0], session );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private final Object nullSafeGet(ResultSet rs, String name, SharedSessionContractImplementor session, Object owner)
|
||||||
public final Object nullSafeGet(ResultSet rs, String name, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
return nullSafeGet( rs, name, session );
|
return nullSafeGet( rs, name, session );
|
||||||
}
|
}
|
||||||
|
@ -336,27 +334,6 @@ public abstract class AbstractStandardBasicType<T>
|
||||||
public final void beforeAssemble(Serializable cached, SharedSessionContractImplementor session) {
|
public final void beforeAssemble(Serializable cached, SharedSessionContractImplementor session) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Object hydrate(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
return nullSafeGet(rs, names, session, owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Object resolve(Object value, SharedSessionContractImplementor session, Object owner) throws HibernateException {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Object semiResolve(Object value, SharedSessionContractImplementor session, Object owner) throws HibernateException {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Type getSemiResolvedType(SessionFactoryImplementor factory) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({ "unchecked" })
|
@SuppressWarnings({ "unchecked" })
|
||||||
public final Object replace(Object original, Object target, SharedSessionContractImplementor session, Object owner, Map copyCache) {
|
public final Object replace(Object original, Object target, SharedSessionContractImplementor session, Object owner, Map copyCache) {
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
package org.hibernate.type;
|
package org.hibernate.type;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@ -79,30 +77,6 @@ public abstract class AbstractType implements Type {
|
||||||
return !isSame( old, current );
|
return !isSame( old, current );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object hydrate(
|
|
||||||
ResultSet rs,
|
|
||||||
String[] names,
|
|
||||||
SharedSessionContractImplementor session,
|
|
||||||
Object owner)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
// TODO: this is very suboptimal for some subclasses (namely components),
|
|
||||||
// since it does not take advantage of two-phase-load
|
|
||||||
return nullSafeGet(rs, names, session, owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object resolve(Object value, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object semiResolve(Object value, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAnyType() {
|
public boolean isAnyType() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -139,11 +113,6 @@ public abstract class AbstractType implements Type {
|
||||||
return getHashCode(x );
|
return getHashCode(x );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getSemiResolvedType(SessionFactoryImplementor factory) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object replace(
|
public Object replace(
|
||||||
Object original,
|
Object original,
|
||||||
|
|
|
@ -236,37 +236,6 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
return resolveAny(
|
|
||||||
(String) discriminatorType.nullSafeGet( rs, names[0], session, owner ),
|
|
||||||
identifierType.nullSafeGet( rs, names[1], session, owner ),
|
|
||||||
session
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object hydrate(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
final String entityName = (String) discriminatorType.nullSafeGet( rs, names[0], session, owner );
|
|
||||||
final Object id = identifierType.nullSafeGet( rs, names[1], session, owner );
|
|
||||||
return new ObjectTypeCacheEntry( entityName, id );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object resolve(Object value, SharedSessionContractImplementor session, Object owner) throws HibernateException {
|
|
||||||
final ObjectTypeCacheEntry holder = (ObjectTypeCacheEntry) value;
|
|
||||||
return resolveAny( holder.entityName, holder.id, session );
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object resolveAny(String entityName, Object id, SharedSessionContractImplementor session)
|
|
||||||
throws HibernateException {
|
|
||||||
return entityName==null || id==null
|
|
||||||
? null
|
|
||||||
: session.internalLoad( entityName, id, eager, false );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
|
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
|
||||||
throws HibernateException, SQLException {
|
throws HibernateException, SQLException {
|
||||||
|
@ -353,16 +322,10 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private Object nullSafeGet(ResultSet rs, String name, SharedSessionContractImplementor session, Object owner) {
|
||||||
public Object nullSafeGet(ResultSet rs, String name, SharedSessionContractImplementor session, Object owner) {
|
|
||||||
throw new UnsupportedOperationException( "object is a multicolumn type" );
|
throw new UnsupportedOperationException( "object is a multicolumn type" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object semiResolve(Object value, SharedSessionContractImplementor session, Object owner) {
|
|
||||||
throw new UnsupportedOperationException( "any mappings may not form part of a property-ref" );
|
|
||||||
}
|
|
||||||
|
|
||||||
// CompositeType implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// CompositeType implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.type;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -23,6 +22,7 @@ import java.util.TreeMap;
|
||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
||||||
import org.hibernate.collection.internal.AbstractPersistentCollection;
|
import org.hibernate.collection.internal.AbstractPersistentCollection;
|
||||||
import org.hibernate.collection.spi.PersistentCollection;
|
import org.hibernate.collection.spi.PersistentCollection;
|
||||||
|
@ -140,17 +140,6 @@ public abstract class CollectionType extends AbstractType implements Association
|
||||||
*/
|
*/
|
||||||
public abstract PersistentCollection instantiate(SharedSessionContractImplementor session, CollectionPersister persister, Object key);
|
public abstract PersistentCollection instantiate(SharedSessionContractImplementor session, CollectionPersister persister, Object key);
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object nullSafeGet(ResultSet rs, String name, SharedSessionContractImplementor session, Object owner) throws SQLException {
|
|
||||||
return nullSafeGet( rs, new String[] { name }, session, owner );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object nullSafeGet(ResultSet rs, String[] name, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
return resolve( null, session, owner );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable,
|
public final void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable,
|
||||||
SharedSessionContractImplementor session) throws HibernateException, SQLException {
|
SharedSessionContractImplementor session) throws HibernateException, SQLException {
|
||||||
|
@ -431,11 +420,13 @@ public abstract class CollectionType extends AbstractType implements Association
|
||||||
Class returnedClass = keyType.getReturnedClass();
|
Class returnedClass = keyType.getReturnedClass();
|
||||||
|
|
||||||
if ( !returnedClass.isInstance( id ) ) {
|
if ( !returnedClass.isInstance( id ) ) {
|
||||||
id = keyType.semiResolve(
|
// todo (6.0) :
|
||||||
entityEntry.getLoadedValue( foreignKeyPropertyName ),
|
throw new NotYetImplementedFor6Exception( "Re-work support for semi-resolve" );
|
||||||
session,
|
// id = keyType.semiResolve(
|
||||||
owner
|
// entityEntry.getLoadedValue( foreignKeyPropertyName ),
|
||||||
);
|
// session,
|
||||||
|
// owner
|
||||||
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
|
@ -474,22 +465,7 @@ public abstract class CollectionType extends AbstractType implements Association
|
||||||
return ownerId;
|
return ownerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private Object resolve(Object value, SharedSessionContractImplementor session, Object owner, Boolean overridingEager) throws HibernateException {
|
||||||
public Object hydrate(ResultSet rs, String[] name, SharedSessionContractImplementor session, Object owner) {
|
|
||||||
// can't just return null here, since that would
|
|
||||||
// cause an owning component to become null
|
|
||||||
return NOT_NULL_COLLECTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object resolve(Object value, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException {
|
|
||||||
|
|
||||||
return resolve( value, session, owner, null );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object resolve(Object value, SharedSessionContractImplementor session, Object owner, Boolean overridingEager) throws HibernateException {
|
|
||||||
return resolveKey( getKeyOfOwner( owner, session ), session, owner, overridingEager );
|
return resolveKey( getKeyOfOwner( owner, session ), session, owner, overridingEager );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,13 +476,6 @@ public abstract class CollectionType extends AbstractType implements Association
|
||||||
getCollection( key, session, owner, overridingEager );
|
getCollection( key, session, owner, overridingEager );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object semiResolve(Object value, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException {
|
|
||||||
throw new UnsupportedOperationException(
|
|
||||||
"collection mappings may not form part of a property-ref" );
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isArrayType() {
|
public boolean isArrayType() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import java.io.Serializable;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.sql.CallableStatement;
|
import java.sql.CallableStatement;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -323,12 +322,6 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
return resolve( hydrate( rs, names, session, owner ), session, owner );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nullSafeSet(PreparedStatement st, Object value, int begin, SharedSessionContractImplementor session)
|
public void nullSafeSet(PreparedStatement st, Object value, int begin, SharedSessionContractImplementor session)
|
||||||
throws HibernateException, SQLException {
|
throws HibernateException, SQLException {
|
||||||
|
@ -384,13 +377,6 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object nullSafeGet(ResultSet rs, String name, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
|
|
||||||
return nullSafeGet( rs, new String[] {name}, session, owner );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getPropertyValue(Object component, int i, SharedSessionContractImplementor session)
|
public Object getPropertyValue(Object component, int i, SharedSessionContractImplementor session)
|
||||||
throws HibernateException {
|
throws HibernateException {
|
||||||
|
@ -652,64 +638,27 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
||||||
return joinedFetch[i];
|
return joinedFetch[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private Object resolve(Object value, SharedSessionContractImplementor session, Object owner)
|
||||||
public Object hydrate(
|
|
||||||
final ResultSet rs,
|
|
||||||
final String[] names,
|
|
||||||
final SharedSessionContractImplementor session,
|
|
||||||
final Object owner)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
|
|
||||||
int begin = 0;
|
|
||||||
boolean notNull = false;
|
|
||||||
Object[] values = new Object[propertySpan];
|
|
||||||
for ( int i = 0; i < propertySpan; i++ ) {
|
|
||||||
int length = propertyTypes[i].getColumnSpan( session.getFactory() );
|
|
||||||
String[] range = ArrayHelper.slice( names, begin, length ); //cache this
|
|
||||||
Object val = propertyTypes[i].hydrate( rs, range, session, owner );
|
|
||||||
if ( val == null ) {
|
|
||||||
if ( isKey ) {
|
|
||||||
return null; //different nullability rules for pk/fk
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
notNull = true;
|
|
||||||
}
|
|
||||||
values[i] = val;
|
|
||||||
begin += length;
|
|
||||||
}
|
|
||||||
|
|
||||||
return notNull ? values : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object resolve(Object value, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException {
|
throws HibernateException {
|
||||||
|
|
||||||
if ( value != null ) {
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
Object result = instantiate( owner, session );
|
|
||||||
Object[] values = (Object[]) value;
|
|
||||||
Object[] resolvedValues = new Object[values.length]; //only really need new array during semi-resolve!
|
|
||||||
for ( int i = 0; i < values.length; i++ ) {
|
|
||||||
resolvedValues[i] = propertyTypes[i].resolve( values[i], session, owner );
|
|
||||||
}
|
|
||||||
setPropertyValues( result, resolvedValues, entityMode );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else if ( isCreateEmptyCompositesEnabled() ) {
|
|
||||||
return instantiate( owner, session );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
// if ( value != null ) {
|
||||||
public Object semiResolve(Object value, SharedSessionContractImplementor session, Object owner)
|
// Object result = instantiate( owner, session );
|
||||||
throws HibernateException {
|
// Object[] values = (Object[]) value;
|
||||||
//note that this implementation is kinda broken
|
// Object[] resolvedValues = new Object[values.length]; //only really need new array during semi-resolve!
|
||||||
//for components with many-to-one associations
|
// for ( int i = 0; i < values.length; i++ ) {
|
||||||
return resolve( value, session, owner );
|
// resolvedValues[i] = propertyTypes[i].resolve( values[i], session, owner );
|
||||||
|
// }
|
||||||
|
// setPropertyValues( result, resolvedValues, entityMode );
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
// else if ( isCreateEmptyCompositesEnabled() ) {
|
||||||
|
// return instantiate( owner, session );
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -169,8 +169,7 @@ public class CustomType<J>
|
||||||
return getUserType().hashCode( x);
|
return getUserType().hashCode( x);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private Object nullSafeGet(
|
||||||
public Object nullSafeGet(
|
|
||||||
ResultSet rs,
|
ResultSet rs,
|
||||||
String[] names,
|
String[] names,
|
||||||
SharedSessionContractImplementor session,
|
SharedSessionContractImplementor session,
|
||||||
|
@ -178,8 +177,7 @@ public class CustomType<J>
|
||||||
throw new UnsupportedOperationException( "Reading from ResultSet by name is no longer supported" );
|
throw new UnsupportedOperationException( "Reading from ResultSet by name is no longer supported" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private Object nullSafeGet(
|
||||||
public Object nullSafeGet(
|
|
||||||
ResultSet rs,
|
ResultSet rs,
|
||||||
String columnName,
|
String columnName,
|
||||||
SharedSessionContractImplementor session,
|
SharedSessionContractImplementor session,
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
package org.hibernate.type;
|
package org.hibernate.type;
|
||||||
|
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -223,21 +222,6 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object nullSafeGet(ResultSet rs, String name, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
return nullSafeGet( rs, new String[] {name}, session, owner );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Object nullSafeGet(
|
|
||||||
ResultSet rs,
|
|
||||||
String[] names,
|
|
||||||
SharedSessionContractImplementor session,
|
|
||||||
Object owner) throws HibernateException, SQLException {
|
|
||||||
return resolve( hydrate( rs, names, session, owner ), session, owner );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable, SharedSessionContractImplementor session)
|
public void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable, SharedSessionContractImplementor session)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
|
@ -418,13 +402,11 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
||||||
/**
|
/**
|
||||||
* Resolve an identifier or unique key value
|
* Resolve an identifier or unique key value
|
||||||
*/
|
*/
|
||||||
@Override
|
private Object resolve(Object value, SharedSessionContractImplementor session, Object owner) throws HibernateException {
|
||||||
public Object resolve(Object value, SharedSessionContractImplementor session, Object owner) throws HibernateException {
|
|
||||||
return resolve(value, session, owner, null);
|
return resolve(value, session, owner, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private Object resolve(Object value, SharedSessionContractImplementor session, Object owner, Boolean overridingEager) throws HibernateException {
|
||||||
public Object resolve(Object value, SharedSessionContractImplementor session, Object owner, Boolean overridingEager) throws HibernateException {
|
|
||||||
if ( value != null && !isNull( owner, session ) ) {
|
if ( value != null && !isNull( owner, session ) ) {
|
||||||
if ( isReferenceToPrimaryKey() ) {
|
if ( isReferenceToPrimaryKey() ) {
|
||||||
return resolveIdentifier( value, session, overridingEager );
|
return resolveIdentifier( value, session, overridingEager );
|
||||||
|
@ -449,11 +431,6 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
||||||
return overridingEager != null ? overridingEager : this.eager;
|
return overridingEager != null ? overridingEager : this.eager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getSemiResolvedType(SessionFactoryImplementor factory) {
|
|
||||||
return getAssociatedEntityPersister( factory ).getIdentifierType();
|
|
||||||
}
|
|
||||||
|
|
||||||
public EntityPersister getAssociatedEntityPersister(final SessionFactoryImplementor factory) {
|
public EntityPersister getAssociatedEntityPersister(final SessionFactoryImplementor factory) {
|
||||||
final EntityPersister persister = associatedEntityPersister;
|
final EntityPersister persister = associatedEntityPersister;
|
||||||
//The following branch implements a simple lazy-initialization, but rather than the canonical
|
//The following branch implements a simple lazy-initialization, but rather than the canonical
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
package org.hibernate.type;
|
package org.hibernate.type;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
|
@ -18,7 +16,6 @@ import org.hibernate.engine.internal.ForeignKeys;
|
||||||
import org.hibernate.engine.jdbc.Size;
|
import org.hibernate.engine.jdbc.Size;
|
||||||
import org.hibernate.engine.spi.*;
|
import org.hibernate.engine.spi.*;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.Loadable;
|
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -127,38 +124,6 @@ public class ManyToOneType extends EntityType {
|
||||||
return ForeignKeyDirection.FROM_PARENT;
|
return ForeignKeyDirection.FROM_PARENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object hydrate(
|
|
||||||
ResultSet rs,
|
|
||||||
String[] names,
|
|
||||||
SharedSessionContractImplementor session,
|
|
||||||
Object owner) throws HibernateException, SQLException {
|
|
||||||
// return the (fully resolved) identifier value, but do not resolve
|
|
||||||
// to the actual referenced entity instance
|
|
||||||
// NOTE: the owner of the association is not really the owner of the id!
|
|
||||||
|
|
||||||
// First hydrate the ID to check if it is null.
|
|
||||||
// Don't bother resolving the ID if hydratedKeyState[i] is null.
|
|
||||||
|
|
||||||
// Implementation note: if id is a composite ID, then resolving a null value will
|
|
||||||
// result in instantiating an empty composite if AvailableSettings#CREATE_EMPTY_COMPOSITES_ENABLED
|
|
||||||
// is true. By not resolving a null value for a composite ID, we avoid the overhead of instantiating
|
|
||||||
// an empty composite, checking if it is equivalent to null (it should be), then ultimately throwing
|
|
||||||
// out the empty value.
|
|
||||||
final Object hydratedId = getIdentifierOrUniqueKeyType( session.getFactory() )
|
|
||||||
.hydrate( rs, names, session, null );
|
|
||||||
final Object id;
|
|
||||||
if ( hydratedId != null ) {
|
|
||||||
id = getIdentifierOrUniqueKeyType( session.getFactory() )
|
|
||||||
.resolve( hydratedId, session, null );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
id = null;
|
|
||||||
}
|
|
||||||
scheduleBatchLoadIfNeeded( id, session );
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register the entity as batch loadable, if enabled
|
* Register the entity as batch loadable, if enabled
|
||||||
*/
|
*/
|
||||||
|
@ -203,28 +168,6 @@ public class ManyToOneType extends EntityType {
|
||||||
.isDirty( getIdentifier( old, session ), getIdentifier( current, session ), session );
|
.isDirty( getIdentifier( old, session ), getIdentifier( current, session ), session );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object resolve(Object value, SharedSessionContractImplementor session, Object owner, Boolean overridingEager) throws HibernateException {
|
|
||||||
Object resolvedValue = super.resolve(value, session, owner, overridingEager);
|
|
||||||
if ( isLogicalOneToOne && value != null && getPropertyName() != null ) {
|
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
|
||||||
EntityEntry entry = persistenceContext.getEntry( owner );
|
|
||||||
if ( entry != null ) {
|
|
||||||
final Loadable ownerPersister = (Loadable) session.getFactory().getMetamodel().entityPersister( entry.getEntityName() );
|
|
||||||
EntityUniqueKey entityKey = new EntityUniqueKey(
|
|
||||||
ownerPersister.getEntityName(),
|
|
||||||
getPropertyName(),
|
|
||||||
value,
|
|
||||||
this,
|
|
||||||
ownerPersister.getEntityMode(),
|
|
||||||
session.getFactory()
|
|
||||||
);
|
|
||||||
persistenceContext.addEntity( entityKey, owner );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return resolvedValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Serializable disassemble(
|
public Serializable disassemble(
|
||||||
Object value,
|
Object value,
|
||||||
|
|
|
@ -75,26 +75,6 @@ public class MetaType extends AbstractType {
|
||||||
return String.class;
|
return String.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object nullSafeGet(
|
|
||||||
ResultSet rs,
|
|
||||||
String[] names,
|
|
||||||
SharedSessionContractImplementor session,
|
|
||||||
Object owner) throws HibernateException, SQLException {
|
|
||||||
Object key = baseType.nullSafeGet(rs, names, session, owner);
|
|
||||||
return key==null ? null : discriminatorValuesToEntityNameMap.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object nullSafeGet(
|
|
||||||
ResultSet rs,
|
|
||||||
String name,
|
|
||||||
SharedSessionContractImplementor session,
|
|
||||||
Object owner) throws HibernateException, SQLException {
|
|
||||||
Object key = baseType.nullSafeGet(rs, name, session, owner);
|
|
||||||
return key==null ? null : discriminatorValuesToEntityNameMap.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nullSafeSet(
|
public void nullSafeSet(
|
||||||
PreparedStatement st,
|
PreparedStatement st,
|
||||||
|
|
|
@ -8,8 +8,6 @@ package org.hibernate.type;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
|
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
@ -21,6 +19,7 @@ import org.hibernate.engine.spi.Mapping;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.persister.entity.UniqueKeyLoadable;
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -140,15 +139,6 @@ public class OneToOneType extends EntityType {
|
||||||
return foreignKeyType;
|
return foreignKeyType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object hydrate(
|
|
||||||
ResultSet rs,
|
|
||||||
String[] names,
|
|
||||||
SharedSessionContractImplementor session,
|
|
||||||
Object owner) throws HibernateException, SQLException {
|
|
||||||
return session.getContextEntityIdentifier(owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isNullable() {
|
public boolean isNullable() {
|
||||||
return !constrained;
|
return !constrained;
|
||||||
|
@ -182,7 +172,12 @@ public class OneToOneType extends EntityType {
|
||||||
|
|
||||||
if ( oid == null ) {
|
if ( oid == null ) {
|
||||||
if ( uniqueKeyPropertyName != null ) {
|
if ( uniqueKeyPropertyName != null ) {
|
||||||
return resolve( session.getContextEntityIdentifier( owner ), session, owner );
|
final EntityPersister associatedEntityPersister = getAssociatedEntityPersister( session.getFactory() );
|
||||||
|
return ( (UniqueKeyLoadable) associatedEntityPersister ).loadByUniqueKey(
|
||||||
|
uniqueKeyPropertyName,
|
||||||
|
session.getContextEntityIdentifier( owner ),
|
||||||
|
session
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
package org.hibernate.type;
|
package org.hibernate.type;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
|
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
@ -78,13 +76,6 @@ public class SpecialOneToOneType extends OneToOneType {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object hydrate(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
return super.getIdentifierOrUniqueKeyType( session.getFactory() )
|
|
||||||
.nullSafeGet(rs, names, session, owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: copy/paste from ManyToOneType
|
// TODO: copy/paste from ManyToOneType
|
||||||
@Override
|
@Override
|
||||||
public Serializable disassemble(Object value, SharedSessionContractImplementor session, Object owner)
|
public Serializable disassemble(Object value, SharedSessionContractImplementor session, Object owner)
|
||||||
|
|
|
@ -283,43 +283,6 @@ public interface Type extends Serializable {
|
||||||
SharedSessionContractImplementor session)
|
SharedSessionContractImplementor session)
|
||||||
throws HibernateException;
|
throws HibernateException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract a value of the {@link #getReturnedClass() mapped class} from the JDBC result set. Implementors
|
|
||||||
* should handle possibility of null values.
|
|
||||||
*
|
|
||||||
* @param rs The result set from which to extract value.
|
|
||||||
* @param names the column names making up this type value (use to read from result set)
|
|
||||||
* @param session The originating session
|
|
||||||
* @param owner the parent entity
|
|
||||||
*
|
|
||||||
* @return The extracted value
|
|
||||||
*
|
|
||||||
* @throws HibernateException An error from Hibernate
|
|
||||||
* @throws SQLException An error from the JDBC driver
|
|
||||||
*
|
|
||||||
* @see Type#hydrate(ResultSet, String[], SharedSessionContractImplementor, Object) alternative, 2-phase property initialization
|
|
||||||
*/
|
|
||||||
Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException, SQLException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract a value of the {@link #getReturnedClass() mapped class} from the JDBC result set. Implementors
|
|
||||||
* should handle possibility of null values. This form might be called if the type is known to be a
|
|
||||||
* single-column type.
|
|
||||||
*
|
|
||||||
* @param rs The result set from which to extract value.
|
|
||||||
* @param name the column name making up this type value (use to read from result set)
|
|
||||||
* @param session The originating session
|
|
||||||
* @param owner the parent entity
|
|
||||||
*
|
|
||||||
* @return The extracted value
|
|
||||||
*
|
|
||||||
* @throws HibernateException An error from Hibernate
|
|
||||||
* @throws SQLException An error from the JDBC driver
|
|
||||||
*/
|
|
||||||
Object nullSafeGet(ResultSet rs, String name, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException, SQLException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bind a value represented by an instance of the {@link #getReturnedClass() mapped class} to the JDBC prepared
|
* Bind a value represented by an instance of the {@link #getReturnedClass() mapped class} to the JDBC prepared
|
||||||
* statement, ignoring some columns as dictated by the 'settable' parameter. Implementors should handle the
|
* statement, ignoring some columns as dictated by the 'settable' parameter. Implementors should handle the
|
||||||
|
@ -437,82 +400,6 @@ public interface Type extends Serializable {
|
||||||
*/
|
*/
|
||||||
void beforeAssemble(Serializable cached, SharedSessionContractImplementor session);
|
void beforeAssemble(Serializable cached, SharedSessionContractImplementor session);
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract a value from the JDBC result set. This is useful for 2-phase property initialization - the second
|
|
||||||
* phase is a call to {@link #resolve}
|
|
||||||
* This hydrated value will be either:<ul>
|
|
||||||
* <li>in the case of an entity or collection type, the key</li>
|
|
||||||
* <li>otherwise, the value itself</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param rs The JDBC result set
|
|
||||||
* @param names the column names making up this type value (use to read from result set)
|
|
||||||
* @param session The originating session
|
|
||||||
* @param owner the parent entity
|
|
||||||
*
|
|
||||||
* @return An entity or collection key, or an actual value.
|
|
||||||
*
|
|
||||||
* @throws HibernateException An error from Hibernate
|
|
||||||
* @throws SQLException An error from the JDBC driver
|
|
||||||
*
|
|
||||||
* @see #resolve
|
|
||||||
*/
|
|
||||||
Object hydrate(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException, SQLException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see #resolve(Object, SharedSessionContractImplementor, Object, Boolean)
|
|
||||||
*/
|
|
||||||
Object resolve(Object value, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The second phase of 2-phase loading. Only really pertinent for entities and collections. Here we resolve the
|
|
||||||
* identifier to an entity or collection instance
|
|
||||||
*
|
|
||||||
* @param value an identifier or value returned by <tt>hydrate()</tt>
|
|
||||||
* @param owner the parent entity
|
|
||||||
* @param session the session
|
|
||||||
* @param overridingEager can override eager from the mapping. For example because of {@link org.hibernate.engine.spi.LoadQueryInfluencers}
|
|
||||||
* If null, then it does not override. If true or false then it overrides the mapping value.
|
|
||||||
*
|
|
||||||
* @return the given value, or the value associated with the identifier
|
|
||||||
*
|
|
||||||
* @throws HibernateException An error from Hibernate
|
|
||||||
*
|
|
||||||
* @see #hydrate
|
|
||||||
*/
|
|
||||||
default Object resolve(Object value, SharedSessionContractImplementor session, Object owner, Boolean overridingEager)
|
|
||||||
throws HibernateException {
|
|
||||||
return resolve(value, session, owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a hydrated, but unresolved value, return a value that may be used to reconstruct property-ref
|
|
||||||
* associations.
|
|
||||||
*
|
|
||||||
* @param value The unresolved, hydrated value
|
|
||||||
* @param session THe originating session
|
|
||||||
* @param owner The value owner
|
|
||||||
*
|
|
||||||
* @return The semi-resolved value
|
|
||||||
*
|
|
||||||
* @throws HibernateException An error from Hibernate
|
|
||||||
*/
|
|
||||||
Object semiResolve(Object value, SharedSessionContractImplementor session, Object owner)
|
|
||||||
throws HibernateException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* As part of 2-phase loading, when we perform resolving what is the resolved type for this type? Generally
|
|
||||||
* speaking the type and its semi-resolved type will be the same. The main deviation from this is in the
|
|
||||||
* case of an entity where the type would be the entity type and semi-resolved type would be its identifier type
|
|
||||||
*
|
|
||||||
* @param factory The session factory
|
|
||||||
*
|
|
||||||
* @return The semi-resolved type
|
|
||||||
*/
|
|
||||||
Type getSemiResolvedType(SessionFactoryImplementor factory);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* During merge, replace the existing (target) value in the entity we are merging to
|
* During merge, replace the existing (target) value in the entity we are merging to
|
||||||
* with a new (original) value from the detached entity we are merging. For immutable
|
* with a new (original) value from the detached entity we are merging. For immutable
|
||||||
|
|
|
@ -66,11 +66,14 @@ public class MergeEnhancedEntityTest extends BaseCoreFunctionalTestCase {
|
||||||
doInHibernate( this::sessionFactory, s -> {
|
doInHibernate( this::sessionFactory, s -> {
|
||||||
Person entity = s.find( Person.class, 1L );
|
Person entity = s.find( Person.class, 1L );
|
||||||
entity.name = "John";
|
entity.name = "John";
|
||||||
try {
|
|
||||||
s.refresh( entity );
|
s.refresh( entity );
|
||||||
} catch ( RuntimeException e ) {
|
|
||||||
fail( "Enhanced entity can't be refreshed: " + e.getMessage() );
|
// try {
|
||||||
}
|
// s.refresh( entity );
|
||||||
|
// } catch ( RuntimeException e ) {
|
||||||
|
// fail( "Enhanced entity can't be refreshed: " + e.getMessage() );
|
||||||
|
// }
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
package org.hibernate.orm.test.cfg.persister;
|
package org.hibernate.orm.test.cfg.persister;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -783,26 +781,6 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
|
||||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object readKey(ResultSet rs, String[] keyAliases, SharedSessionContractImplementor session)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object readElement(ResultSet rs, Object owner, String[] columnAliases, SharedSessionContractImplementor session)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object readIndex(ResultSet rs, String[] columnAliases, SharedSessionContractImplementor session)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object readIdentifier(ResultSet rs, String columnAlias, SharedSessionContractImplementor session)
|
|
||||||
throws HibernateException, SQLException {
|
|
||||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isPrimitiveArray() {
|
public boolean isPrimitiveArray() {
|
||||||
return false; //To change body of implemented methods use File | Settings | File Templates.
|
return false; //To change body of implemented methods use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
|
@ -339,41 +339,42 @@ public class CustomPersister implements EntityPersister {
|
||||||
Object id,
|
Object id,
|
||||||
Object optionalObject,
|
Object optionalObject,
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
SharedSessionContractImplementor session
|
SharedSessionContractImplementor session) {
|
||||||
) throws HibernateException {
|
|
||||||
|
|
||||||
// fails when optional object is supplied
|
throw new UnsupportedOperationException();
|
||||||
|
//
|
||||||
Custom clone = null;
|
// // fails when optional object is supplied
|
||||||
Custom obj = (Custom) INSTANCES.get(id);
|
//
|
||||||
if (obj!=null) {
|
// Custom clone = null;
|
||||||
clone = (Custom) obj.clone();
|
// Custom obj = (Custom) INSTANCES.get(id);
|
||||||
TwoPhaseLoad.addUninitializedEntity(
|
// if (obj!=null) {
|
||||||
session.generateEntityKey( id, this ),
|
// clone = (Custom) obj.clone();
|
||||||
clone,
|
// TwoPhaseLoad.addUninitializedEntity(
|
||||||
this,
|
// session.generateEntityKey( id, this ),
|
||||||
LockMode.NONE,
|
// clone,
|
||||||
session
|
// this,
|
||||||
);
|
// LockMode.NONE,
|
||||||
TwoPhaseLoad.postHydrate(
|
// session
|
||||||
this,
|
// );
|
||||||
id,
|
// TwoPhaseLoad.postHydrate(
|
||||||
new String[] { obj.getName() },
|
// this,
|
||||||
null,
|
// id,
|
||||||
clone,
|
// new String[] { obj.getName() },
|
||||||
LockMode.NONE,
|
// null,
|
||||||
session
|
// clone,
|
||||||
);
|
// LockMode.NONE,
|
||||||
TwoPhaseLoad.initializeEntity(
|
// session
|
||||||
clone,
|
// );
|
||||||
false,
|
// TwoPhaseLoad.initializeEntity(
|
||||||
session,
|
// clone,
|
||||||
new PreLoadEvent( (EventSource) session )
|
// false,
|
||||||
);
|
// session,
|
||||||
TwoPhaseLoad.afterInitialize( clone, session );
|
// new PreLoadEvent( (EventSource) session )
|
||||||
TwoPhaseLoad.postLoad( clone, session, new PostLoadEvent( (EventSource) session ) );
|
// );
|
||||||
}
|
// TwoPhaseLoad.afterInitialize( clone, session );
|
||||||
return clone;
|
// TwoPhaseLoad.postLoad( clone, session, new PostLoadEvent( (EventSource) session ) );
|
||||||
|
// }
|
||||||
|
// return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue