Package org.hibernate.action.internal

Source Code of org.hibernate.action.internal.EntityIdentityInsertAction

/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors.  All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA  02110-1301  USA
*/
package org.hibernate.action.internal;

import java.io.Serializable;

import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.spi.EventType;
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;

public final class EntityIdentityInsertAction extends EntityAction  {

  private transient Object[] state;
  private final boolean isDelayed;
  private final EntityKey delayedEntityKey;
  //private CacheEntry cacheEntry;
  private Serializable generatedId;

  public EntityIdentityInsertAction(
      Object[] state,
          Object instance,
          EntityPersister persister,
          SessionImplementor session,
          boolean isDelayed) throws HibernateException {
    super(
        session,
        ( isDelayed ? generateDelayedPostInsertIdentifier() : null ),
        instance,
        persister
    );
    this.state = state;
    this.isDelayed = isDelayed;
    this.delayedEntityKey = isDelayed ? generateDelayedEntityKey() : null;
  }

  @Override
  public void execute() throws HibernateException {
    final EntityPersister persister = getPersister();
    final SessionImplementor session = getSession();
    final Object instance = getInstance();

    boolean veto = preInsert();

    // Don't need to lock the cache here, since if someone
    // else inserted the same pk first, the insert would fail

    if ( !veto ) {
      generatedId = persister.insert( state, instance, session );
      if ( persister.hasInsertGeneratedProperties() ) {
        persister.processInsertGeneratedProperties( generatedId, instance, state, 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 );
      getSession().getPersistenceContext().registerInsertedKey( getPersister(), generatedId );
    }


    //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() && !veto ) {
      session.getFactory().getStatisticsImplementor().insertEntity( getPersister().getEntityName() );
    }

  }

  @Override
    public boolean needsAfterTransactionCompletion() {
    //TODO: simply remove this override if we fix the above todos
    return hasPostCommitEventListeners();
  }

  @Override
    protected boolean hasPostCommitEventListeners() {
    return ! listenerGroup( EventType.POST_COMMIT_INSERT ).isEmpty();
  }

  @Override
  public void doAfterTransactionCompletion(boolean success, SessionImplementor 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();
  }

  private void postInsert() {
    if ( isDelayed ) {
      getSession().getPersistenceContext().replaceDelayedEntityIdentityInsertKeys( delayedEntityKey, generatedId );
    }

    EventListenerGroup<PostInsertEventListener> listenerGroup = listenerGroup( EventType.POST_INSERT );
    if ( listenerGroup.isEmpty() ) {
      return;
    }
    final PostInsertEvent event = new PostInsertEvent(
        getInstance(),
        generatedId,
        state,
        getPersister(),
        eventSource()
    );
    for ( PostInsertEventListener listener : listenerGroup.listeners() ) {
      listener.onPostInsert( event );
    }
  }

  private void postCommitInsert() {
    EventListenerGroup<PostInsertEventListener> listenerGroup = listenerGroup( EventType.POST_COMMIT_INSERT );
    if ( listenerGroup.isEmpty() ) {
      return;
    }
    final PostInsertEvent event = new PostInsertEvent(
        getInstance(),
        generatedId,
        state,
        getPersister(),
        eventSource()
    );
    for ( PostInsertEventListener listener : listenerGroup.listeners() ) {
      listener.onPostInsert( event );
    }
  }

  private boolean preInsert() {
    EventListenerGroup<PreInsertEventListener> listenerGroup = listenerGroup( EventType.PRE_INSERT );
    if ( listenerGroup.isEmpty() ) {
      return false; // NO_VETO
    }
    boolean veto = false;
    final PreInsertEvent event = new PreInsertEvent( getInstance(), null, state, getPersister(), eventSource() );
    for ( PreInsertEventListener listener : listenerGroup.listeners() ) {
      veto |= listener.onPreInsert( event );
    }
    return veto;
  }

  public final Serializable getGeneratedId() {
    return generatedId;
  }

  public EntityKey getDelayedEntityKey() {
    return delayedEntityKey;
  }

  private synchronized static DelayedPostInsertIdentifier generateDelayedPostInsertIdentifier() {
    return new DelayedPostInsertIdentifier();
  }

  private EntityKey generateDelayedEntityKey() {
    if ( !isDelayed ) {
      throw new AssertionFailure( "cannot request delayed entity-key for non-delayed post-insert-id generation" );
    }
    return getSession().generateEntityKey( getDelayedId(), getPersister() );
  }

  @Override
    public void afterDeserialize(SessionImplementor session) {
    super.afterDeserialize( session );
    // IMPL NOTE: non-flushed changes code calls this method with session == null...
    // guard against NullPointerException
    if ( session != null ) {
      EntityEntry entityEntry = session.getPersistenceContext().getEntry( getInstance() );
      this.state = entityEntry.getLoadedState();
    }
  }
}
TOP

Related Classes of org.hibernate.action.internal.EntityIdentityInsertAction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.