spark操作数据库的几种方法
一.使用jdbcRDD的接口:
SparkConf conf = new SparkConf();
conf.setAppName("Simple Application").setMaster("local");
JavaSparkContext jsc = new JavaSparkContext(conf); //1.直接使用jdbcRDD的构造函数
class DbConnection extends AbstractFunction0<Connection> implements
Serializable {
private static final long serialVersionUID = 1L;
private String driverClassName;
private String connectionUrl;
private String userName;
private String password; public DbConnection(String driverClassName, String connectionUrl,
String userName, String password) {
this.driverClassName = driverClassName;
this.connectionUrl = connectionUrl;
this.userName = userName;
this.password = password;
} @Override
public Connection apply() {
try {
Class.forName(driverClassName);
} catch (ClassNotFoundException e) {
}
Properties properties = new Properties();
properties.setProperty("user", userName);
properties.setProperty("password", password);
Connection connection = null;
try {
connection = DriverManager.getConnection(connectionUrl,
properties);
} catch (SQLException e) {
}
return connection;
}
} class MapResult extends AbstractFunction1<ResultSet, Object[]>
implements Serializable {
private static final long serialVersionUID = 1L; public Object[] apply(ResultSet row) {
return JdbcRDD.resultSetToObjectArray(row);
}
} String Connection_url = "jdbc:mysql://ip:port/dbname?useUnicode=true&characterEncoding=utf8";
String Driver="com.mysql.jdbc.Driver";
String UserName = "root";
String password = "pd";
DbConnection dbConnection = new DbConnection(Driver,
Connection_url, UserName, password);
sql = "select * from (" + sql + ") as tmp where 0=? and 0=?";
//lowerBound,upperBound均设置0,where条件就为恒真,这个是个处理技巧
JdbcRDD<Object[]> jdbcRDD = new JdbcRDD<>(jsc.sc(), dbConnection,
sql, , , , new MapResult(),
ClassManifestFactory$.MODULE$.fromClass(Object[].class));
JavaRDD<Object[]> javaRDD = JavaRDD.fromRDD(jdbcRDD,
ClassManifestFactory$.MODULE$.fromClass(Object[].class)); //另外一种实现:
class DbConnectionFactory implements JdbcRDD.ConnectionFactory {
private static final long serialVersionUID = 1L;
private String driverClassName;
private String connectionUrl;
private String userName;
private String password; public Connection getConnection() throws Exception {
Class.forName(driverClassName);
String url = connectionUrl;
Properties properties = new Properties();
properties.setProperty("user", userName);
properties.setProperty("password", password);
return DriverManager.getConnection(url, properties);
} public DbConnectionFactory(String driverClassName, String connectionUrl,
String userName, String password) {
this.driverClassName = driverClassName;
this.connectionUrl = connectionUrl;
this.userName = userName;
this.password = password;
} } String Connection_url = "jdbc:mysql://ip:port/dbname?useUnicode=true&characterEncoding=utf8";
sql = "select * from (" + sql + ") as tmp where 0=? and 0=?";
DbConnectionFactory ConnectFactory = new DbConnectionFactory(Driver,
Connection_url, UserName, password)
javaRDD = JdbcRDD.create(jsc, new DbConnectionFactory(Driver,
Connection_url, UserName, password), sql, , , ,new Function<ResultSet,Object[]>()
{
private static final long serialVersionUID = 1L;
public Object[] call(ResultSet resultSet)
{
return JdbcRDD.resultSetToObjectArray(resultSet);
}
});//直接返回JavaRDD<Object[]>,这个底层调用的是JdbcRDD(SparkContext sc, Function0<Connection> getConnection, String sql, long lowerBound, long upperBound, int numPartitions, Function1<ResultSet, T> mapRow, ClassTag<T> evidence$1)
//javaRDD =JdbcRDD.create(jsc, ConnectFactory, sql, 0, 0, 1);//该方法更加简洁,底层调用上面的create(JavaSparkContext paramJavaSparkContext, ConnectionFactory paramConnectionFactory, String paramString, long paramLong1, long paramLong2, int paramInt, Function<ResultSet, T> paramFunction)
二.使用通过sparksession的接口:
SparkSession ss = SparkSession.builder().config(conf).enableHiveSupport().getOrCreate()
//读取方式1
String sql = "(select * from xxx) as tmp; //注意这里的sql格式,该sql也可以直接是一个表名
Dataset<Row> df = session.read().format("jdbc")
.option("url", jdbcURL)
.option("driver", driver)
.option("dbtable", sql)
.option("user", username)
.option("password", password)
.load();
//读取方式2:
Properties connectionProperties = new Properties();
connectionProperties.put("user", username);
connectionProperties.put("password", password);
connectionProperties.put("driver", driver);
session.read().jdbc(url, table, properties)
df = session.read().jdbc(jdbcURL,sql,connectionProperties); //写入方式1:
String saveMode = "Overwrite";
df.write().mode(saveMode).jdbc(jdbcURL, tablename, connectionProperties);
//写入方式2:
final String sql = "insert into tab_xxx (c1,c2,c3) values(?,?,?)"; df.javaRDD().foreachPartition(new VoidFunction<Iterator<Row>>() {
private static final long serialVersionUID = -834520661839866305L;
@Override
public void call(Iterator<Row> t) throws Exception {
Class.forName(driver);
Connection conn = (Connection) DriverManager.getConnection(url, username, password);
conn.setAutoCommit(false);
try {
PreparedStatement pstmt = (PreparedStatement) conn.prepareStatement(sql);
int loop = ;
while (t.hasNext()) {
Row row = t.next();
for (int i = ; i < ; i++) { //这里的3是插入的列只有3列
pstmt.setObject(i + , row.get(i));
}
pstmt.executeUpdate();
if (++loop % == ) {
conn.commit();
}
}
conn.commit();
pstmt.close();
} finally {
conn.close();
}
}
});
}
//写入方法3
3.转换成List<Row>,可以批量写入,但是有可能导致Driver 内存承载过高 private static void InsertTmpTable(Connection conn,Dataset<Row> ndf,final String m_cols,final String tabname) {
System.out.println("InsertTmpTab "+tabname+" start!");
String placeholderStr="values(";
int cnt = m_cols.split(",").length+1;
for(int i = 0;i<cnt;i++){
placeholderStr+="?"+ (i == cnt-1 ? ")" : ",");
} String sql = "insert into "+ tabname+"("+m_cols+",orderby_time)"+placeholderStr;
PreparedStatement pstmt = null; try {
List<Row> lrow=ndf.collectAsList();
pstmt = (PreparedStatement) conn.prepareStatement(sql); for(int j =0;j<lrow.size();j++){
for(int i=0;i<cnt;i++){
pstmt.setObject(i+1,lrow.get(j).get(i));
}
pstmt.executeUpdate();
if(j%10000==0) //批量提交
conn.commit();
}
conn.commit();
pstmt.close();
}catch (Exception e){
System.out.println(e.getMessage());
System.exit(-1);
}
System.out.println("InsertTmpTab "+tabname+" success!");
}
spark操作数据库的几种方法的更多相关文章
- Yii操作数据库的3种方法
一.执行原生太SQL的PDO方式. 复制代码代码如下: $sql = "";//原生态sql语句 xx::model()->dbConnection->createCo ...
- 将Excel数据导入mysql数据库的几种方法
将Excel数据导入mysql数据库的几种方法 “我的面试感悟”有奖征文大赛结果揭晓! 前几天需要将Excel表格中的数据导入到mysql数据库中,在网上查了半天,研究了半天,总结出以下几种方法,下面 ...
- python更新数据库脚本两种方法
最近项目的两次版本迭代中,根据业务需求的变化,需要对数据库进行更新,两次分别使用了不同的方式进行更新. 第一种:使用python的MySQLdb模块利用原生的sql语句进行更新 import MySQ ...
- Shell脚本中执行sql语句操作mysql的5种方法【转】
对于自动化运维,诸如备份恢复之类的,DBA经常需要将SQL语句封装到shell脚本.本文描述了在Linux环境下mysql数据库中,shell脚本下调用sql语句的几种方法,供大家参考.对于脚本输出的 ...
- C++连接mysql数据库的两种方法
本文主要介绍了C++连接mysql数据库的两种方法,希望通过本文,能对你有所帮助,一起来看. 现在正做一个接口,通过不同的连接字符串操作不同的数据库.要用到mysql数据库,以前没用过这个数据库,用a ...
- python更新数据库脚本三种方法
最近项目的两次版本迭代中,根据业务需求的变化,需要对数据库进行更新,两次分别使用了不同的方式进行更新. 第一种:使用python的MySQLdb模块利用原生的sql语句进行更新 import MySQ ...
- Yii框架操作数据库的几种方式与mysql_escape_string
一.Yii操作数据库的几种选择 1,PDO方式. $sql = "";//原生态sql语句 xx::model()->dbConnection->createComma ...
- 【Python】python更新数据库脚本两种方法
最近项目的两次版本迭代中,根据业务需求的变化,需要对数据库进行更新,两次分别使用了不同的方式进行更新. 第一种:使用python的MySQLdb模块利用原生的sql语句进行更新 1 import ...
- Linux 下操作GPIO(两种方法,驱动和mmap)(转载)
目前我所知道的在Linux下操作GPIO有两种方法: 1.编写驱动,这当然要熟悉Linux下驱动的编写方法和技巧,在驱动里可以使用ioremap函数获得GPIO物理基地址指针,然后使用这个指针根据io ...
随机推荐
- ConcurrentHashMap 中putIfAbsent 和put的区别
putIfAbsent 源代码 public V putIfAbsent(K key, V value) { Segment<K,V> s; if (value == null) thro ...
- AWS backup
shadowsocks ssserver -c /etc/shadowsocks/config.json start/stop/reset
- IDEA 相关问题
IntelliJ Idea 常用快捷键列表 Alt+回车 导入包,自动修正Ctrl+N 查找类Ctrl+Shift+N 查找文件Ctrl+Alt+L 格式化代码 Ctrl+Alt+O 优化导 ...
- Knowledge Point 20180305 Java程序员详述编码Unicode
Unicode Unicode(统一码.万国码.单一码)是计算机科学领域里的一项业界标准,包括字符集.编码方案等.Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设 ...
- 四种常见的 POST 提交数据方式对应的content-type
原文地址:https://www.cnblogs.com/wushifeng/p/6707248.html application/x-www-form-urlencoded 这应该是最常见的 POS ...
- Handshake Lemma
- finite undirected gragh ∑deg(v) = 2|E| In a k-ary tree where every node has either 0 or k children ...
- vue的$emit 与$on父子组件与兄弟组件的之间通信
本文主要对vue 用$emit 与 $on 来进行组件之间的数据传输. 主要的传输方式有三种: 1.父组件到子组件通信 2.子组件到父组件的通信 3.兄弟组件之间的通信 一.父组件传值给子组件 父组件 ...
- tp5.1路由报错No input file specified.
问题: 按照官方教安装了框架,打开首页没问题,可是安装教程路由规则打开 "http://127.0.0.1/hello/2" 时, 却报错误 "No input fil ...
- hadoop生态搭建(3节点)-09.flume配置
# http://archive.apache.org/dist/flume/1.8.0/# ===================================================== ...
- Hadoop原理之——HDFS原理
Hadoop 3个核心组件: 分布式文件系统:Hdfs——实现将文件分布式存储在很多的服务器上(hdfs是一个基于Linux本地文件系统上的文件系统) 分布式运算编程框架:Mapreduce——实现在 ...