Java Code Examples for org.hibernate.persister.entity.EntityPersister#hasNaturalIdentifier()

The following examples show how to use org.hibernate.persister.entity.EntityPersister#hasNaturalIdentifier() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: StatefulPersistenceContext.java    From lams with GNU General Public License v2.0 6 votes vote down vote up
@Override
public void cacheNaturalIdCrossReferenceFromLoad(
		EntityPersister persister,
		Serializable id,
		Object[] naturalIdValues) {
	if ( !persister.hasNaturalIdentifier() ) {
		// nothing to do
		return;
	}

	persister = locateProperPersister( persister );

	// 'justAddedLocally' is meant to handle the case where we would get double stats jounaling
	//	from a single load event.  The first put journal would come from the natural id resolution;
	// the second comes from the entity loading.  In this condition, we want to avoid the multiple
	// 'put' stats incrementing.
	final boolean justAddedLocally = naturalIdXrefDelegate.cacheNaturalIdCrossReference( persister, id, naturalIdValues );

	if ( justAddedLocally && persister.hasNaturalIdCache() ) {
		managedSharedCacheEntries( persister, id, naturalIdValues, null, CachedNaturalIdValueSource.LOAD );
	}
}
 
Example 2
Source File: StatefulPersistenceContext.java    From lams with GNU General Public License v2.0 6 votes vote down vote up
@Override
public void manageLocalNaturalIdCrossReference(
		EntityPersister persister,
		Serializable id,
		Object[] state,
		Object[] previousState,
		CachedNaturalIdValueSource source) {
	if ( !persister.hasNaturalIdentifier() ) {
		// nothing to do
		return;
	}

	persister = locateProperPersister( persister );
	final Object[] naturalIdValues = extractNaturalIdValues( state, persister );

	// cache
	naturalIdXrefDelegate.cacheNaturalIdCrossReference( persister, id, naturalIdValues );
}
 
Example 3
Source File: StatefulPersistenceContext.java    From lams with GNU General Public License v2.0 6 votes vote down vote up
@Override
public void manageSharedNaturalIdCrossReference(
		EntityPersister persister,
		final Serializable id,
		Object[] state,
		Object[] previousState,
		CachedNaturalIdValueSource source) {
	if ( !persister.hasNaturalIdentifier() ) {
		// nothing to do
		return;
	}

	if ( !persister.hasNaturalIdCache() ) {
		// nothing to do
		return;
	}

	persister = locateProperPersister( persister );
	final Object[] naturalIdValues = extractNaturalIdValues( state, persister );
	final Object[] previousNaturalIdValues = previousState == null ? null : extractNaturalIdValues( previousState, persister );

	managedSharedCacheEntries( persister, id, naturalIdValues, previousNaturalIdValues, source );
}
 
Example 4
Source File: StatefulPersistenceContext.java    From lams with GNU General Public License v2.0 6 votes vote down vote up
@Override
public Object[] removeLocalNaturalIdCrossReference(EntityPersister persister, Serializable id, Object[] state) {
	if ( !persister.hasNaturalIdentifier() ) {
		// nothing to do
		return null;
	}

	persister = locateProperPersister( persister );
	final Object[] naturalIdValues = getNaturalIdValues( state, persister );

	final Object[] localNaturalIdValues = naturalIdXrefDelegate.removeNaturalIdCrossReference( 
			persister, 
			id, 
			naturalIdValues 
	);

	return localNaturalIdValues != null ? localNaturalIdValues : naturalIdValues;
}
 
Example 5
Source File: DefaultFlushEntityEventListener.java    From cacheonix-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
private void checkNaturalId(
		EntityPersister persister,
        Serializable identifier,
        Object[] current,
        Object[] loaded,
        EntityMode entityMode,
        SessionImplementor session) {
	if ( persister.hasNaturalIdentifier() ) {
			Object[] snapshot = null;			
		Type[] types = persister.getPropertyTypes();
		int[] props = persister.getNaturalIdentifierProperties();
		boolean[] updateable = persister.getPropertyUpdateability();
		for ( int i=0; i<props.length; i++ ) {
			int prop = props[i];
			if ( !updateable[prop] ) {
					Object loadedVal;
					if ( loaded == null ) {
						if ( snapshot == null) {
							snapshot = session.getPersistenceContext().getNaturalIdSnapshot( identifier, persister );
						}
						loadedVal = snapshot[i];
					} else {
						loadedVal = loaded[prop];
					}
					if ( !types[prop].isEqual( current[prop], loadedVal, entityMode ) ) {						
					throw new HibernateException(
							"immutable natural identifier of an instance of " +
							persister.getEntityName() +
							" was altered"
						);
				}
			}
		}
	}
}
 
