/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
 * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
 */
package org.hibernate.action.internal;

import java.io.Serializable;

import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PostCommitInsertEventListener;
import org.hibernate.event.spi.PostInsertEvent;
import org.hibernate.event.spi.PostInsertEventListener;
import org.hibernate.event.spi.PreInsertEvent;
import org.hibernate.event.spi.PreInsertEventListener;
import org.hibernate.persister.entity.EntityPersister;

The action for performing entity insertions when entity is using IDENTITY column identifier generation
See Also:
  • EntityInsertAction
/** * The action for performing entity insertions when entity is using IDENTITY column identifier generation * * @see EntityInsertAction */
public final class EntityIdentityInsertAction extends AbstractEntityInsertAction { private final boolean isDelayed; private final EntityKey delayedEntityKey; private EntityKey entityKey; private Serializable generatedId;
Constructs an EntityIdentityInsertAction
Params:
  • state – The current (extracted) entity state
  • instance – The entity instance
  • persister – The entity persister
  • isVersionIncrementDisabled – Whether version incrementing is disabled
  • session – The session
  • isDelayed – Are we in a situation which allows the insertion to be delayed?
Throws:
/** * Constructs an EntityIdentityInsertAction * * @param state The current (extracted) entity state * @param instance The entity instance * @param persister The entity persister * @param isVersionIncrementDisabled Whether version incrementing is disabled * @param session The session * @param isDelayed Are we in a situation which allows the insertion to be delayed? * * @throws HibernateException Indicates an illegal state */
public EntityIdentityInsertAction( Object[] state, Object instance, EntityPersister persister, boolean isVersionIncrementDisabled, SharedSessionContractImplementor session, boolean isDelayed) { super( ( isDelayed ? generateDelayedPostInsertIdentifier() : null ), state, instance, isVersionIncrementDisabled, persister, session ); this.isDelayed = isDelayed; this.delayedEntityKey = isDelayed ? generateDelayedEntityKey() : null; } @Override public void execute() throws HibernateException { nullifyTransientReferencesIfNotAlready(); final EntityPersister persister = getPersister(); final SharedSessionContractImplementor session = getSession(); final Object instance = getInstance(); setVeto( preInsert() ); // Don't need to lock the cache here, since if someone // else inserted the same pk first, the insert would fail if ( !isVeto() ) { generatedId = persister.insert( getState(), instance, session ); if ( persister.hasInsertGeneratedProperties() ) { persister.processInsertGeneratedProperties( generatedId, instance, getState(), session ); } //need to do that here rather than in the save event listener to let //the post insert events to have a id-filled entity when IDENTITY is used (EJB3) persister.setIdentifier( instance, generatedId, session ); session.getPersistenceContext().registerInsertedKey( getPersister(), generatedId ); entityKey = session.generateEntityKey( generatedId, persister ); session.getPersistenceContext().checkUniqueness( entityKey, getInstance() ); } //TODO: this bit actually has to be called after all cascades! // but since identity insert is called *synchronously*, // instead of asynchronously as other actions, it isn't /*if ( persister.hasCache() && !persister.isCacheInvalidationRequired() ) { cacheEntry = new CacheEntry(object, persister, session); persister.getCache().insert(generatedId, cacheEntry); }*/ postInsert(); if ( session.getFactory().getStatistics().isStatisticsEnabled() && !isVeto() ) { session.getFactory().getStatistics().insertEntity( getPersister().getEntityName() ); } markExecuted(); } @Override public boolean needsAfterTransactionCompletion() { //TODO: simply remove this override if we fix the above todos return hasPostCommitEventListeners(); } @Override protected boolean hasPostCommitEventListeners() { final EventListenerGroup<PostInsertEventListener> group = listenerGroup( EventType.POST_COMMIT_INSERT ); for ( PostInsertEventListener listener : group.listeners() ) { if ( listener.requiresPostCommitHandling( getPersister() ) ) { return true; } } return false; } @Override public void doAfterTransactionCompletion(boolean success, SharedSessionContractImplementor session) { //TODO: reenable if we also fix the above todo /*EntityPersister persister = getEntityPersister(); if ( success && persister.hasCache() && !persister.isCacheInvalidationRequired() ) { persister.getCache().afterInsert( getGeneratedId(), cacheEntry ); }*/ postCommitInsert( success ); } private void postInsert() { if ( isDelayed ) { getSession().getPersistenceContext().replaceDelayedEntityIdentityInsertKeys( delayedEntityKey, generatedId ); } final EventListenerGroup<PostInsertEventListener> listenerGroup = listenerGroup( EventType.POST_INSERT ); if ( listenerGroup.isEmpty() ) { return; } final PostInsertEvent event = new PostInsertEvent( getInstance(), generatedId, getState(), getPersister(), eventSource() ); for ( PostInsertEventListener listener : listenerGroup.listeners() ) { listener.onPostInsert( event ); } } private void postCommitInsert(boolean success) { final EventListenerGroup<PostInsertEventListener> listenerGroup = listenerGroup( EventType.POST_COMMIT_INSERT ); if ( listenerGroup.isEmpty() ) { return; } final PostInsertEvent event = new PostInsertEvent( getInstance(), generatedId, getState(), getPersister(), eventSource() ); for ( PostInsertEventListener listener : listenerGroup.listeners() ) { if ( PostCommitInsertEventListener.class.isInstance( listener ) ) { if ( success ) { listener.onPostInsert( event ); } else { ((PostCommitInsertEventListener) listener).onPostInsertCommitFailed( event ); } } else { //default to the legacy implementation that always fires the event listener.onPostInsert( event ); } } } private boolean preInsert() { final EventListenerGroup<PreInsertEventListener> listenerGroup = listenerGroup( EventType.PRE_INSERT ); if ( listenerGroup.isEmpty() ) { // NO_VETO return false; } boolean veto = false; final PreInsertEvent event = new PreInsertEvent( getInstance(), null, getState(), getPersister(), eventSource() ); for ( PreInsertEventListener listener : listenerGroup.listeners() ) { veto |= listener.onPreInsert( event ); } return veto; }
Access to the generated identifier
Returns:The generated identifier
/** * Access to the generated identifier * * @return The generated identifier */
public final Serializable getGeneratedId() { return generatedId; }
Access to the delayed entity key
Returns:The delayed entity key
Deprecated:No Hibernate code currently uses this method
/** * Access to the delayed entity key * * @return The delayed entity key * * @deprecated No Hibernate code currently uses this method */
@Deprecated @SuppressWarnings("UnusedDeclaration") public EntityKey getDelayedEntityKey() { return delayedEntityKey; } @Override public boolean isEarlyInsert() { return !isDelayed; } @Override protected EntityKey getEntityKey() { return entityKey != null ? entityKey : delayedEntityKey; } private static DelayedPostInsertIdentifier generateDelayedPostInsertIdentifier() { return new DelayedPostInsertIdentifier(); } private EntityKey generateDelayedEntityKey() { if ( !isDelayed ) { throw new AssertionFailure( "cannot request delayed entity-key for early-insert post-insert-id generation" ); } return getSession().generateEntityKey( getDelayedId(), getPersister() ); } }