package com.ctrip.platform.dal.dao.task;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import com.ctrip.platform.dal.dao.DalHints;
import com.ctrip.platform.dal.dao.StatementParameters;
import com.ctrip.platform.dal.dao.UpdatableEntity;
import com.ctrip.platform.dal.exceptions.DalException;
import com.ctrip.platform.dal.exceptions.ErrorCode;
public class SingleUpdateTask<T> extends TaskAdapter<T> implements SingleTask<T> {
public static final String TMPL_SQL_UPDATE = "UPDATE %s SET %s WHERE %s";
@Override
public int execute(DalHints hints, Map<String, ?> fields, T rawPojo) throws SQLException {
if (fields.size() == 0)
throw new DalException(ErrorCode.ValidateFieldCount);
Map<String, ?> pks = getPrimaryKeys(fields);
Object version = getVersion(fields);
Map<String, ?> filted = null;
if(rawPojo instanceof UpdatableEntity)
filted = filterUpdatableEntity(hints, fields, getUpdatedColumns(rawPojo));
else
filted = filterNullColumns(hints, fields);
// If there is no columns changed, we will not perform update
if(filted.size() == 0)
return 0;
String updateSql = buildUpdateSql(getTableName(hints, fields), filted, hints);
StatementParameters parameters = new StatementParameters();
addParameters(parameters, filted);
addParameters(parameters, pks);
addVersion(parameters, version);
return client.update(updateSql, parameters, hints.setFields(fields));
}
private Object getVersion(Map<String, ?> fields) throws DalException {
if(!hasVersion)
return null;
Object version = fields.get(parser.getVersionColumn());
if(version == null)
throw new DalException(ErrorCode.ValidateVersion);
return version;
}
private Map<String, ?> filterNullColumns(DalHints hints, Map<String, ?> fields) throws DalException {
Map<String, Object> filted = new LinkedHashMap<>();
Set<String> updatableColumns = filterColumns(hints);
// Remove null value when hints is not DalHintEnum.updateNullField or
// primary key or not updatable
for (String column : parser.getColumnNames()) {
if ((fields.get(column) == null && !hints.isUpdateNullField())
|| isPrimaryKey(column) || !updatableColumns.contains(column))
continue;
filted.put(column, fields.get(column));
}
return filted;
}
private Map<String, ?> filterUpdatableEntity(DalHints hints, Map<String, ?> fields, Set<String> updatedColumns) throws DalException {
Map<String, Object> filted = new LinkedHashMap<>();
Set<String> updatableColumns = filterColumns(hints);
// Dirty flag is not set but need to update
// primary key or not updatable
for (String column : parser.getColumnNames()) {
if (!updatedColumns.contains(column) && !hints.isUpdateUnchangedField() ||
isPrimaryKey(column) || !updatableColumns.contains(column))
continue;
filted.put(column, fields.get(column));
}
return filted;
}
private String buildUpdateSql(String tableName, Map<String, ?> fields, DalHints hints) {
String columns = String.format(
combine(TMPL_SET_VALUE, fields.size(), COLUMN_SEPARATOR),
quote(fields.keySet()));
if(isVersionUpdatable)
columns += COLUMN_SEPARATOR + setVersionValueTmpl;
return String.format(TMPL_SQL_UPDATE, tableName, columns, updateCriteriaTmpl);
}
private void addVersion(StatementParameters parameters, Object version) throws DalException {
if(!hasVersion)
return;
addParameter(parameters, parameters.size() + 1, parser.getVersionColumn(), version);
}
}