Open Source Repository

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


org/hibernate/id/enhanced/TableStructure.java
package org.hibernate.id.enhanced;

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.hibernate.dialect.Dialect;
import org.hibernate.LockMode;
import org.hibernate.HibernateException;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.TransactionHelper;
import org.hibernate.id.IdentifierGenerationException;

/**
 * Describes a table used to mimic sequence behavior
 *
 @author Steve Ebersole
 */
public class TableStructure extends TransactionHelper implements DatabaseStructure {
  private static final Log log = LogFactory.getLogTableStructure.class );
  private static final Log SQL_LOG = LogFactory.getLog"org.hibernate.SQL" );

  private final String tableName;
  private final String valueColumnName;
  private final int initialValue;
  private final int incrementSize;
  private final String select;
  private final String update;
  private boolean applyIncrementSizeToSourceValues;
  private int accessCounter;

  public TableStructure(Dialect dialect, String tableName, String valueColumnName, int initialValue, int incrementSize) {
    this.tableName = tableName;
    this.initialValue = initialValue;
    this.incrementSize = incrementSize;
    this.valueColumnName = valueColumnName;

    select = "select " + valueColumnName + " id_val" +
        " from " + dialect.appendLockHintLockMode.UPGRADE, tableName +
        dialect.getForUpdateString();

    update = "update " + tableName +
        " set " + valueColumnName + "= ?" +
        " where " + valueColumnName + "=?";
  }

  public String getName() {
    return tableName;
  }

  public int getIncrementSize() {
    return incrementSize;
  }

  public int getTimesAccessed() {
    return accessCounter;
  }

  public void prepare(Optimizer optimizer) {
    applyIncrementSizeToSourceValues = optimizer.applyIncrementSizeToSourceValues();
  }

  public AccessCallback buildCallback(final SessionImplementor session) {
    return new AccessCallback() {
      public long getNextValue() {
        return ( ( Number doWorkInNewTransactionsession ) ).longValue();
      }
    };
  }

  public String[] sqlCreateStrings(Dialect dialectthrows HibernateException {
    return new String[] {
        "create table " + tableName + " ( " + valueColumnName + " " + dialect.getTypeNameTypes.BIGINT " )",
        "insert into " + tableName + " values ( " + initialValue + " )"
    };
  }

  public String[] sqlDropStrings(Dialect dialectthrows HibernateException {
    StringBuffer sqlDropString = new StringBuffer().append"drop table " );
    if dialect.supportsIfExistsBeforeTableName() ) {
      sqlDropString.append"if exists " );
    }
    sqlDropString.appendtableName ).appenddialect.getCascadeConstraintsString() );
    if dialect.supportsIfExistsAfterTableName() ) {
      sqlDropString.append" if exists" );
    }
    return new String[] { sqlDropString.toString() };
  }

  protected Serializable doWorkInCurrentTransaction(Connection conn, String sqlthrows SQLException {
    long result;
    int rows;
    do {
      sql = select;
      SQL_LOG.debugsql );
      PreparedStatement qps = conn.prepareStatementselect );
      try {
        ResultSet rs = qps.executeQuery();
        if !rs.next() ) {
          String err = "could not read a hi value - you need to populate the table: " + tableName;
          log.errorerr );
          throw new IdentifierGenerationExceptionerr );
        }
        result = rs.getLong);
        rs.close();
      }
      catch SQLException sqle ) {
        log.error"could not read a hi value", sqle );
        throw sqle;
      }
      finally {
        qps.close();
      }

      sql = update;
      SQL_LOG.debugsql );
      PreparedStatement ups = conn.prepareStatementupdate );
      try {
        int increment = applyIncrementSizeToSourceValues ? incrementSize : 1;
        ups.setLong1, result + increment );
        ups.setLong2, result );
        rows = ups.executeUpdate();
      }
      catch SQLException sqle ) {
        log.error"could not update hi value in: " + tableName, sqle );
        throw sqle;
      }
      finally {
        ups.close();
      }
    while rows == );

    accessCounter++;

    return new Longresult );
  }

}