Example 6
Source File: StatefulPersistenceContext.java    From cacheonix-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
public Object[] getNaturalIdSnapshot(Serializable id, EntityPersister persister)
throws HibernateException {
	if ( !persister.hasNaturalIdentifier() ) {
		return null;
	}

	// if the natural-id is marked as non-mutable, it is not retrieved during a
	// normal database-snapshot operation...
	int[] props = persister.getNaturalIdentifierProperties();
	boolean[] updateable = persister.getPropertyUpdateability();
	boolean allNatualIdPropsAreUpdateable = true;
	for ( int i = 0; i < props.length; i++ ) {
		if ( !updateable[ props[i] ] ) {
			allNatualIdPropsAreUpdateable = false;
			break;
		}
	}

	if ( allNatualIdPropsAreUpdateable ) {
		// do this when all the properties are updateable since there is
		// a certain likelihood that the information will already be
		// snapshot-cached.
		Object[] entitySnapshot = getDatabaseSnapshot( id, persister );
		if ( entitySnapshot == NO_ROW ) {
			return null;
		}
		Object[] naturalIdSnapshot = new Object[ props.length ];
		for ( int i = 0; i < props.length; i++ ) {
			naturalIdSnapshot[i] = entitySnapshot[ props[i] ];
		}
		return naturalIdSnapshot;
	}
	else {
		return persister.getNaturalIdentifierSnapshot( id, session );
	}
}
 
Example 7
Source File: EntityUpdateAction.java    From lams with GNU General Public License v2.0 5 votes vote down vote up
private Object[] determinePreviousNaturalIdValues(
		EntityPersister persister,
		Object[] previousState,
		SharedSessionContractImplementor session,
		Serializable id) {
	if ( ! persister.hasNaturalIdentifier() ) {
		return null;
	}

	if ( previousState != null ) {
		return session.getPersistenceContext().getNaturalIdHelper().extractNaturalIdValues( previousState, persister );
	}

	return session.getPersistenceContext().getNaturalIdSnapshot( id, persister );
}
 
Example 8
Source File: StatefulPersistenceContext.java    From lams with GNU General Public License v2.0 5 votes vote down vote up
@Override
		public void removeSharedNaturalIdCrossReference(EntityPersister persister, Serializable id, Object[] naturalIdValues) {
			if ( !persister.hasNaturalIdentifier() ) {
				// nothing to do
				return;
			}

			if ( ! persister.hasNaturalIdCache() ) {
				// nothing to do
				return;
			}

			// todo : couple of things wrong here:
			//		1) should be using access strategy, not plain evict..
			//		2) should prefer session-cached values if any (requires interaction from removeLocalNaturalIdCrossReference

			persister = locateProperPersister( persister );
			final NaturalIdDataAccess naturalIdCacheAccessStrategy = persister.getNaturalIdCacheAccessStrategy();
			final Object naturalIdCacheKey = naturalIdCacheAccessStrategy.generateCacheKey( naturalIdValues, persister, session );
			naturalIdCacheAccessStrategy.evict( naturalIdCacheKey );

//			if ( sessionCachedNaturalIdValues != null
//					&& !Arrays.equals( sessionCachedNaturalIdValues, deletedNaturalIdValues ) ) {
//				final NaturalIdCacheKey sessionNaturalIdCacheKey = new NaturalIdCacheKey( sessionCachedNaturalIdValues, persister, session );
//				naturalIdCacheAccessStrategy.evict( sessionNaturalIdCacheKey );
//			}
		}
 
