All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.ebeaninternal.server.persist.dml.InsertHandler Maven / Gradle / Ivy

There is a newer version: 15.8.0
Show newest version
package io.ebeaninternal.server.persist.dml;

import io.ebean.bean.EntityBean;
import io.ebean.util.JdbcClose;
import io.ebeaninternal.api.SpiTransaction;
import io.ebeaninternal.server.core.PersistRequestBean;
import io.ebeaninternal.server.deploy.BeanDescriptor;

import javax.persistence.OptimisticLockException;
import javax.persistence.PersistenceException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import static io.ebeaninternal.server.persist.DmlUtil.isNullOrZero;

/**
 * Insert bean handler.
 */
public final class InsertHandler extends DmlHandler {

  private final InsertMeta meta;
  private final boolean concatenatedKey;
  private boolean useGeneratedKeys;
  /**
   * SQL Select used to fetch back the Id where generatedKeys is not supported.
   */
  private boolean useSelectLastInsertedId;

  /**
   * Create to handle the insert execution.
   */
  public InsertHandler(PersistRequestBean persist, InsertMeta meta) {
    super(persist);
    this.meta = meta;
    this.concatenatedKey = meta.isConcatenatedKey();
  }

  @Override
  public boolean isUpdate() {
    return false;
  }

  /**
   * Generate and bind the insert statement.
   */
  @Override
  public void bind() throws SQLException {
    BeanDescriptor desc = persistRequest.descriptor();
    EntityBean bean = persistRequest.entityBean();
    Object idValue = desc.getId(bean);
    boolean withId = !isNullOrZero(idValue);

    // check to see if we are going to use generated keys
    if (!withId) {
      if (concatenatedKey) {
        // expecting a concatenated key that can
        // be built from supplied AssocOne beans
        withId = meta.deriveConcatenatedId(persistRequest);
      } else if (meta.supportsGetGeneratedKeys()) {
        // Identity with getGeneratedKeys
        useGeneratedKeys = true;
      } else {
        // use a query to get the last inserted id
        useSelectLastInsertedId = meta.supportsSelectLastInsertedId();
      }
    }

    SpiTransaction t = persistRequest.transaction();
    // get the appropriate sql
    sql = meta.sql(withId, persistRequest.isPublish(), persistRequest.insertOptions());
    PreparedStatement pstmt;
    if (persistRequest.isBatched()) {
      pstmt = pstmtBatch(t, sql, persistRequest, useGeneratedKeys);
    } else {
      pstmt = pstmt(t, sql, useGeneratedKeys);
    }
    dataBind = bind(pstmt);
    meta.bind(this, bean, withId, persistRequest.isPublish());
    if (persistRequest.isBatched()) {
      batchedPstmt.registerInputStreams(dataBind.getInputStreams());
    }
    logSql(sql);
  }

  /**
   * Check with useGeneratedKeys to get appropriate PreparedStatement.
   */
  @Override
  PreparedStatement pstmt(SpiTransaction t, String sql, boolean useGeneratedKeys) throws SQLException {
    Connection conn = t.internalConnection();
    if (useGeneratedKeys) {
      return conn.prepareStatement(sql, meta.identityDbColumns());
    } else {
      return conn.prepareStatement(sql);
    }
  }

  /**
   * Execute non batched insert additionally using getGeneratedKeys if required.
   */
  @Override
  public int execute() throws SQLException, OptimisticLockException {
    int rowCount = dataBind.executeUpdate();
    if (useGeneratedKeys) {
      // get the auto-increment value back and set into the bean
      getGeneratedKeys();

    } else if (useSelectLastInsertedId) {
      // fetch back the Id using a query
      fetchGeneratedKeyUsingSelect();
    }

    checkRowCount(rowCount);
    return rowCount;
  }

  /**
   * For non batch insert with generated keys.
   */
  private void getGeneratedKeys() throws SQLException {
    ResultSet rset = dataBind.getPstmt().getGeneratedKeys();
    try {
      setGeneratedKey(rset);
    } finally {
      JdbcClose.close(rset);
    }
  }

  private void setGeneratedKey(ResultSet rset) throws SQLException {
    if (rset.next()) {
      Object idValue = rset.getObject(1);
      if (idValue != null) {
        persistRequest.setGeneratedKey(idValue);
      }
    } else if (persistRequest.insertOptions() == null) {
      // insert on conflict do nothing can not return generated key
      throw new PersistenceException("Autoincrement getGeneratedKeys() returned no rows?");
    }
  }

  /**
   * For non batch insert with DBs that do not support getGeneratedKeys. Use a
   * SQL select to fetch back the Id value.
   */
  private void fetchGeneratedKeyUsingSelect() throws SQLException {
    PreparedStatement stmt = null;
    ResultSet rset = null;
    try {
      stmt = transaction.connection().prepareStatement(persistRequest.selectLastInsertedId());
      rset = stmt.executeQuery();
      setGeneratedKey(rset);
    } finally {
      JdbcClose.close(rset);
      JdbcClose.close(stmt);
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy