package com.xavient.dip.storm.bolt; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.xavient.dip.storm.utils.DataSourceFactory; import backtype.storm.task.OutputCollector; import backtype.storm.task.TopologyContext; import backtype.storm.topology.OutputFieldsDeclarer; import backtype.storm.tuple.Tuple; public class MySQLDataWriterBolt extends DataIngestionBolt { private static final long serialVersionUID = 1552882008838885198L; private static final Logger LOG = LoggerFactory.getLogger(MySQLDataWriterBolt.class); private QueryRunner queryRunner; @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) { super.prepare(stormConf, context, collector); this.batchSize = Math.min(100, rankMaxThreshold); queryRunner = new QueryRunner( DataSourceFactory.getDataSource((Map<String, String>) stormConf.get("dbProperties"))); } @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { } @Override protected void finishBatch() { List<Tuple> tuples = new ArrayList<Tuple>(); queue.drainTo(tuples); try { if (CollectionUtils.isNotEmpty(tuples)) { int t = 0; List<String> fields = getFileds(tuples.get(0)); Object[][] data = new Object[tuples.size()][]; for (Tuple tuple : tuples) { Object[] value = new Object[] { tuple.getValueByField(fields.get(0)), tuple.getValueByField(fields.get(1)), tuple.getValueByField(fields.get(1)) }; data[t] = value; t++; } queryRunner.batch(buildQuery(tuples.get(0).getStringByField("tableName"), fields), data); } } catch (Exception e) { LOG.error("Exception occurred while executing query", e); } } private List<String> getFileds(Tuple tuple) { List<String> fields = new ArrayList<>(); Iterator<String> itr = tuple.getFields().iterator(); while (itr.hasNext()) { String field = itr.next(); if (!"tableName".equals(field)) fields.add(field); } return fields; } private static String buildQuery(String tableName, List<String> fields) { StringBuilder builder = new StringBuilder(); builder.append("INSERT INTO "); builder.append(tableName); builder.append(" ("); for (String field : fields) { builder.append(field); builder.append(","); } builder = new StringBuilder(StringUtils.removeEnd(builder.toString(), ",")); builder.append(") "); builder.append(" VALUES "); builder.append(" ("); for (int i = 0; i < fields.size(); i++) { builder.append(" ?,"); } builder = new StringBuilder(StringUtils.removeEnd(builder.toString(), ",")); builder.append(") "); builder.append(" ON DUPLICATE KEY UPDATE "); builder.append(fields.get(1)); builder.append("="); if ("tweets_location".equals(tableName)) { builder.append(fields.get(1)); builder.append("+"); } builder.append(" ?"); return builder.toString(); } }