Example 9
Source File: StatefulPersistenceContext.java    From lams with GNU General Public License v2.0 5 votes vote down vote up
@Override
public void handleSynchronization(EntityPersister persister, Serializable pk, Object entity) {
	if ( !persister.hasNaturalIdentifier() ) {
		// nothing to do
		return;
	}

	persister = locateProperPersister( persister );

	final Object[] naturalIdValuesFromCurrentObjectState = extractNaturalIdValues( entity, persister );
	final boolean changed = ! naturalIdXrefDelegate.sameAsCached(
			persister,
			pk,
			naturalIdValuesFromCurrentObjectState
	);

	if ( changed ) {
		final Object[] cachedNaturalIdValues = naturalIdXrefDelegate.findCachedNaturalId( persister, pk );
		naturalIdXrefDelegate.cacheNaturalIdCrossReference( persister, pk, naturalIdValuesFromCurrentObjectState );
		naturalIdXrefDelegate.stashInvalidNaturalIdReference( persister, cachedNaturalIdValues );

		removeSharedNaturalIdCrossReference(
				persister,
				pk,
				cachedNaturalIdValues
		);
	}
}
 
Example 10
Source File: DefaultReactiveLoadEventListener.java    From hibernate-reactive with GNU Lesser General Public License v2.1 5 votes vote down vote up
private void cacheNaturalId(LoadEvent event, EntityPersister persister, EventSource session, Object entity) {
	if ( entity != null && persister.hasNaturalIdentifier() ) {
		final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
		final PersistenceContext.NaturalIdHelper naturalIdHelper = persistenceContext.getNaturalIdHelper();
		naturalIdHelper.cacheNaturalIdCrossReferenceFromLoad(
				persister,
				event.getEntityId(),
				naturalIdHelper.extractNaturalIdValues(
						entity,
						persister
				)
		);
	}
}
 
Example 11
Source File: SessionImpl.java    From lams with GNU General Public License v2.0 5 votes vote down vote up
private BaseNaturalIdLoadAccessImpl(EntityPersister entityPersister) {
	this.entityPersister = entityPersister;

	if ( !entityPersister.hasNaturalIdentifier() ) {
		throw new HibernateException(
				String.format( "Entity [%s] did not define a natural id", entityPersister.getEntityName() )
		);
	}
}
 
