/******************************************************************************* * * Copyright 2012-2015, the original author or authors. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obta a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package com.flipkart.aesop.mysqldatalayer.upsert; import com.flipkart.aesop.destinationoperation.JDBCDataLayer; import com.flipkart.aesop.destinationoperation.UpsertDestinationStoreProcessor; import com.flipkart.aesop.destinationoperation.utils.DataLayerConstants; import com.flipkart.aesop.event.AbstractEvent; import com.flipkart.aesop.mysqldatalayer.delete.MySQLDeleteDataLayer; import com.linkedin.databus.client.pub.ConsumerCallbackResult; import com.linkedin.databus.core.DbusOpcode; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import java.util.Map; import java.util.Set; /** * MySQL Upsert Data Layer. Persists {@link DbusOpcode#UPSERT} events to MySQL. * @author Prakhar Jain * @see MySQLDeleteDataLayer */ public class MySQLUpsertDataLayer extends UpsertDestinationStoreProcessor implements JDBCDataLayer { /** JDBC Template Map, with Namespace name as key and the corresponding JDBC template as value. */ private Map<String, NamedParameterJdbcTemplate> jdbcTemplateMap; /** * Field Constructor. * @param jdbcTemplateMap */ public MySQLUpsertDataLayer(Map<String, NamedParameterJdbcTemplate> jdbcTemplateMap) { this.jdbcTemplateMap = jdbcTemplateMap; } public Map<String, NamedParameterJdbcTemplate> getJdbcTemplateMap() { return jdbcTemplateMap; } @Override protected ConsumerCallbackResult upsert(AbstractEvent event) { String upsertQuery = generateUpsertQuery(event); NamedParameterJdbcTemplate jdbcTemplate = jdbcTemplateMap.get(event.getNamespaceName()); jdbcTemplate.update(upsertQuery, event.getFieldMapPair()); return ConsumerCallbackResult.SUCCESS; } /** * Generates Upsert Query using {@link #buildQuery(String, String, StringBuilder, StringBuilder, StringBuilder)} and * {@link #populateUpsertQueryParts(Map, Set, StringBuilder, StringBuilder, StringBuilder)} helper functions. * @param event * @return Upsert Query */ private String generateUpsertQuery(AbstractEvent event) { StringBuilder columnNameStringBuilder = new StringBuilder(); StringBuilder columnValueStringBuilder = new StringBuilder(); StringBuilder updateQueryStringBuilder = new StringBuilder(); populateUpsertQueryParts(event.getFieldMapPair(), event.getPrimaryKeySet(), columnNameStringBuilder, columnValueStringBuilder, updateQueryStringBuilder); return buildQuery(event.getNamespaceName(), event.getEntityName(), columnNameStringBuilder, columnValueStringBuilder, updateQueryStringBuilder); } /** * Helper Function for {@link #generateUpsertQuery(AbstractEvent)}. * @param fieldMap * @param primaryKeySet * @param columnNameStringBuilder * @param columnValueStringBuilder * @param updateQueryStringBuilder */ private void populateUpsertQueryParts(Map<String, Object> fieldMap, Set<String> primaryKeySet, StringBuilder columnNameStringBuilder, StringBuilder columnValueStringBuilder, StringBuilder updateQueryStringBuilder) { for (String field : fieldMap.keySet()) { columnNameStringBuilder.append(field + DataLayerConstants.COMMA); columnValueStringBuilder.append(DataLayerConstants.COLON + field + DataLayerConstants.COMMA); if (!primaryKeySet.contains(field)) { updateQueryStringBuilder.append(field + DataLayerConstants.EQUALTO_AND_COLON + field + ","); } } } /** * Helper Function for {@link #generateUpsertQuery(AbstractEvent)}. * @param namespace * @param entity * @param columnNameStringBuilder * @param columnValueStringBuilder * @param updateQueryStringBuilder * @return Upsert Query */ private String buildQuery(String namespace, String entity, StringBuilder columnNameStringBuilder, StringBuilder columnValueStringBuilder, StringBuilder updateQueryStringBuilder) { StringBuilder query = new StringBuilder(); query.append("INSERT INTO "); query.append(namespace + "." + entity + " ("); query.append(columnNameStringBuilder.substring(0, columnNameStringBuilder.length() - 1)); query.append(") VALUES("); query.append(columnValueStringBuilder.substring(0, columnValueStringBuilder.length() - 1)); query.append(") ON DUPLICATE KEY UPDATE "); query.append(updateQueryStringBuilder.substring(0, updateQueryStringBuilder.length() - 1)); return query.toString(); } }