重写JdbcRDD支持Sql命名参数和分区
Spark提供的JdbcRDD很不好用,没法指定命名参数,而且必须要提供两个Long类型的参数表示分区的范围,如果数据表没有long类型的字段或者不需要条件,那就不能用JdbcRDD了。这里我简单重写了一个GenericJdbcRDD,支持命名参数和分区,仅仅作为参考哦。
项目结构如下:
GenericJdbcRDD.scala
package yay.jdbc.rdd import java.sql.{Connection, ResultSet} import org.apache.spark.annotation.DeveloperApi
import org.apache.spark.rdd.{JdbcRDD, RDD}
import org.apache.spark.{Logging, Partition, SparkContext, TaskContext} import scala.reflect.ClassTag /**
* Created by ${yuananyun} on 2015/2/7.
*/
private[yay] class JdbcPartition(idx: Int, val lower: Long, val upper: Long) extends Partition {
override def index = idx
} class GenericJdbcRDD[T: ClassTag](
sc: SparkContext,
getConnection: () => Connection,
sql: String,
paramsMap: Map[String, Object],
skip: Long,
take: Long,
numPartitions: Int,
mapRow: (ResultSet) => T = JdbcRDD.resultSetToObjectArray _) extends RDD[T](sc, Nil) with Logging {
@DeveloperApi
override def compute(thePart: Partition, context: TaskContext) = new JdbcNextIterator[T] {
context.addTaskCompletionListener { context => closeIfNeeded()}
val part = thePart.asInstanceOf[JdbcPartition]
val conn = getConnection()
// val stmt = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)
var parsedSql = ""
if (conn.getMetaData.getURL.matches("jdbc:mysql:.*")) {
parsedSql = sql+" limit "+ part.lower+","+ part.upper
} val stmt = new NamedParameterStatement(conn, parsedSql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY) // setFetchSize(Integer.MIN_VALUE) is a mysql driver specific way to force streaming results,
// rather than pulling entire resultset into memory.
// see http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-implementation-notes.html
if (conn.getMetaData.getURL.matches("jdbc:mysql:.*")) {
stmt.setFetchSize(Integer.MIN_VALUE)
logInfo("statement fetch size set to: " + stmt.getFetchSize + " to force MySQL streaming ")
}
if (paramsMap != null && paramsMap.size > 0) {
val paramsIter = paramsMap.iterator
while (paramsIter.hasNext) {
val (key, value) = paramsIter.next()
stmt.setObject(key, value)
}
}
val rs = stmt.executeQuery() override def getNext: T = {
if (rs.next()) {
mapRow(rs)
} else {
finished = true
null.asInstanceOf[T]
}
} override def close() {
try {
if (null != rs && !rs.isClosed()) {
rs.close()
}
} catch {
case e: Exception => logWarning("Exception closing resultset", e)
}
try {
if (null != stmt && !stmt.isClosed()) {
stmt.close()
}
} catch {
case e: Exception => logWarning("Exception closing statement", e)
}
try {
if (null != conn && !conn.isClosed()) {
conn.close()
}
logInfo("closed connection")
} catch {
case e: Exception => logWarning("Exception closing connection", e)
}
}
} override protected def getPartitions: Array[Partition] = {
take > 0 match {
case false => throw new IllegalArgumentException("take 参数不能小于0")
case _ => {
val step = take / numPartitions
(0 until numPartitions).map(i => {
val start = (skip + i * step)
val end = start + step
new JdbcPartition(i, start, end)
}).toArray
}
}
} }
JdbcNextIterator.scala
package yay.jdbc.rdd /**
* Created by ${yuananyun} on 2015/2/8.
*/
abstract private[yay] class JdbcNextIterator[U] extends Iterator[U] {
private var gotNext = false
private var nextValue: U = _
private var closed = false
protected var finished = false /**
* Method for subclasses to implement to provide the next element.
*
* If no next element is available, the subclass should set `finished`
* to `true` and may return any value (it will be ignored).
*
* This convention is required because `null` may be a valid value,
* and using `Option` seems like it might create unnecessary Some/None
* instances, given some iterators might be called in a tight loop.
*
* @return U, or set 'finished' when done
*/
protected def getNext(): U /**
* Method for subclasses to implement when all elements have been successfully
* iterated, and the iteration is done.
*
* <b>Note:</b> `NextIterator` cannot guarantee that `close` will be
* called because it has no control over what happens when an exception
* happens in the user code that is calling hasNext/next.
*
* Ideally you should have another try/catch, as in HadoopRDD, that
* ensures any resources are closed should iteration fail.
*/
protected def close() /**
* Calls the subclass-defined close method, but only once.
*
* Usually calling `close` multiple times should be fine, but historically
* there have been issues with some InputFormats throwing exceptions.
*/
def closeIfNeeded() {
if (!closed) {
close()
closed = true
}
} override def hasNext: Boolean = {
if (!finished) {
if (!gotNext) {
nextValue = getNext()
if (finished) {
closeIfNeeded()
}
gotNext = true
}
}
!finished
} override def next(): U = {
if (!hasNext) {
throw new NoSuchElementException("End of stream")
}
gotNext = false
nextValue
}
}
NamedParameterStatement.java
package yay.jdbc.rdd; import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.*;
import java.sql.Date;
import java.util.*; /**
* This class wraps around a {@link PreparedStatement} and allows the programmer to set parameters by name instead
* of by index. This eliminates any confusion as to which parameter index represents what. This also means that
* rearranging the SQL statement or adding a parameter doesn't involve renumbering your indices.
* Code such as this:
* <p/>
* <pre><code>
* Connection conn = getConnection();
* String sql = "select * from my_table where name=? or address=?";
* PreparedStatement p = conn.prepareStatement(sql);
* p.setString(1, "bob");
* p.setString(2, "123");
* ResultSet rs = p.executeQuery();
* </code></pre>
* <p/>
* Can be replaced with:
* <p/>
* <pre><code>
* Connection conn = getConnection();
* String sql = "select * from my_table where name=:name or address=:address";
* NamedParameterStatement p = new NamedParameterStatement(conn, sql);
* p.setString("name", "bob");
* p.setString("address", "123");
* ResultSet rs = p.executeQuery();
* </code></pre>
*/
public class NamedParameterStatement extends PreparedStatementWrapper
{
private static final HashMap<String, Map<String, List<Integer>>> nameIndexCache = new HashMap<String, Map<String, List<Integer>>>();
private static final HashMap<String, String> parsedSqlCache = new HashMap<String, String>(); private final String parsedSql;
private final Map<String, List<Integer>> nameIndexMap; /**
* Creates a NamedParameterStatement. Wraps a call to
* c.{@link Connection#prepareStatement(java.lang.String) prepareStatement}.
*
* @param conn the database connection
* @param sql the parameterized sql
* @throws SQLException if the statement could not be created
*/
public NamedParameterStatement(Connection conn, String sql,int resultSetType,int resultSetConcurrency) throws SQLException
{
if (nameIndexCache.containsKey(sql))
{
nameIndexMap = nameIndexCache.get(sql);
parsedSql = parsedSqlCache.get(sql);
} else
{
nameIndexMap = new HashMap<String, List<Integer>>();
parsedSql = parseNamedSql(sql, nameIndexMap); nameIndexCache.put(sql, nameIndexMap);
parsedSqlCache.put(sql, parsedSql);
}
ps = conn.prepareStatement(parsedSql,resultSetType,resultSetConcurrency);
} /**
* Returns the indexes for a parameter.
*
* @param name parameter name
* @return parameter indexes
* @throws IllegalArgumentException if the parameter does not exist
*/
private List<Integer> getIndexes(String name)
{
List<Integer> indexes = nameIndexMap.get(name);
if (indexes == null)
{
throw new IllegalArgumentException("Parameter not found: " + name);
}
return indexes;
} /**
* Parses a sql with named parameters. The parameter-index mappings
* are put into the map, and the parsed sql is returned.
*
* @param sql sql with named parameters
* @return the parsed sql
*/
private static String parseNamedSql(String sql, Map<String, List<Integer>> nameIndexMap)
{
// I was originally using regular expressions, but they didn't work well for ignoring // parameter-like strings inside quotes.
int length = sql.length();
StringBuffer parsedSql = new StringBuffer(length);
boolean inSingleQuote = false;
boolean inDoubleQuote = false;
int index = 1;
for (int i = 0; i < length; i++)
{
char c = sql.charAt(i);
if (inSingleQuote)
{
if (c == '\'')
{
inSingleQuote = false;
}
} else if (inDoubleQuote)
{
if (c == '"')
{
inDoubleQuote = false;
}
} else
{
if (c == '\'')
{
inSingleQuote = true;
} else if (c == '"')
{
inDoubleQuote = true;
} else if (c == ':' && i + 1 < length && Character.isJavaIdentifierStart(sql.charAt(i + 1)))
{
int j = i + 2;
while (j < length && Character.isJavaIdentifierPart(sql.charAt(j)))
{
j++;
}
String name = sql.substring(i + 1, j);
c = '?'; // replace the parameter with a question mark
i += name.length(); // skip past the end if the parameter
List<Integer> indexList = nameIndexMap.get(name);
if (indexList == null)
{
indexList = new LinkedList<Integer>();
nameIndexMap.put(name, indexList);
}
indexList.add(index);
index++;
}
}
parsedSql.append(c);
} return parsedSql.toString();
} public void setArray(String name, Array value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setArray(index, value);
}
} public void setAsciiStream(String name, InputStream value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setAsciiStream(index, value);
}
} public void setAsciiStream(String name, InputStream value, int length) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setAsciiStream(index, value, length);
}
} public void setBigDecimal(String name, BigDecimal value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setBigDecimal(index, value);
}
} public void setBinaryStream(String name, InputStream value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setBinaryStream(index, value);
}
} public void setBinaryStream(String name, InputStream value, int length) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setBinaryStream(index, value, length);
}
} public void setBinaryStream(String name, InputStream value, long length) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setBinaryStream(index, value, length);
}
} public void setBlob(String name, Blob value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setBlob(index, value);
}
} public void setBlob(String name, InputStream value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setBlob(index, value);
}
} public void setBlob(String name, InputStream value, long length) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setBlob(index, value, length);
}
} public void setBoolean(String name, boolean value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setBoolean(index, value);
}
} public void setByte(String name, byte value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setByte(index, value);
}
} public void setBytes(String name, byte[] value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setBytes(index, value);
}
} public void setCharacterStream(String name, Reader value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setCharacterStream(index, value);
}
} public void setCharacterStream(String name, Reader value, int length) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setCharacterStream(index, value, length);
}
} public void setCharacterStream(String name, Reader value, long length) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setCharacterStream(index, value, length);
}
} public void setClob(String name, Clob value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setClob(index, value);
}
} public void setClob(String name, Reader value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setClob(index, value);
}
} public void setClob(String name, Reader value, long length) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setClob(index, value, length);
}
} public void setDate(String name, Date value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setDate(index, value);
}
} public void setDate(String name, Date value, Calendar cal) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setDate(index, value, cal);
}
} public void setDouble(String name, double value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setDouble(index, value);
}
} public void setFloat(String name, float value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setFloat(index, value);
}
} public void setInt(String name, int value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setInt(index, value);
}
} public void setLong(String name, long value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setLong(index, value);
}
} public void setNCharacterStream(String name, Reader value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setNCharacterStream(index, value);
}
} public void setNCharacterStream(String name, Reader value, long length) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setNCharacterStream(index, value, length);
}
} public void setNClob(String name, NClob value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setNClob(index, value);
}
} public void setNClob(String name, Reader value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setNClob(index, value);
}
} public void setNClob(String name, Reader value, long length) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setNClob(index, value, length);
}
} public void setNString(String name, String value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setNString(index, value);
}
} public void setNull(String name, int sqlType) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setNull(index, sqlType);
}
} public void setObject(String name, Object value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setObject(index, value);
}
} public void setObject(String name, Object value, int targetSqlType) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setObject(index, value, targetSqlType);
}
} public void setObject(String name, Object value, int targetSqlType, int scaleOrLength) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setObject(index, value, targetSqlType, scaleOrLength);
}
} public void setRef(String name, Ref value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setRef(index, value);
}
} public void setRowId(String name, RowId value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setRowId(index, value);
}
} public void setShort(String name, short value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setShort(index, value);
}
} public void setSQLXML(String name, SQLXML value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setSQLXML(index, value);
}
} public void setString(String name, String value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setString(index, value);
}
} public void setTime(String name, Time value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setTime(index, value);
}
} public void setTime(String name, Time value, Calendar cal) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setTime(index, value, cal);
}
} public void setTimestamp(String name, Timestamp value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setTimestamp(index, value);
}
} public void setTimestamp(String name, Timestamp value, Calendar cal) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setTimestamp(index, value, cal);
}
} @SuppressWarnings("deprecation")
public void setUnicodeStream(String name, InputStream value, int length) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setUnicodeStream(index, value, length);
}
} public void setURL(String name, URL value) throws SQLException
{
for (Integer index : getIndexes(name))
{
ps.setURL(index, value);
}
} }
PreparedStatementWrapper.java
package yay.jdbc.rdd; import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.*;
import java.util.Calendar; public class PreparedStatementWrapper implements PreparedStatement
{
protected PreparedStatement ps; @Override
public <T> T unwrap(Class<T> iface) throws SQLException
{
return ps.unwrap(iface);
} @Override
public ResultSet executeQuery(String sql) throws SQLException
{
return ps.executeQuery(sql);
} @Override
public ResultSet executeQuery() throws SQLException
{
return ps.executeQuery();
} @Override
public boolean isWrapperFor(Class<?> iface) throws SQLException
{
return ps.isWrapperFor(iface);
} @Override
public int executeUpdate(String sql) throws SQLException
{
return ps.executeUpdate(sql);
} @Override
public int executeUpdate() throws SQLException
{
return ps.executeUpdate();
} @Override
public void setNull(int parameterIndex, int sqlType) throws SQLException
{
ps.setNull(parameterIndex, sqlType);
} @Override
public void close() throws SQLException
{
ps.close();
} @Override
public int getMaxFieldSize() throws SQLException
{
return ps.getMaxFieldSize();
} @Override
public void setBoolean(int parameterIndex, boolean x) throws SQLException
{
ps.setBoolean(parameterIndex, x);
} @Override
public void setByte(int parameterIndex, byte x) throws SQLException
{
ps.setByte(parameterIndex, x);
} @Override
public void setMaxFieldSize(int max) throws SQLException
{
ps.setMaxFieldSize(max);
} @Override
public void setShort(int parameterIndex, short x) throws SQLException
{
ps.setShort(parameterIndex, x);
} @Override
public int getMaxRows() throws SQLException
{
return ps.getMaxRows();
} @Override
public void setInt(int parameterIndex, int x) throws SQLException
{
ps.setInt(parameterIndex, x);
} @Override
public void setMaxRows(int max) throws SQLException
{
ps.setMaxRows(max);
} @Override
public void setLong(int parameterIndex, long x) throws SQLException
{
ps.setLong(parameterIndex, x);
} @Override
public void setEscapeProcessing(boolean enable) throws SQLException
{
ps.setEscapeProcessing(enable);
} @Override
public void setFloat(int parameterIndex, float x) throws SQLException
{
ps.setFloat(parameterIndex, x);
} @Override
public void setDouble(int parameterIndex, double x) throws SQLException
{
ps.setDouble(parameterIndex, x);
} @Override
public int getQueryTimeout() throws SQLException
{
return ps.getQueryTimeout();
} @Override
public void setQueryTimeout(int seconds) throws SQLException
{
ps.setQueryTimeout(seconds);
} @Override
public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException
{
ps.setBigDecimal(parameterIndex, x);
} @Override
public void setString(int parameterIndex, String x) throws SQLException
{
ps.setString(parameterIndex, x);
} @Override
public void setBytes(int parameterIndex, byte[] x) throws SQLException
{
ps.setBytes(parameterIndex, x);
} @Override
public void cancel() throws SQLException
{
ps.cancel();
} @Override
public SQLWarning getWarnings() throws SQLException
{
return ps.getWarnings();
} @Override
public void setDate(int parameterIndex, Date x) throws SQLException
{
ps.setDate(parameterIndex, x);
} @Override
public void setTime(int parameterIndex, Time x) throws SQLException
{
ps.setTime(parameterIndex, x);
} @Override
public void clearWarnings() throws SQLException
{
ps.clearWarnings();
} @Override
public void setCursorName(String name) throws SQLException
{
ps.setCursorName(name);
} @Override
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
{
ps.setTimestamp(parameterIndex, x);
} @Override
public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException
{
ps.setAsciiStream(parameterIndex, x, length);
} @Override
public boolean execute(String sql) throws SQLException
{
return ps.execute(sql);
} @Override
@SuppressWarnings("deprecation")
public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException
{
ps.setUnicodeStream(parameterIndex, x, length);
} @Override
public ResultSet getResultSet() throws SQLException
{
return ps.getResultSet();
} @Override
public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException
{
ps.setBinaryStream(parameterIndex, x, length);
} @Override
public int getUpdateCount() throws SQLException
{
return ps.getUpdateCount();
} @Override
public boolean getMoreResults() throws SQLException
{
return ps.getMoreResults();
} @Override
public void clearParameters() throws SQLException
{
ps.clearParameters();
} @Override
public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException
{
ps.setObject(parameterIndex, x, targetSqlType);
} @Override
public void setFetchDirection(int direction) throws SQLException
{
ps.setFetchDirection(direction);
} @Override
public int getFetchDirection() throws SQLException
{
return ps.getFetchDirection();
} @Override
public void setObject(int parameterIndex, Object x) throws SQLException
{
ps.setObject(parameterIndex, x);
} @Override
public void setFetchSize(int rows) throws SQLException
{
ps.setFetchSize(rows);
} @Override
public int getFetchSize() throws SQLException
{
return ps.getFetchSize();
} @Override
public int getResultSetConcurrency() throws SQLException
{
return ps.getResultSetConcurrency();
} @Override
public boolean execute() throws SQLException
{
return ps.execute();
} @Override
public int getResultSetType() throws SQLException
{
return ps.getResultSetType();
} @Override
public void addBatch(String sql) throws SQLException
{
ps.addBatch(sql);
} @Override
public void clearBatch() throws SQLException
{
ps.clearBatch();
} @Override
public void addBatch() throws SQLException
{
ps.addBatch();
} @Override
public int[] executeBatch() throws SQLException
{
return ps.executeBatch();
} @Override
public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException
{
ps.setCharacterStream(parameterIndex, reader, length);
} @Override
public void setRef(int parameterIndex, Ref x) throws SQLException
{
ps.setRef(parameterIndex, x);
} @Override
public void setBlob(int parameterIndex, Blob x) throws SQLException
{
ps.setBlob(parameterIndex, x);
} @Override
public void setClob(int parameterIndex, Clob x) throws SQLException
{
ps.setClob(parameterIndex, x);
} @Override
public Connection getConnection() throws SQLException
{
return ps.getConnection();
} @Override
public void setArray(int parameterIndex, Array x) throws SQLException
{
ps.setArray(parameterIndex, x);
} @Override
public ResultSetMetaData getMetaData() throws SQLException
{
return ps.getMetaData();
} @Override
public boolean getMoreResults(int current) throws SQLException
{
return ps.getMoreResults(current);
} @Override
public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException
{
ps.setDate(parameterIndex, x, cal);
} @Override
public ResultSet getGeneratedKeys() throws SQLException
{
return ps.getGeneratedKeys();
} @Override
public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException
{
ps.setTime(parameterIndex, x, cal);
} @Override
public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException
{
return ps.executeUpdate(sql, autoGeneratedKeys);
} @Override
public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException
{
ps.setTimestamp(parameterIndex, x, cal);
} @Override
public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException
{
ps.setNull(parameterIndex, sqlType, typeName);
} @Override
public int executeUpdate(String sql, int[] columnIndexes) throws SQLException
{
return ps.executeUpdate(sql, columnIndexes);
} @Override
public void setURL(int parameterIndex, URL x) throws SQLException
{
ps.setURL(parameterIndex, x);
} @Override
public int executeUpdate(String sql, String[] columnNames) throws SQLException
{
return ps.executeUpdate(sql, columnNames);
} @Override
public ParameterMetaData getParameterMetaData() throws SQLException
{
return ps.getParameterMetaData();
} @Override
public void setRowId(int parameterIndex, RowId x) throws SQLException
{
ps.setRowId(parameterIndex, x);
} @Override
public void setNString(int parameterIndex, String value) throws SQLException
{
ps.setNString(parameterIndex, value);
} @Override
public boolean execute(String sql, int autoGeneratedKeys) throws SQLException
{
return ps.execute(sql, autoGeneratedKeys);
} @Override
public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException
{
ps.setNCharacterStream(parameterIndex, value, length);
} @Override
public void setNClob(int parameterIndex, NClob value) throws SQLException
{
ps.setNClob(parameterIndex, value);
} @Override
public void setClob(int parameterIndex, Reader reader, long length) throws SQLException
{
ps.setClob(parameterIndex, reader, length);
} @Override
public boolean execute(String sql, int[] columnIndexes) throws SQLException
{
return ps.execute(sql, columnIndexes);
} @Override
public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException
{
ps.setBlob(parameterIndex, inputStream, length);
} @Override
public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException
{
ps.setNClob(parameterIndex, reader, length);
} @Override
public boolean execute(String sql, String[] columnNames) throws SQLException
{
return ps.execute(sql, columnNames);
} @Override
public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException
{
ps.setSQLXML(parameterIndex, xmlObject);
} @Override
public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException
{
ps.setObject(parameterIndex, x, targetSqlType, scaleOrLength);
} @Override
public int getResultSetHoldability() throws SQLException
{
return ps.getResultSetHoldability();
} @Override
public boolean isClosed() throws SQLException
{
return ps.isClosed();
} @Override
public void setPoolable(boolean poolable) throws SQLException
{
ps.setPoolable(poolable);
} @Override
public boolean isPoolable() throws SQLException
{
return ps.isPoolable();
} @Override
public void closeOnCompletion() throws SQLException
{
ps.closeOnCompletion();
} @Override
public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException
{
ps.setAsciiStream(parameterIndex, x, length);
} @Override
public boolean isCloseOnCompletion() throws SQLException
{
return ps.isCloseOnCompletion();
} @Override
public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException
{
ps.setBinaryStream(parameterIndex, x, length);
} @Override
public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException
{
ps.setCharacterStream(parameterIndex, reader, length);
} @Override
public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException
{
ps.setAsciiStream(parameterIndex, x);
} @Override
public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException
{
ps.setBinaryStream(parameterIndex, x);
} @Override
public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException
{
ps.setCharacterStream(parameterIndex, reader);
} @Override
public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException
{
ps.setNCharacterStream(parameterIndex, value);
} @Override
public void setClob(int parameterIndex, Reader reader) throws SQLException
{
ps.setClob(parameterIndex, reader);
} @Override
public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException
{
ps.setBlob(parameterIndex, inputStream);
} @Override
public void setNClob(int parameterIndex, Reader reader) throws SQLException
{
ps.setNClob(parameterIndex, reader);
} }
具体的用法:
object SparkToJDBC {
def main(args: Array[String]): Unit = {
val sc = new SparkContext("local", "mySql")
val paramsMap = Map[String, Object]("msgType" -> "99", "sendTime" -> "1419821878146")
val rdd = new GenericJdbcRDD(sc, () => {
Class.forName("com.mysql.jdbc.Driver").newInstance()
DriverManager.getConnection("jdbc:mysql://xxxxxxxx?characterEncoding=utf-8", "root", "xxxxx")
}, "SELECT * FROM emb_message where msg_type=:msgType and send_time>=:sendTime",
paramsMap, 0, 1000, 3, r => (r.getString(6),r.getString(11))) // rdd.foreach(x => println(x))
rdd.saveAsTextFile("c:\\temp\\test")
sc.stop()
} }
红色部分:其中paramsMap表示要传给sql的命名参数,0和1000分别表示skip和take,3表示生成的Rdd的partition数。
重写JdbcRDD支持Sql命名参数和分区的更多相关文章
- MyBatis映射文件2(不支持自增的数据库解决方案/参数处理[单参、多参、命名参数])
针对Oracle不支持自增的解决方案 Oracle不支持自增,但是它使用序列来模拟自增,每次插入数据的主键是从序列中拿到的值,那么如何获取这个值呢? <insert id="addEm ...
- java:Hibernate框架3(使用Myeclipse逆向工程生成实体和配置信息,hql语句各种查询(使用hibernate执行原生SQL语句,占位符和命名参数,封装Vo查询多个属性,聚合函数,链接查询,命名查询),Criteria)
1.使用Myeclipse逆向工程生成实体和配置信息: 步骤1:配置MyEclipse Database Explorer: 步骤2:为项目添加hibernate的依赖: 此处打开后,点击next进入 ...
- 用SqlParameter 给SQL传递参数
1.数据访问层 using的用法: 01.可以using System;导命名控空间 02.using 的语法结构 using(变量类型 变量名 =new 变量类型()) { } 案例: 03.us ...
- ibernate学习笔记5---实体类或属性名与数据库关键字冲突、hql命名参数、hql实现通用分页
一.实体类或属性名与数据库关键字冲突问题1.实体类名与数据库中的关键字冲突比如:实体表User与oracle中的系统表冲突解决方式1:在xml中添加table属性,指定表名,使其不与name默认相等 ...
- 使用命名参数处理 CallableStatement
简介:JDBC 中的语句处理 在 JDBC 应用程序中,JDBC 语句对象用于将 SQL 语句发送到数据库服务器.一个语句对象与一个连接相关联,应用程序与数据库服务器之间的通信由语句对象来处理. JD ...
- SQL Server 批量主分区备份(Multiple Jobs)
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 案例分析(Case) 方案一(Solution One) 方案二(Solution Two) ...
- SQL Server 批量主分区备份(One Job)
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 案例分析(Case) 实现代码(SQL Codes) 主分区完整.差异还原(Primary B ...
- Liferay中SQL打印参数
XX\tomcat-7.0.42\webapps\ROOT\WEB-INF\classes\log4j.properties log4j.rootLogger=INFO, CONSOLE log4 ...
- c# 方法参数(传值,传引用,ref,out,params,可选参数,命名参数)
一.方法参数的类型----值类型和引用类型 当方法传递的参数是值类型时,变量的栈数据会完整地复制到目标参数中即实参和形参中的数据相同但存放在内存的不同位置.所以,在目标方法中对形参所做的更改不会 ...
随机推荐
- Hadoop系列-HDFS基础
基本原理 HDFS(Hadoop Distributed File System)是Hadoop的一个基础的分布式文件系统,这个分布式的概念主要体现在两个地方: 数据分块存储在多台主机 数据块采取冗余 ...
- 嵌入式C语言自我修养 13:C语言习题测试
13.1 总结 前面12节的课程,主要针对 Linux 内核中 GNU C 扩展的一些常用 C 语言语法进行了分析.GNU C 的这些扩展语法,主要用来完善 C 语言标准和编译优化.而通过 C 标准的 ...
- Python学习——编程语言介绍
开发语言 高级语言:基于C/汇编等封装的语言,如Python.Java.C#.PHP.Go.ruby.C++……生成字节码让C/汇编去识别 低级语言:直接让计算机底层能识别成机器码的语言(计算机再将机 ...
- linux——nginx的安装及配置
目录 1. 在Linux上安装nginx 2. 配置nginx反向代理 1. 在Linux上安装ngix 1.1 在以下网页下载nginx的tar包,并将其传到linux中 http://nginx. ...
- 20155306 实验三 敏捷开发与XP实践
20155306 实验三 敏捷开发与XP实践 实验内容 XP基础 XP核心实践 相关工具 实验要求 1.没有Linux基础的同学建议先学习<Linux基础入门(新版)><Vim编辑器 ...
- 20145209刘一阳《JAVA程序设计》第一周课堂测试
第一周课堂测试 1.下列不属于Java后继技术的是(D) A .Android B .JSP C .XML D .Python 2.下列关于Java语言特点的描述,正确的一组是(C) A .面向过程: ...
- easyui -validatebox 验证框加载
问题: easyui验证狂框有时会验证输入字符的位数,或者验证有效字符组合 解决: 使用easyui的验证框,继承验证框,指定输入框为验证框即可 $(function(){ $.extend($.fn ...
- POJ1035_Spell checker_KEY
题目传送门 一道暴力可以过的水题.(直接暴力模拟的那种) 但是我打Trie练练模板,但是TMD因为数组开太小卡了好久. code: #include <cstdio> #include & ...
- Java——基于java自身包实现消息系统间的通信(TCP/IP+BIO)
最近看到阿里的一位童鞋写的一本关于分布式的书,感觉不错,准备把这本书上基础的代码都写一写. /** * Created by LiuHuiChao on 2016/11/15. * descripti ...
- Azkaban 工作流调度器
Azkaban 工作流调度器 1 概述 1.1 为什么需要工作流调度系统 a)一个完整的数据分析系统通常都是由大量任务单元组成,shell脚本程序,java程序,mapreduce程序.hive脚本等 ...