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 ...
随机推荐
- 聊聊c#与Python以及IronPython
简单说说这个意义.做了很久的c#,突然发现Python火了.就看看,估计这篇博文有点长,有点长,尽量包括主要的东西,还有点杂,浏览吧,选择自己喜欢的看看. 先看比较.网上一堆各种比较.但是主要比较语法 ...
- SASS实现代码的重用:混合器Mixin、继承
1. 继承: @extend sass允许一个选择器,继承另一个选择器,通过@extend实现 .class1{ border: 1px solid #333; } .class2{ @extend ...
- PHP封装CURL
CURL是一个非常强大的开源库,支持很多协议,包括HTTP.FTP.TELNET等,我们使用它来发送HTTP请求.它给我 们带来的好处是可以通过灵活的选项设置不同的HTTP协议参数,并且支持HTTPS ...
- CentOS7 搭建GIT环境
一. 安装 libiconv 这个是非常规项 如果服务器原来已经装过 可以不装 但是如果git安装时候提示找不到libiconv 需要在git的安装参数中指定安装路径 最新版是 1.15 wget h ...
- 集合之HashMap、Hashtable
HashMap 基于哈希表的 Map 接口的实现.此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.(除了非同步和允许使用 null 之外,HashMap 类与 Hashtabl ...
- 电子相册之bitmap
位图文件主要分为3部分:1. 文件信息头 14Byte 2. 位图信息头 40Byte 3. RGB颜色阵列 由图像长宽尺寸决定 1. 文件信息头 定义结构体: typedef s ...
- 【Keil】Keil5添加源程序和头文件
xxx.c就是源程序 xxx.h就是头文件 [源程序添加方法] 双击文件夹,例如图片上的Source,跳出弹窗,选择需要添加的源程序即可 [添加头文件的方法] 1.首先点击图片红框处,或是在文件夹te ...
- Hadoop端口
本文转自:<Hadoop默认端口应用一览> Hadoop集群的各部分一般都会使用到多个端口,有些是daemon之间进行交互之用,有些是用于RPC访问以及HTTP访问.而随着Hadoop周边 ...
- 北京Uber优步司机奖励政策(2月28日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- Mybatis之XML、注解
前言 上篇简单介绍了Mybatis的简单实用,本篇先对上次实验环境的一些内容进行优化,然后验证Mybatis的XML配置以及注解方式. 实验环境优化 数据库配置 在mybatis的配置文件中,引入数据 ...