背景:能看到这篇博客的伙计儿,应该是充分理解了[理想是丰满的 现实是骨感] 这句名言了吧。
为啥子这么说呢,那就是 不就是个SparkSql从hive导入到mysql吗!
有什么技术含量,但是呢 不断地踩坑ing填坑ing。
废话不多说,直接上硬菜。
package com.test
import java.sql.{Connection, DriverManager, PreparedStatement}
import java.text.{DateFormat, SimpleDateFormat}
import java.util.{Calendar, Properties}
import org.apache.spark.rdd.{JdbcRDD, RDD}
import org.apache.spark.sql.{Row, SQLContext, SaveMode}
import org.apache.spark.sql.hive.HiveContext
import org.apache.spark.sql.types._
import org.apache.spark.{SparkConf, SparkContext}
object hiveToMysql {
def main(args: Array[String]) {
var list: List[String] = List[String]()
//初始化SparkContext
val conf = new SparkConf().setAppName("hiveToMysql")
val sc: SparkContext = new SparkContext(conf)
val hc=new HiveContext(sc)
val scoreRdd = new JdbcRDD(sc, () => {
Class.forName("com.mysql.jdbc.Driver").newInstance()
DriverManager.getConnection("jdbc:mysql://ip:3306/databases", username, password)
}, "select id,score from tables where is_delete=? and age=?", 0, 0, 15, r => r.getString(1) + "," + r.getString(2))
val scoreStr:String=scoreRdd.map(_.split(",")(1)).collect().mkString(",")
val threeSql="SELECT id,name,age,score,grades FROM db.hivetables " +
"where score in (" + scoreStr + ")"
val data=hc.sql(threeSql).map(line=>{
Row(java.lang.Long.getLong("1"),
line.getLong(0),
stringUtil.filterOffUtf8Mb4(line.getString(1)),
Integer.valueOf(line.getString(2)),
Integer.valueOf(line.getString(3)),
line.getByte(4))
})
val schema=StructType( List(
StructField("mid", LongType, false),
StructField("id", LongType, false),
StructField("name", StringType, true),
StructField("age", IntegerType, true),
StructField("score", IntegerType, true),
StructField("grades", ByteType, true),
))
val url = "jdbc:mysql://ip:3306/databases?user=test&password=test&useUnicode=true"
val table ="tables"
val df=hc.createDataFrame(data,schema)
df.insertIntoJDBC(url,table,true)
println("导入数据完成!!!")
sc.stop()
}
}
一下是踩过的坑,以及解决方案:
1、jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '0' for key 'PRIMARY'错误
今天在运行写好的项目时报了这么一个错误(主键重复,0主键已经存在)。。。后来检查了一下数据库,数据库中表User的id属性已设置为自增,而我在HQL语句中把user.id(主键)写进去企图更新它?所以去掉对主键的更新语句后运行正常。
2、com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column "name" cannot be null,
引起这个的原因是表示,name主键的列不能为null值。
3、spark-数据类型
http://www.aboutyun.com/thread-11575-1-1.html
4、DataFrame类中提供了很多写数据库的操作,本例中的createJDBCTable就是可以创建表,它的函数原型如下:
def createJDBCTable(url: String, table: String, allowExisting: Boolean): Unit
table是表的名字,最后一个参数是如果表存在是否删除表的意思,false代表不删除。
DataFrame类中还有insertIntoJDBC方法,调用该函数必须保证表事先存在,它只用于插入数据,函数原型如下:
def insertIntoJDBC(url: String, table: String, overwrite: Boolean): Unit
前面两个参数和createJDBCTable一致,第三个参数如果设置为true,则在插入数据之前会调用mysql的TRUNCATE TABLE语句先清掉表中的数据。
5、Spark RDD写入RMDB(Mysql)方法二
6、java.lang.ClassCastException:java.lang.Byte cannot be cast to java.lang.Long
不能将Byte转换为Long类型
解决方法:java.lang.Long.getLong(String.valueOf(line.getByte(1)))
7、java.sql.SQLException: Incorrect string value: '\xF4\x80\xB3\x8A \xE6...' for column 'content' at row 1
https://blog.csdn.net/wangchangshuai0010/article/details/12714575
数据格式问题
8、java.sql.SQLException: Column count doesn't match value count at row 1
错误原因:在插入数据时,插入的字段个数跟数据库表字段个数不一致
insert into student(sno,sname,sage,ssex) values(1,'张三','man');
解决办法:保证插入数据字段个数跟数据库表中的字段个数一致
9、java过滤非汉字的utf8的字符
https://www.aliyun.com/jiaocheng/847138.html
好了。
愿世界和平 哈哈哈~