下面列出了org.hibernate.persister.entity.EntityPersister#getIdentifier ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public void update(String entityName, Object entity) {
errorIfClosed();
EntityPersister persister = getEntityPersister(entityName, entity);
Serializable id = persister.getIdentifier(entity, EntityMode.POJO);
Object[] state = persister.getPropertyValues(entity, EntityMode.POJO);
Object oldVersion;
if ( persister.isVersioned() ) {
oldVersion = persister.getVersion(entity, EntityMode.POJO);
Object newVersion = Versioning.increment( oldVersion, persister.getVersionType(), this );
Versioning.setVersion(state, newVersion, persister);
persister.setPropertyValues(entity, state, EntityMode.POJO);
}
else {
oldVersion = null;
}
persister.update(id, state, null, false, null, oldVersion, entity, null, this);
}
@Override
public void update(String entityName, Object entity) {
checkOpen();
EntityPersister persister = getEntityPersister( entityName, entity );
Serializable id = persister.getIdentifier( entity, this );
Object[] state = persister.getPropertyValues( entity );
Object oldVersion;
if ( persister.isVersioned() ) {
oldVersion = persister.getVersion( entity );
Object newVersion = Versioning.increment( oldVersion, persister.getVersionType(), this );
Versioning.setVersion( state, newVersion, persister );
persister.setPropertyValues( entity, state );
}
else {
oldVersion = null;
}
persister.update( id, state, null, false, null, oldVersion, entity, null, this );
}
/**
* Determine the id to use for updating.
*
* @param entity The entity.
* @param persister The entity persister
* @param requestedId The requested identifier
* @param session The session
*
* @return The id.
*
* @throws TransientObjectException If the entity is considered transient.
*/
protected Serializable getUpdateId(
Object entity,
EntityPersister persister,
Serializable requestedId,
SessionImplementor session) {
// use the id assigned to the instance
Serializable id = persister.getIdentifier( entity, session );
if ( id == null ) {
// assume this is a newly instantiated transient object
// which should be saved rather than updated
throw new TransientObjectException(
"The given object has a null identifier: " +
persister.getEntityName()
);
}
else {
return id;
}
}
/**
* Is this instance, which we know is not persistent, actually transient?
* <p/>
* If <tt>assumed</tt> is non-null, don't hit the database to make the determination, instead assume that
* value; the client code must be prepared to "recover" in the case that this assumed result is incorrect.
*
* @param entityName The name of the entity
* @param entity The entity instance
* @param assumed The assumed return value, if avoiding database hit is desired
* @param session The session
*
* @return {@code true} if the given entity is transient (unsaved)
*/
public static CompletionStage<Boolean> isTransient(String entityName, Object entity, Boolean assumed,
SessionImplementor session) {
if ( entity == LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
// an unfetched association can only point to
// an entity that already exists in the db
return CompletionStages.falseFuture();
}
// let the interceptor inspect the instance to decide
Boolean isUnsaved = session.getInterceptor().isTransient( entity );
if ( isUnsaved != null ) {
return CompletionStages.completedFuture( isUnsaved );
}
// let the persister inspect the instance to decide
final EntityPersister persister = session.getEntityPersister( entityName, entity );
isUnsaved = persister.isTransient( entity, session );
if ( isUnsaved != null ) {
return CompletionStages.completedFuture( isUnsaved );
}
// we use the assumed value, if there is one, to avoid hitting
// the database
if ( assumed != null ) {
return CompletionStages.completedFuture( assumed );
}
// hit the database, after checking the session cache for a snapshot
ReactivePersistenceContextAdapter persistenceContext =
(ReactivePersistenceContextAdapter) session.getPersistenceContextInternal();
Serializable id = persister.getIdentifier(entity, session);
return persistenceContext.reactiveGetDatabaseSnapshot( id, persister).thenApply(Objects::isNull);
}
private void disallowDeletionOfDetached(DeleteEvent event) {
EventSource source = event.getSession();
String entityName = event.getEntityName();
EntityPersister persister = source.getEntityPersister( entityName, event.getObject() );
Serializable id = persister.getIdentifier( event.getObject(), source );
entityName = entityName == null ? source.guessEntityName( event.getObject() ) : entityName;
throw new IllegalArgumentException( "Removing a detached instance " + entityName + "#" + id );
}
protected void entityIsTransient(MergeEvent event, Map copyCache) {
LOG.trace( "Merging transient instance" );
final Object entity = event.getEntity();
final EventSource source = event.getSession();
final String entityName = event.getEntityName();
final EntityPersister persister = source.getEntityPersister( entityName, entity );
final Serializable id = persister.hasIdentifierProperty() ?
persister.getIdentifier( entity, source ) :
null;
if ( copyCache.containsKey( entity ) ) {
persister.setIdentifier( copyCache.get( entity ), id, source );
}
else {
( (MergeContext) copyCache ).put( entity, source.instantiate( persister, id ), true ); //before cascade!
}
final Object copy = copyCache.get( entity );
// cascade first, so that all unsaved objects get their
// copy created before we actually copy
//cascadeOnMerge(event, persister, entity, copyCache, Cascades.CASCADE_BEFORE_MERGE);
super.cascadeBeforeSave( source, persister, entity, copyCache );
copyValues( persister, entity, copy, source, copyCache, ForeignKeyDirection.FROM_PARENT );
saveTransientEntity( copy, entityName, event.getRequestedId(), source, copyCache );
// cascade first, so that all unsaved objects get their
// copy created before we actually copy
super.cascadeAfterSave( source, persister, entity, copyCache );
copyValues( persister, entity, copy, source, copyCache, ForeignKeyDirection.TO_PARENT );
event.setResult( copy );
}
private boolean existsInDatabase(Object entity, EventSource source, EntityPersister persister) {
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
EntityEntry entry = persistenceContext.getEntry( entity );
if ( entry == null ) {
Serializable id = persister.getIdentifier( entity, source );
if ( id != null ) {
final EntityKey key = source.generateEntityKey( id, persister );
final Object managedEntity = persistenceContext.getEntity( key );
entry = persistenceContext.getEntry( managedEntity );
}
}
return entry != null && entry.isExistsInDatabase();
}
/**
* Hibernate 3.1 implementation of ID transferral.
*/
@Override
protected void entityIsTransient(MergeEvent event, Map copyCache) {
super.entityIsTransient(event, copyCache);
SessionImplementor session = event.getSession();
EntityPersister persister = session.getEntityPersister(event.getEntityName(), event.getEntity());
// Extract id from merged copy (which is currently registered with Session).
Serializable id = persister.getIdentifier(event.getResult(), session.getEntityMode());
// Set id on original object (which remains detached).
persister.setIdentifier(event.getOriginal(), id, session.getEntityMode());
}
/**
* Hibernate 3.1 implementation of ID transferral.
*/
@Override
protected void entityIsTransient(MergeEvent event, Map copyCache) {
super.entityIsTransient(event, copyCache);
SessionImplementor session = event.getSession();
EntityPersister persister = session.getEntityPersister(event.getEntityName(), event.getEntity());
// Extract id from merged copy (which is currently registered with Session).
Serializable id = persister.getIdentifier(event.getResult(), session.getEntityMode());
// Set id on original object (which remains detached).
persister.setIdentifier(event.getOriginal(), id, session.getEntityMode());
}
/**
* {@inheritDoc}
*/
public boolean isEqual(Object x, Object y, EntityMode entityMode, SessionFactoryImplementor factory) {
EntityPersister persister = factory.getEntityPersister(associatedEntityName);
if ( !persister.canExtractIdOutOfEntity() ) {
return super.isEqual(x, y, entityMode);
}
Serializable xid;
if (x instanceof HibernateProxy) {
xid = ( (HibernateProxy) x ).getHibernateLazyInitializer()
.getIdentifier();
}
else {
xid = persister.getIdentifier(x, entityMode);
}
Serializable yid;
if (y instanceof HibernateProxy) {
yid = ( (HibernateProxy) y ).getHibernateLazyInitializer()
.getIdentifier();
}
else {
yid = persister.getIdentifier(y, entityMode);
}
return persister.getIdentifierType()
.isEqual(xid, yid, entityMode, factory);
}
@Override
public void delete(String entityName, Object entity) {
checkOpen();
EntityPersister persister = getEntityPersister( entityName, entity );
Serializable id = persister.getIdentifier( entity, this );
Object version = persister.getVersion( entity );
persister.delete( id, version, entity, this );
}
/**
* Get the identifier value of an instance or proxy.
* <p/>
* Intended only for loggin purposes!!!
*
* @param object The object from which to extract the identifier.
* @param persister The entity persister
* @param entityMode The entity mode
* @return The extracted identifier.
*/
private static Serializable getIdentifier(Object object, EntityPersister persister, EntityMode entityMode) {
if (object instanceof HibernateProxy) {
HibernateProxy proxy = (HibernateProxy) object;
LazyInitializer li = proxy.getHibernateLazyInitializer();
return li.getIdentifier();
}
else {
return persister.getIdentifier( object, entityMode );
}
}
/**
* Generate a loggable representation of an instance of the value mapped by this type.
*
* @param value The instance to be logged.
* @param factory The session factory.
*
* @return The loggable string.
*
* @throws HibernateException Generally some form of resolution problem.
*/
@Override
public String toLoggableString(Object value, SessionFactoryImplementor factory) {
if ( value == null ) {
return "null";
}
final EntityPersister persister = getAssociatedEntityPersister( factory );
if ( !persister.getEntityTuplizer().isInstance( value ) ) {
// it should be the id type...
if ( persister.getIdentifierType().getReturnedClass().isInstance( value ) ) {
return associatedEntityName + "#" + value;
}
}
final StringBuilder result = new StringBuilder().append( associatedEntityName );
if ( persister.hasIdentifierProperty() ) {
final Serializable id;
if ( value instanceof HibernateProxy ) {
HibernateProxy proxy = (HibernateProxy) value;
id = proxy.getHibernateLazyInitializer().getIdentifier();
}
else {
id = persister.getIdentifier( value );
}
result.append( '#' )
.append( persister.getIdentifierType().toLoggableString( id, factory ) );
}
return result.toString();
}
protected void entityIsDetached(MergeEvent event, Map copyCache) {
log.trace("merging detached instance");
final Object entity = event.getEntity();
final EventSource source = event.getSession();
final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
final String entityName = persister.getEntityName();
Serializable id = event.getRequestedId();
if ( id == null ) {
id = persister.getIdentifier( entity, source.getEntityMode() );
}
else {
// check that entity id = requestedId
Serializable entityId = persister.getIdentifier( entity, source.getEntityMode() );
if ( !persister.getIdentifierType().isEqual( id, entityId, source.getEntityMode(), source.getFactory() ) ) {
throw new HibernateException( "merge requested with id not matching id of passed entity" );
}
}
String previousFetchProfile = source.getFetchProfile();
source.setFetchProfile("merge");
//we must clone embedded composite identifiers, or
//we will get back the same instance that we pass in
final Serializable clonedIdentifier = (Serializable) persister.getIdentifierType()
.deepCopy( id, source.getEntityMode(), source.getFactory() );
final Object result = source.get(entityName, clonedIdentifier);
source.setFetchProfile(previousFetchProfile);
if ( result == null ) {
//TODO: we should throw an exception if we really *know* for sure
// that this is a detached instance, rather than just assuming
//throw new StaleObjectStateException(entityName, id);
// we got here because we assumed that an instance
// with an assigned id was detached, when it was
// really persistent
entityIsTransient(event, copyCache);
}
else {
copyCache.put(entity, result); //before cascade!
final Object target = source.getPersistenceContext().unproxy(result);
if ( target == entity ) {
throw new AssertionFailure("entity was not detached");
}
else if ( !source.getEntityName(target).equals(entityName) ) {
throw new WrongClassException(
"class of the given object did not match class of persistent copy",
event.getRequestedId(),
entityName
);
}
else if ( isVersionChanged( entity, source, persister, target ) ) {
if ( source.getFactory().getStatistics().isStatisticsEnabled() ) {
source.getFactory().getStatisticsImplementor()
.optimisticFailure( entityName );
}
throw new StaleObjectStateException( entityName, id );
}
// cascade first, so that all unsaved objects get their
// copy created before we actually copy
cascadeOnMerge(source, persister, entity, copyCache);
copyValues(persister, entity, target, source, copyCache);
//copyValues works by reflection, so explicitly mark the entity instance dirty
markInterceptorDirty( entity, target );
event.setResult(result);
}
}
@Override
public CompletionStage<Void> reactiveOnLock(LockEvent event) throws HibernateException {
if ( event.getObject() == null ) {
throw new NullPointerException( "attempted to lock null" );
}
if ( event.getLockMode() == LockMode.WRITE ) {
throw new HibernateException( "Invalid lock mode for lock()" );
}
if ( event.getLockMode() == LockMode.UPGRADE_SKIPLOCKED ) {
log.explicitSkipLockedLockCombo();
}
SessionImplementor source = event.getSession();
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
Object entity = persistenceContext.unproxyAndReassociate( event.getObject() );
//TODO: if object was an uninitialized proxy, this is inefficient,
// resulting in two SQL selects
EntityEntry entry = persistenceContext.getEntry(entity);
CompletionStage<EntityEntry> stage;
if (entry==null) {
final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
final Serializable id = persister.getIdentifier( entity, source );
stage = ForeignKeys.isNotTransient( event.getEntityName(), entity, Boolean.FALSE, source )
.thenApply(
trans -> {
if (!trans) {
throw new TransientObjectException(
"cannot lock an unsaved transient instance: " +
persister.getEntityName()
);
}
EntityEntry e = reassociate(event, entity, id, persister);
cascadeOnLock(event, persister, entity);
return e;
} );
}
else {
stage = CompletionStages.completedFuture(entry);
}
return stage.thenCompose( e -> upgradeLock( entity, e, event.getLockOptions(), event.getSession() ) );
}
protected CompletionStage<Void> entityIsTransient(MergeEvent event, MergeContext copyCache) {
LOG.trace( "Merging transient instance" );
final Object entity = event.getEntity();
final EventSource session = event.getSession();
final String entityName = event.getEntityName();
final EntityPersister persister = session.getEntityPersister( entityName, entity );
final Serializable id = persister.hasIdentifierProperty()
? persister.getIdentifier( entity, session )
: null;
final Object copy;
final Object existingCopy = copyCache.get( entity );
if ( existingCopy != null ) {
persister.setIdentifier( copyCache.get( entity ), id, session );
copy = existingCopy;
}
else {
copy = session.instantiate( persister, id );
//before cascade!
copyCache.put( entity, copy, true );
}
// cascade first, so that all unsaved objects get their
// copy created before we actually copy
//cascadeOnMerge(event, persister, entity, copyCache, Cascades.CASCADE_BEFORE_MERGE);
return super.cascadeBeforeSave( session, persister, entity, copyCache )
.thenAccept( v -> copyValues( persister, entity, copy, session, copyCache, ForeignKeyDirection.FROM_PARENT ) )
.thenCompose( v -> saveTransientEntity( copy, entityName, event.getRequestedId(), session, copyCache ) )
.thenCompose( v -> super.cascadeAfterSave( session, persister, entity, copyCache ) )
.thenAccept( v -> {
copyValues(persister, entity, copy, session, copyCache, ForeignKeyDirection.TO_PARENT);
event.setResult(copy);
if (copy instanceof PersistentAttributeInterceptable) {
final PersistentAttributeInterceptable interceptable = (PersistentAttributeInterceptable) copy;
final PersistentAttributeInterceptor interceptor = interceptable.$$_hibernate_getInterceptor();
if (interceptor == null) {
persister.getBytecodeEnhancementMetadata().injectInterceptor(copy, id, session);
}
}
});
}
protected CompletionStage<Void> entityIsDetached(MergeEvent event, MergeContext copyCache) {
LOG.trace( "Merging detached instance" );
final Object entity = event.getEntity();
final EventSource source = event.getSession();
final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
final String entityName = persister.getEntityName();
Serializable requestedId = event.getRequestedId();
Serializable id;
if ( requestedId == null ) {
id = persister.getIdentifier( entity, source );
}
else {
id = requestedId;
// check that entity id = requestedId
Serializable entityId = persister.getIdentifier( entity, source );
if ( !persister.getIdentifierType().isEqual( id, entityId, source.getFactory() ) ) {
throw new HibernateException( "merge requested with id not matching id of passed entity" );
}
}
String previousFetchProfile = source.getLoadQueryInfluencers().getInternalFetchProfile();
source.getLoadQueryInfluencers().setInternalFetchProfile( "merge" );
//we must clone embedded composite identifiers, or
//we will get back the same instance that we pass in
final Serializable clonedIdentifier = (Serializable)
persister.getIdentifierType().deepCopy( id, source.getFactory() );
return source.unwrap(ReactiveSession.class)
.reactiveGet( (Class<?>) persister.getMappedClass(), clonedIdentifier )
.thenCompose(result -> {
if ( result!=null ) {
// before cascade!
copyCache.put(entity, result, true);
Object target = unproxyManagedForDetachedMerging(entity, result, persister, source);
if (target == entity) {
throw new AssertionFailure("entity was not detached");
}
else if ( !source.getEntityName(target).equals(entityName) ) {
throw new WrongClassException(
"class of the given object did not match class of persistent copy",
event.getRequestedId(),
entityName
);
}
else if ( isVersionChanged(entity, source, persister, target) ) {
final StatisticsImplementor statistics = source.getFactory().getStatistics();
if (statistics.isStatisticsEnabled()) {
statistics.optimisticFailure(entityName);
}
throw new StaleObjectStateException(entityName, id);
}
// cascade first, so that all unsaved objects get their
// copy created before we actually copy
return cascadeOnMerge( source, persister, entity, copyCache )
.thenCompose( v -> fetchAndCopyValues( persister, entity, target, source, copyCache ) )
.thenAccept(v -> {
// copyValues() (called by fetchAndCopyValues) works by reflection,
// so explicitly mark the entity instance dirty
markInterceptorDirty(entity, target, persister);
event.setResult(result);
});
}
else {
//TODO: we should throw an exception if we really *know* for sure
// that this is a detached instance, rather than just assuming
//throw new StaleObjectStateException(entityName, id);
// we got here because we assumed that an instance
// with an assigned id was detached, when it was
// really persistent
return entityIsTransient(event, copyCache);
}
})
.whenComplete( (v,e) -> source.getLoadQueryInfluencers().setInternalFetchProfile(previousFetchProfile) );
}
protected void entityIsDetached(MergeEvent event, Map copyCache) {
LOG.trace( "Merging detached instance" );
final Object entity = event.getEntity();
final EventSource source = event.getSession();
final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
final String entityName = persister.getEntityName();
Serializable id = event.getRequestedId();
if ( id == null ) {
id = persister.getIdentifier( entity, source );
}
else {
// check that entity id = requestedId
Serializable entityId = persister.getIdentifier( entity, source );
if ( !persister.getIdentifierType().isEqual( id, entityId, source.getFactory() ) ) {
throw new HibernateException( "merge requested with id not matching id of passed entity" );
}
}
String previousFetchProfile = source.getLoadQueryInfluencers().getInternalFetchProfile();
source.getLoadQueryInfluencers().setInternalFetchProfile( "merge" );
//we must clone embedded composite identifiers, or
//we will get back the same instance that we pass in
final Serializable clonedIdentifier = (Serializable) persister.getIdentifierType()
.deepCopy( id, source.getFactory() );
final Object result = source.get( entityName, clonedIdentifier );
source.getLoadQueryInfluencers().setInternalFetchProfile( previousFetchProfile );
if ( result == null ) {
//TODO: we should throw an exception if we really *know* for sure
// that this is a detached instance, rather than just assuming
//throw new StaleObjectStateException(entityName, id);
// we got here because we assumed that an instance
// with an assigned id was detached, when it was
// really persistent
entityIsTransient( event, copyCache );
}
else {
( (MergeContext) copyCache ).put( entity, result, true ); //before cascade!
final Object target = source.getPersistenceContext().unproxy( result );
if ( target == entity ) {
throw new AssertionFailure( "entity was not detached" );
}
else if ( !source.getEntityName( target ).equals( entityName ) ) {
throw new WrongClassException(
"class of the given object did not match class of persistent copy",
event.getRequestedId(),
entityName
);
}
else if ( isVersionChanged( entity, source, persister, target ) ) {
if ( source.getFactory().getStatistics().isStatisticsEnabled() ) {
source.getFactory().getStatistics().optimisticFailure( entityName );
}
throw new StaleObjectStateException( entityName, id );
}
// cascade first, so that all unsaved objects get their
// copy created before we actually copy
cascadeOnMerge( source, persister, entity, copyCache );
copyValues( persister, entity, target, source, copyCache );
//copyValues works by reflection, so explicitly mark the entity instance dirty
markInterceptorDirty( entity, target, persister );
event.setResult( result );
}
}
/**
* Handle the given merge event.
*
* @param event The merge event to be handled.
*
* @throws HibernateException
*/
public void onMerge(MergeEvent event, Map copiedAlready) throws HibernateException {
final MergeContext copyCache = (MergeContext) copiedAlready;
final EventSource source = event.getSession();
final Object original = event.getOriginal();
if ( original != null ) {
final Object entity;
if ( original instanceof HibernateProxy ) {
LazyInitializer li = ( (HibernateProxy) original ).getHibernateLazyInitializer();
if ( li.isUninitialized() ) {
LOG.trace( "Ignoring uninitialized proxy" );
event.setResult( source.load( li.getEntityName(), li.getIdentifier() ) );
return; //EARLY EXIT!
}
else {
entity = li.getImplementation();
}
}
else {
entity = original;
}
if ( copyCache.containsKey( entity ) &&
( copyCache.isOperatedOn( entity ) ) ) {
LOG.trace( "Already in merge process" );
event.setResult( entity );
}
else {
if ( copyCache.containsKey( entity ) ) {
LOG.trace( "Already in copyCache; setting in merge process" );
copyCache.setOperatedOn( entity, true );
}
event.setEntity( entity );
EntityState entityState = null;
// Check the persistence context for an entry relating to this
// entity to be merged...
EntityEntry entry = source.getPersistenceContext().getEntry( entity );
if ( entry == null ) {
EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
Serializable id = persister.getIdentifier( entity, source );
if ( id != null ) {
final EntityKey key = source.generateEntityKey( id, persister );
final Object managedEntity = source.getPersistenceContext().getEntity( key );
entry = source.getPersistenceContext().getEntry( managedEntity );
if ( entry != null ) {
// we have specialized case of a detached entity from the
// perspective of the merge operation. Specifically, we
// have an incoming entity instance which has a corresponding
// entry in the current persistence context, but registered
// under a different entity instance
entityState = EntityState.DETACHED;
}
}
}
if ( entityState == null ) {
entityState = getEntityState( entity, event.getEntityName(), entry, source );
}
switch ( entityState ) {
case DETACHED:
entityIsDetached( event, copyCache );
break;
case TRANSIENT:
entityIsTransient( event, copyCache );
break;
case PERSISTENT:
entityIsPersistent( event, copyCache );
break;
default: //DELETED
throw new ObjectDeletedException(
"deleted instance passed to merge",
null,
getLoggableName( event.getEntityName(), entity )
);
}
}
}
}
/**
* Handle the given create event.
*
* @param event The create event to be handled.
*
*/
public void onPersist(PersistEvent event, Map createCache) throws HibernateException {
final SessionImplementor source = event.getSession();
final Object object = event.getObject();
final Object entity;
if ( object instanceof HibernateProxy ) {
LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer();
if ( li.isUninitialized() ) {
if ( li.getSession() == source ) {
return; //NOTE EARLY EXIT!
}
else {
throw new PersistentObjectException( "uninitialized proxy passed to persist()" );
}
}
entity = li.getImplementation();
}
else {
entity = object;
}
final String entityName;
if ( event.getEntityName() != null ) {
entityName = event.getEntityName();
}
else {
entityName = source.bestGuessEntityName( entity );
event.setEntityName( entityName );
}
final EntityEntry entityEntry = source.getPersistenceContext().getEntry( entity );
EntityState entityState = getEntityState( entity, entityName, entityEntry, source );
if ( entityState == EntityState.DETACHED ) {
// JPA 2, in its version of a "foreign generated", allows the id attribute value
// to be manually set by the user, even though this manual value is irrelevant.
// The issue is that this causes problems with the Hibernate unsaved-value strategy
// which comes into play here in determining detached/transient state.
//
// Detect if we have this situation and if so null out the id value and calculate the
// entity state again.
// NOTE: entityEntry must be null to get here, so we cannot use any of its values
EntityPersister persister = source.getFactory().getEntityPersister( entityName );
if ( ForeignGenerator.class.isInstance( persister.getIdentifierGenerator() ) ) {
if ( LOG.isDebugEnabled() && persister.getIdentifier( entity, source ) != null ) {
LOG.debug( "Resetting entity id attribute to null for foreign generator" );
}
persister.setIdentifier( entity, null, source );
entityState = getEntityState( entity, entityName, entityEntry, source );
}
}
switch ( entityState ) {
case DETACHED: {
throw new PersistentObjectException(
"detached entity passed to persist: " +
getLoggableName( event.getEntityName(), entity )
);
}
case PERSISTENT: {
entityIsPersistent( event, createCache );
break;
}
case TRANSIENT: {
entityIsTransient( event, createCache );
break;
}
case DELETED: {
entityEntry.setStatus( Status.MANAGED );
entityEntry.setDeletedState( null );
event.getSession().getActionQueue().unScheduleDeletion( entityEntry, event.getObject() );
entityIsDeleted( event, createCache );
break;
}
default: {
throw new ObjectDeletedException(
"deleted entity passed to persist",
null,
getLoggableName( event.getEntityName(), entity )
);
}
}
}