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

com.rapleaf.jack.queries.GenericUpdate Maven / Gradle / Ivy

There is a newer version: 1.8
Show newest version
package com.rapleaf.jack.queries;

import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.SQLRecoverableException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.rapleaf.jack.BaseDatabaseConnection;
import com.rapleaf.jack.util.JackUtility;

public class GenericUpdate extends AbstractExecution {
  private static final Logger LOG = LoggerFactory.getLogger(GenericUpdate.class);

  private final boolean allowBulkOperation;
  private final AbstractTable table;
  private final Map values;
  private final List whereConstraints;
  private final List whereParameters;

  private GenericUpdate(BaseDatabaseConnection dbConnection, boolean allowBulkOperation, AbstractTable table) {
    super(dbConnection);
    this.allowBulkOperation = allowBulkOperation;
    this.table = table;
    this.values = Maps.newLinkedHashMap();
    this.whereConstraints = Lists.newLinkedList();
    this.whereParameters = Lists.newLinkedList();
  }

  public static Builder create(BaseDatabaseConnection dbConnection, boolean allowBulkOperation) {
    return new Builder(dbConnection, allowBulkOperation);
  }

  public static class Builder {
    private final BaseDatabaseConnection dbConnection;
    private final boolean allowBulkOperation;

    public Builder(BaseDatabaseConnection dbConnection, boolean allowBulkOperation) {
      this.dbConnection = dbConnection;
      this.allowBulkOperation = allowBulkOperation;
    }

    public GenericUpdate table(AbstractTable table) {
      return new GenericUpdate(dbConnection, allowBulkOperation, table);
    }
  }

  public  GenericUpdate set(Column column, T value) {
    if (column.isDateColumn()) {
      String millisString = JackUtility.FORMATTER_FUNCTION_MAP.get(column.getType()).apply(Long.class.cast(value));
      this.values.put(column, millisString);
    } else {
      this.values.put(column, value);
    }
    return this;
  }

  public GenericUpdate where(GenericConstraint constraint, GenericConstraint... constraints) {
    this.whereConstraints.add(constraint);
    this.whereParameters.addAll(constraint.getParameters());
    for (GenericConstraint genericConstraint : constraints) {
      this.whereConstraints.add(genericConstraint);
      this.whereParameters.addAll(genericConstraint.getParameters());
    }
    return this;
  }

  public Updates execute() throws IOException {
    checkBulkOperation(allowBulkOperation, whereConstraints);

    int retryCount = 0;
    PreparedStatement preparedStatement = getPreparedStatement(Optional.empty());

    while (true) {
      try {
        return UpdateFetcher.getUpdateResults(preparedStatement, dbConnection);
      } catch (SQLRecoverableException e) {
        LOG.error(e.toString());
        if (++retryCount > MAX_CONNECTION_RETRIES) {
          throw new IOException(e);
        }
      } catch (SQLException e) {
        throw new IOException(e);
      }
    }
  }

  @Override
  public String getQueryStatement() {
    return getUpdateClause() +
        getSetClause() +
        getWhereClause();
  }

  private String getUpdateClause() {
    return "UPDATE " + table.getName() + " ";
  }

  private String getSetClause() {
    StringBuilder clause = new StringBuilder("SET ");

    Iterator> it = values.entrySet().iterator();
    while (it.hasNext()) {
      Map.Entry entry = it.next();
      clause.append(entry.getKey().getSqlKeyword()).append(" = ");
      if (entry.getValue() == null) {
        clause.append("NULL");
      } else {
        clause.append("?");
      }
      if (it.hasNext()) {
        clause.append(", ");
      }
    }

    return clause.append(" ").toString();
  }

  private String getWhereClause() {
    return getClauseFromQueryConditions(whereConstraints, "WHERE ", " AND ", " ");
  }

  @Override
  protected List getParameters() {
    List parameters = Lists.newLinkedList();
    parameters.addAll(values.values());
    parameters.addAll(whereParameters);
    return parameters;
  }
}