Example 12
Source File: BulkOperationCleanupAction.java    From lams with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Constructs an action to cleanup "affected cache regions" based on a
 * set of affected table spaces.  This differs from {@link #BulkOperationCleanupAction(SharedSessionContractImplementor, Queryable[])}
 * in that here we have the affected <strong>table names</strong>.  From those
 * we deduce the entity persisters which are affected based on the defined
 * {@link EntityPersister#getQuerySpaces() table spaces}; and from there, we
 * determine the affected collection regions based on any collections
 * in which those entity persisters participate as elements/keys/etc.
 *
 * @param session The session to which this request is tied.
 * @param tableSpaces The table spaces.
 */
@SuppressWarnings({ "unchecked" })
public BulkOperationCleanupAction(SharedSessionContractImplementor session, Set tableSpaces) {
	final LinkedHashSet<String> spacesList = new LinkedHashSet<>();
	spacesList.addAll( tableSpaces );

	final SessionFactoryImplementor factory = session.getFactory();
	for ( EntityPersister persister : factory.getMetamodel().entityPersisters().values() ) {
		final String[] entitySpaces = (String[]) persister.getQuerySpaces();
		if ( affectedEntity( tableSpaces, entitySpaces ) ) {
			spacesList.addAll( Arrays.asList( entitySpaces ) );

			if ( persister.canWriteToCache() ) {
				entityCleanups.add( new EntityCleanup( persister.getCacheAccessStrategy(), session ) );
			}
			if ( persister.hasNaturalIdentifier() && persister.hasNaturalIdCache() ) {
				naturalIdCleanups.add( new NaturalIdCleanup( persister.getNaturalIdCacheAccessStrategy(), session ) );
			}

			final Set<String> roles = session.getFactory().getMetamodel().getCollectionRolesByEntityParticipant( persister.getEntityName() );
			if ( roles != null ) {
				for ( String role : roles ) {
					final CollectionPersister collectionPersister = factory.getMetamodel().collectionPersister( role );
					if ( collectionPersister.hasCache() ) {
						collectionCleanups.add(
								new CollectionCleanup( collectionPersister.getCacheAccessStrategy(), session )
						);
					}
				}
			}
		}
	}

	this.affectedTableSpaces = spacesList.toArray( new String[ spacesList.size() ] );
}
 
Example 13
Source File: DefaultEvictEventListener.java    From lams with GNU General Public License v2.0 5 votes vote down vote up
protected void doEvict(
		final Object object,
		final EntityKey key,
		final EntityPersister persister,
		final EventSource session)
		throws HibernateException {

	if ( LOG.isTraceEnabled() ) {
		LOG.tracev( "Evicting {0}", MessageHelper.infoString( persister ) );
	}

	if ( persister.hasNaturalIdentifier() ) {
		session.getPersistenceContext().getNaturalIdHelper().handleEviction(
				object,
				persister,
				key.getIdentifier()
		);
	}

	// remove all collections for the entity from the session-level cache
	if ( persister.hasCollections() ) {
		new EvictVisitor( session, object ).process( object, persister );
	}

	// remove any snapshot, not really for memory management purposes, but
	// rather because it might now be stale, and there is no longer any
	// EntityEntry to take precedence
	// This is now handled by removeEntity()
	//session.getPersistenceContext().removeDatabaseSnapshot(key);
	
	session.getPersistenceContext().removeEntity( key );
	session.getPersistenceContext().removeEntry( object );

	Cascade.cascade( CascadingActions.EVICT, CascadePoint.AFTER_EVICT, session, persister, object );
}
 
Example 14
Source File: SessionImpl.java    From lams with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Checks to see if the CriteriaImpl is a naturalId lookup that can be done via
 * NaturalIdLoadAccess
 *
 * @param criteria The criteria to check as a complete natural identifier lookup.
 *
 * @return A fully configured NaturalIdLoadAccess or null, if null is returned the standard CriteriaImpl execution
 * should be performed
 */
private NaturalIdLoadAccess tryNaturalIdLoadAccess(CriteriaImpl criteria) {
	// See if the criteria lookup is by naturalId
	if ( !criteria.isLookupByNaturalKey() ) {
		return null;
	}

	final String entityName = criteria.getEntityOrClassName();
	final EntityPersister entityPersister = getFactory().getMetamodel().entityPersister( entityName );

	// Verify the entity actually has a natural id, needed for legacy support as NaturalIdentifier criteria
	// queries did no natural id validation
	if ( !entityPersister.hasNaturalIdentifier() ) {
		return null;
	}

	// Since isLookupByNaturalKey is true there can be only one CriterionEntry and getCriterion() will
	// return an instanceof NaturalIdentifier
	final CriterionEntry criterionEntry = criteria.iterateExpressionEntries().next();
	final NaturalIdentifier naturalIdentifier = (NaturalIdentifier) criterionEntry.getCriterion();

	final Map<String, Object> naturalIdValues = naturalIdentifier.getNaturalIdValues();
	final int[] naturalIdentifierProperties = entityPersister.getNaturalIdentifierProperties();

	// Verify the NaturalIdentifier criterion includes all naturalId properties, first check that the property counts match
	if ( naturalIdentifierProperties.length != naturalIdValues.size() ) {
		return null;
	}

	final String[] propertyNames = entityPersister.getPropertyNames();
	final NaturalIdLoadAccess naturalIdLoader = this.byNaturalId( entityName );

	// Build NaturalIdLoadAccess and in the process verify all naturalId properties were specified
	for ( int naturalIdentifierProperty : naturalIdentifierProperties ) {
		final String naturalIdProperty = propertyNames[naturalIdentifierProperty];
		final Object naturalIdValue = naturalIdValues.get( naturalIdProperty );

		if ( naturalIdValue == null ) {
			// A NaturalId property is missing from the critera query, can't use NaturalIdLoadAccess
			return null;
		}

		naturalIdLoader.using( naturalIdProperty, naturalIdValue );
	}

	// Criteria query contains a valid naturalId, use the new API
	log.warn(
			"Session.byNaturalId(" + entityName
					+ ") should be used for naturalId queries instead of Restrictions.naturalId() from a Criteria"
	);

	return naturalIdLoader;
}
 
Example 15
Source File: DefaultLoadEventListener.java    From lams with GNU General Public License v2.0 4 votes vote down vote up
/**
 * 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
 * @param persister The persister for the entity being requested for load
 * @param keyToLoad The EntityKey representing the entity to be loaded.
 * @param options The load options.
 *
 * @return The loaded entity, or null.
 */
private Object doLoad(
		final LoadEvent event,
		final EntityPersister persister,
		final EntityKey keyToLoad,
		final LoadEventListener.LoadType options) {

	if ( traceEnabled ) {
		LOG.tracev(
				"Attempting to resolve: {0}",
				MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() )
		);
	}

	Object entity = loadFromSessionCache( event, keyToLoad, options );
	if ( entity == REMOVED_ENTITY_MARKER ) {
		LOG.debug( "Load request found matching entity in context, but it is scheduled for removal; returning null" );
		return null;
	}
	if ( entity == INCONSISTENT_RTN_CLASS_MARKER ) {
		LOG.debug(
				"Load request found matching entity in context, but the matched entity was of an inconsistent return type; returning null"
		);
		return null;
	}
	if ( entity != null ) {
		if ( traceEnabled ) {
			LOG.tracev(
					"Resolved object in session cache: {0}",
					MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() )
			);
		}
		return entity;
	}

	entity = loadFromSecondLevelCache( event, persister, keyToLoad );
	if ( entity != null ) {
		if ( traceEnabled ) {
			LOG.tracev(
					"Resolved object in second-level cache: {0}",
					MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() )
			);
		}
	}
	else {
		if ( traceEnabled ) {
			LOG.tracev(
					"Object not resolved in any cache: {0}",
					MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() )
			);
		}
		entity = loadFromDatasource( event, persister );
	}

	if ( entity != null && persister.hasNaturalIdentifier() ) {
		event.getSession().getPersistenceContext().getNaturalIdHelper().cacheNaturalIdCrossReferenceFromLoad(
				persister,
				event.getEntityId(),
				event.getSession().getPersistenceContext().getNaturalIdHelper().extractNaturalIdValues(
						entity,
						persister
				)
		);
	}


	return entity;
}
 
Example 16
Source File: DefaultFlushEntityEventListener.java    From lams with GNU General Public License v2.0 4 votes vote down vote up
private void checkNaturalId(
		EntityPersister persister,
		EntityEntry entry,
		Object[] current,
		Object[] loaded,
		SessionImplementor session) {
	if ( persister.hasNaturalIdentifier() && entry.getStatus() != Status.READ_ONLY ) {
		if ( !persister.getEntityMetamodel().hasImmutableNaturalId() ) {
			// SHORT-CUT: if the natural id is mutable (!immutable), no need to do the below checks
			// EARLY EXIT!!!
			return;
		}

		final int[] naturalIdentifierPropertiesIndexes = persister.getNaturalIdentifierProperties();
		final Type[] propertyTypes = persister.getPropertyTypes();
		final boolean[] propertyUpdateability = persister.getPropertyUpdateability();

		final Object[] snapshot = loaded == null
				? session.getPersistenceContext().getNaturalIdSnapshot( entry.getId(), persister )
				: session.getPersistenceContext().getNaturalIdHelper().extractNaturalIdValues( loaded, persister );

		for ( int i = 0; i < naturalIdentifierPropertiesIndexes.length; i++ ) {
			final int naturalIdentifierPropertyIndex = naturalIdentifierPropertiesIndexes[i];
			if ( propertyUpdateability[naturalIdentifierPropertyIndex] ) {
				// if the given natural id property is updatable (mutable), there is nothing to check
				continue;
			}

			final Type propertyType = propertyTypes[naturalIdentifierPropertyIndex];
			if ( !propertyType.isEqual( current[naturalIdentifierPropertyIndex], snapshot[i] ) ) {
				throw new HibernateException(
						String.format(
								"An immutable natural identifier of entity %s was altered from %s to %s",
								persister.getEntityName(),
								propertyTypes[naturalIdentifierPropertyIndex].toLoggableString(
										snapshot[i],
										session.getFactory()
								),
								propertyTypes[naturalIdentifierPropertyIndex].toLoggableString(
										current[naturalIdentifierPropertyIndex],
										session.getFactory()
								)
						)
				);
			}
		}
	}
}
 
Example 17
Source File: ResolveNaturalIdEvent.java    From lams with GNU General Public License v2.0 4 votes vote down vote up
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] );
	}
}
 
