Open Source Repository

Home /hibernate/hibernate-3.2.6.ga | Repository Home


org/hibernate/id/IdentityGenerator.java
//$Id: IdentityGenerator.java 14098 2007-10-18 06:17:56Z gbadner $
package org.hibernate.id;

import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;

import org.hibernate.engine.SessionImplementor;
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
import org.hibernate.id.insert.IdentifierGeneratingInsert;
import org.hibernate.id.insert.AbstractSelectingDelegate;
import org.hibernate.id.insert.AbstractReturningDelegate;
import org.hibernate.id.insert.InsertSelectIdentityInsert;
import org.hibernate.dialect.Dialect;
import org.hibernate.HibernateException;
import org.hibernate.AssertionFailure;
import org.hibernate.util.GetGeneratedKeysHelper;


/**
 * A generator for use with ANSI-SQL IDENTITY columns used as the primary key.
 * The IdentityGenerator for autoincrement/identity key generation.
 <br><br>
 * Indicates to the <tt>Session</tt> that identity (ie. identity/autoincrement
 * column) key generation should be used.
 *
 @author Christoph Sturm
 */
public class IdentityGenerator extends AbstractPostInsertGenerator {

  public InsertGeneratedIdentifierDelegate getInsertGeneratedIdentifierDelegate(
      PostInsertIdentityPersister persister,
          Dialect dialect,
          boolean isGetGeneratedKeysEnabledthrows HibernateException {
    if isGetGeneratedKeysEnabled ) {
      return new GetGeneratedKeysDelegatepersister, dialect );
    }
    else if dialect.supportsInsertSelectIdentity() ) {
      return new InsertSelectDelegatepersister, dialect );
    }
    else {
      return new BasicDelegatepersister, dialect );
    }
  }

  /**
   * Delegate for dealing with IDENTITY columns using JDBC3 getGeneratedKeys
   */
  public static class GetGeneratedKeysDelegate
      extends AbstractReturningDelegate
      implements InsertGeneratedIdentifierDelegate {
    private final PostInsertIdentityPersister persister;
    private final Dialect dialect;

    public GetGeneratedKeysDelegate(PostInsertIdentityPersister persister, Dialect dialect) {
      superpersister );
      this.persister = persister;
      this.dialect = dialect;
    }

    public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert() {
      IdentifierGeneratingInsert insert = new IdentifierGeneratingInsertdialect );
      insert.addIdentityColumnpersister.getRootTableKeyColumnNames()[0] );
      return insert;
    }

    protected PreparedStatement prepare(String insertSQL, SessionImplementor sessionthrows SQLException {
      return session.getBatcher().prepareStatementinsertSQL, true );
    }

    public Serializable executeAndExtract(PreparedStatement insertthrows SQLException {
      insert.executeUpdate();
      ResultSet rs = null;
      try {
        rs = GetGeneratedKeysHelper.getGeneratedKeyinsert );
        return IdentifierGeneratorFactory.getGeneratedIdentity(
          rs,
          persister.getIdentifierType()
        );
      }
      finally {
        if rs != null ) {
          rs.close();
        }
      }
    }
  }

  /**
   * Delegate for dealing with IDENTITY columns where the dialect supports returning
   * the generated IDENTITY value directly from the insert statement.
   */
  public static class InsertSelectDelegate
      extends AbstractReturningDelegate
      implements InsertGeneratedIdentifierDelegate {
    private final PostInsertIdentityPersister persister;
    private final Dialect dialect;

    public InsertSelectDelegate(PostInsertIdentityPersister persister, Dialect dialect) {
      superpersister );
      this.persister = persister;
      this.dialect = dialect;
    }

    public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert() {
      InsertSelectIdentityInsert insert = new InsertSelectIdentityInsertdialect );
      insert.addIdentityColumnpersister.getRootTableKeyColumnNames()[0] );
      return insert;
    }

    protected PreparedStatement prepare(String insertSQL, SessionImplementor sessionthrows SQLException {
      return session.getBatcher().prepareStatementinsertSQL, false );
    }

    public Serializable executeAndExtract(PreparedStatement insertthrows SQLException {
      if !insert.execute() ) {
        while !insert.getMoreResults() && insert.getUpdateCount() != -) {
          // do nothing until we hit the rsult set containing the generated id
        }
      }
      ResultSet rs = insert.getResultSet();
      try {
        return IdentifierGeneratorFactory.getGeneratedIdentityrs, persister.getIdentifierType() );
      }
      finally {
        rs.close();
      }
    }

    public Serializable determineGeneratedIdentifier(SessionImplementor session, Object entity) {
      throw new AssertionFailure"insert statement returns generated value" );
    }
  }

  /**
   * Delegate for dealing with IDENTITY columns where the dialect requires an
   * additional command execution to retrieve the generated IDENTITY value
   */
  public static class BasicDelegate
      extends AbstractSelectingDelegate
      implements InsertGeneratedIdentifierDelegate {
    private final PostInsertIdentityPersister persister;
    private final Dialect dialect;

    public BasicDelegate(PostInsertIdentityPersister persister, Dialect dialect) {
      superpersister );
      this.persister = persister;
      this.dialect = dialect;
    }

    public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert() {
      IdentifierGeneratingInsert insert = new IdentifierGeneratingInsertdialect );
      insert.addIdentityColumnpersister.getRootTableKeyColumnNames()[0] );
      return insert;
    }

    protected String getSelectSQL() {
      return persister.getIdentitySelectString();
    }

    protected Serializable getResult(
        SessionImplementor session,
            ResultSet rs,
            Object objectthrows SQLException {
      return IdentifierGeneratorFactory.getGeneratedIdentityrs, persister.getIdentifierType() );
    }
  }

}