Example 18
Source File: StatefulPersistenceContext.java    From lams with GNU General Public License v2.0 4 votes vote down vote up
@Override
public Object[] getNaturalIdSnapshot(Serializable id, EntityPersister persister) throws HibernateException {
	if ( !persister.hasNaturalIdentifier() ) {
		return null;
	}

	persister = locateProperPersister( persister );

	// let's first see if it is part of the natural id cache...
	final Object[] cachedValue = naturalIdHelper.findCachedNaturalId( persister, id );
	if ( cachedValue != null ) {
		return cachedValue;
	}

	// check to see if the natural id is mutable/immutable
	if ( persister.getEntityMetamodel().hasImmutableNaturalId() ) {
		// an immutable natural-id is not retrieved during a normal database-snapshot operation...
		final Object[] dbValue = persister.getNaturalIdentifierSnapshot( id, session );
		naturalIdHelper.cacheNaturalIdCrossReferenceFromLoad(
				persister,
				id,
				dbValue
		);
		return dbValue;
	}
	else {
		// for a mutable natural there is a likelihood that the the information will already be
		// snapshot-cached.
		final int[] props = persister.getNaturalIdentifierProperties();
		final Object[] entitySnapshot = getDatabaseSnapshot( id, persister );
		if ( entitySnapshot == NO_ROW || entitySnapshot == null ) {
			return null;
		}

		final Object[] naturalIdSnapshotSubSet = new Object[ props.length ];
		for ( int i = 0; i < props.length; i++ ) {
			naturalIdSnapshotSubSet[i] = entitySnapshot[ props[i] ];
		}
		naturalIdHelper.cacheNaturalIdCrossReferenceFromLoad(
				persister,
				id,
				naturalIdSnapshotSubSet
		);
		return naturalIdSnapshotSubSet;
	}
}
 
Example 19
Source File: DefaultReactiveFlushEntityEventListener.java    From hibernate-reactive with GNU Lesser General Public License v2.1 4 votes vote down vote up
private void checkNaturalId(
		EntityPersister persister,
		EntityEntry entry,
		Object[] current,
		Object[] loaded,
		SessionImplementor session) {
	if ( persister.hasNaturalIdentifier() && entry.getStatus() != Status.READ_ONLY ) {
		if ( !persister.getEntityMetamodel().hasImmutableNaturalId() ) {
			// SHORT-CUT: if the natural id is mutable (!immutable), no need to do the below checks
			// EARLY EXIT!!!
			return;
		}

		final int[] naturalIdentifierPropertiesIndexes = persister.getNaturalIdentifierProperties();
		final Type[] propertyTypes = persister.getPropertyTypes();
		final boolean[] propertyUpdateability = persister.getPropertyUpdateability();

		final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
		final Object[] snapshot = loaded == null
				? persistenceContext.getNaturalIdSnapshot( entry.getId(), persister )
				: persistenceContext.getNaturalIdHelper().extractNaturalIdValues( loaded, persister );

		for ( int i = 0; i < naturalIdentifierPropertiesIndexes.length; i++ ) {
			final int naturalIdentifierPropertyIndex = naturalIdentifierPropertiesIndexes[i];
			if ( propertyUpdateability[naturalIdentifierPropertyIndex] ) {
				// if the given natural id property is updatable (mutable), there is nothing to check
				continue;
			}

			final Type propertyType = propertyTypes[naturalIdentifierPropertyIndex];
			if ( !propertyType.isEqual( current[naturalIdentifierPropertyIndex], snapshot[i] ) ) {
				throw new HibernateException(
						String.format(
								"An immutable natural identifier of entity %s was altered from %s to %s",
								persister.getEntityName(),
								propertyTypes[naturalIdentifierPropertyIndex].toLoggableString(
										snapshot[i],
										session.getFactory()
								),
								propertyTypes[naturalIdentifierPropertyIndex].toLoggableString(
										current[naturalIdentifierPropertyIndex],
										session.getFactory()
								)
						)
				);
			}
		}
	}
}
 
Example 20
Source File: NaturalIdXrefDelegate.java    From lams with GNU General Public License v2.0 3 votes vote down vote up
/**
 * Invariant validate of the natural id.  Checks include<ul>
 *     <li>that the entity defines a natural id</li>
 *     <li>the number of natural id values matches the expected number</li>
 * </ul>
 *
 * @param persister The persister representing the entity type.
 * @param naturalIdValues The natural id values
 */
protected void validateNaturalId(EntityPersister persister, Object[] naturalIdValues) {
	if ( !persister.hasNaturalIdentifier() ) {
		throw new IllegalArgumentException( "Entity did not define a natrual-id" );
	}
	if ( persister.getNaturalIdentifierProperties().length != naturalIdValues.length ) {
		throw new IllegalArgumentException( "Mismatch between expected number of natural-id values and found." );
	}
}