你的位置:首页 > 操作系统

[操作系统]Gradle实战:执行sql操作hive数据库

查看原文:http://blog.csdn.net/u010818425/article/details/52490628

Gradle实战系列文章: 
《Gradle基本知识点与常用配置》 
《Gradle实战:Android多渠道打包方案汇总》 
《Gradle实战:不同编译类型的包同设备共存》 
《Gradle实战:发布aar包到maven仓库》


本文将介绍使用groovy+sql的脚本,实现从hive抓取数据,为方便理解,重要语句有详细注释,关键处已标明“关键点”;在阅读本文过程中,如对groovy还不是很熟悉的读者可以查看《 Gradle基本知识点与常用配置》这篇文章


入门例子

Gradle简单操作mysql数据库


import groovy.sql.Sql class GroovySqlExample1{   static void main(args) {     sql = Sql.newInstance("jdbc:mysql://localhost:3306/tablename", "account", "password", "org.gjt.mm.mysql.Driver")     sql.eachRow("select * from tablename"){       row | println row.word_id + " " + row.spelling + " " + row.part_of_speech       //“row”表示查询到的每一行数据,“row.word_id”表示“word_id”这个字段的值    }   } }

这是一个使用Gradle操作mysql数据库的入门例子,配置好数据库地址、驱动、账号、密码就可以执行sql语句操作数据库了,但是现在越来越多的公司都转向使用分布式存储,以下我们来详细介绍一下Gradle操作hive数据库的实例(当然,你需要有这样一个数据库环境)。



实战例子

以获取udid(设备唯一识别码)为例,条件是:1、近两周内打开过我们app(即我们后台系统有其访问记录),我们认为这些是活跃用户;2、满足条件1的各城市用户中,各取20%的用户。以下分为5各部分来讲述我们的实现方案:sql脚本、配置文件、groovy代码、使用方法、数据产出。


1. getUdid.sql中的sql脚本:

首先,新建一个android工程,无需任何java代码;然后在module中新建一个名为“getUdid.sql“的文件,里面存放的就是我们用于查询数据库的sql脚本;但这个脚本还可以通过gradle运行过程中动态拼接一些参数,下文会有介绍。


SELECT count(DISTINCT udid) AS allCount FROM tablename WHERE dt>=date_sub(current_date,14);SELECT DISTINCT udid FROM tablename WHERE dt>=date_sub(current_date,14)

2. hive.properties中的配置数据

再在module中新建一个名为“hive.properties“的配置文件,用于存放连接数据库所需的相关参数。


HiveUrl=jdbc:hive2://host:port/basename?useUnicode=true&characterEncoding=utf8 Account=xxxPassword=xxxDriver=org.apache.hive.jdbc.HiveDriver //连接hive所用的驱动

注:上述的HiveUrl中,scheme使用的是hive2,因此与其配套的驱动是org.apache.hive.jdbc.HiveDriver,如果使用的是早期的hive,则scheme是hive,其配套的驱动是org.apache.hadoop.hive.jdbc.HiveDriver


3. groovy代码:


import groovy.sql.Sql  //关键点1apply plugin: 'java'apply plugin: 'groovy'apply plugin: 'maven'repositories {  mavenCentral()}configurations {  driver  //关键点2}dependencies {  driver 'org.apache.hive:hive-jdbc:2.1.0' //数据库连接驱动依赖,关键点3}//数据库连接驱动下载,关键点4URLClassLoader loader = GroovyObject.class.classLoaderconfigurations.driver.each { File file ->  loader.addURL(file.toURL()) }task run << {  def File propFile = new File('hive.properties') //“hive.properties”为自定义的配置文件,上文有介绍  if (propFile.canRead()) {    def Properties props = new Properties()    props.load(new FileInputStream(propFile))    if (props != null && props.containsKey('HiveUrl') && props.containsKey('Account')         && props.containsKey('Password') && props.containsKey('Driver')) {       //从配置文件中读取各参数      String hiveUrl = props['HiveUrl']//数据库地址      String account = props['Account']//访问数据库的账号      String password = props['Password']//密码      String driver = props['Driver'] //连接数据库的驱动类名      String os = System.properties['os'] //读取命令行设置的手机系统类型(设置见下文“使用方法”中的命令行)      String ver = System.properties['ver']//读取命令行设置的app版本号(设置见下文“使用方法”中的命令行)      def sql = Sql.newInstance(hiveUrl, account, password, driver)//建立数据库连接,关键点5      String udidName = "udid_" //存放udid的文件名      String summaryName = "summary_" //存放各城市概况的文件名      if (os.equals("Android")) {        udidName += "android.txt"        summaryName += "android.txt"      } else {        udidName += "ios.txt"        summaryName += "ios.txt"      }      String dirPath = getRootDir().toString() + '/result/' //结果存放路径      def dir = new File(dirPath)      if (!dir.exists()) {        dir.mkdirs()      }      String udidPath = dirPath + '/' + udidName //udid文件路径      String summaryPath = dirPath + '/' + summaryName //各城市概况文件路径      def udidFile = new File(udidPath)      def summaryFile = new File(summaryPath)      if (udidFile.exists()) {        udidFile.delete()      }      udidFile.createNewFile()      if (summaryFile.exists()) {        summaryFile.delete()      }      summaryFile.createNewFile()      def resultPrintWriter = udidFile.newPrintWriter()      def summaryPrintWriter = summaryFile.newPrintWriter()       //制表      summaryPrintWriter.write('\n')      summaryPrintWriter.write(os + "用户情况")      summaryPrintWriter.write('\n')      summaryPrintWriter.write('-------------------')      summaryPrintWriter.write('\n')      summaryPrintWriter.write(" 城市" + "  总数" + " 抽取")      summaryPrintWriter.write('\n')      summaryPrintWriter.write('-------------------')      summaryPrintWriter.write('\n')      def citys = ['北京市', '上海市', '广州市', '深圳市']      int allcount = 0 // 活跃用户总数      int allExtracted = 0 // 抽取20%的用户数      try {         //各个城市遍历        citys.each {          city ->            resultPrintWriter.write(city + ':')            resultPrintWriter.write('\n')            resultPrintWriter.write('--------------------------------------')            resultPrintWriter.write('\n')            boolean isGetCount = true            int num = 0             // 读取sql脚本,每句以分号分隔,下方还需动态拼接参数            new File('getUdid.sql').text.split(";").each { //“getUdid.sql”里面为查询udid的sql语句,下文有介绍              sqlTemp ->                 //动态拼接参数                String sqlString = sqlTemp +                    ' AND city=' + "'" + city + "'" +                    ' AND os=' + "'" + os + "'" +                    ' AND ver=' + "'" + ver + "'"                 if (isGetCount) { // 执行第一句sql,获取该城市总活跃用户中的20%                  println sqlString                  sql.eachRow(sqlString) { // 执行sql,关键点6                    num = it.allcount * 0.2 // 总数的20%                    allcount += it.allcount                    allExtracted += num                     //制表                    summaryPrintWriter.write(city + " " + it.allcount + getCount(it.allcount) + num)                    summaryPrintWriter.write('\n')                    summaryPrintWriter.write('-------------------')                    summaryPrintWriter.write('\n')                  }                  isGetCount = false                } else { // 执行第二句sql,获取该城市总活跃用户数前20%的udid                  sqlString = sqlString + " LIMIT " + num // 取前num个数据,动态拼接条件                  println sqlString                  sql.eachRow(sqlString) { // 执行sql                    if (it.udid != null && it.udid != '') {                      resultPrintWriter.write(it.udid + ",")                      resultPrintWriter.write('\n')                    }                  }                }            }            resultPrintWriter.write('--------------------------------------')            resultPrintWriter.write('\n')        }         //制表        summaryPrintWriter.write(" 累计 " + " " + allcount + getCount(allcount) + " " + allExtracted)        summaryPrintWriter.write('\n')        summaryPrintWriter.write('-------------------')        summaryPrintWriter.write('\n')        summaryPrintWriter.write("统计日期:" + releaseTime())        summaryPrintWriter.write('\n')      } catch (Exception e) {        println e.message      }       //关闭打印      resultPrintWriter.flush()      summaryPrintWriter.flush()      resultPrintWriter.close()      summaryPrintWriter.close()    }  }}//获取系统时间def releaseTime() {  return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))}//模拟制表符,用于summary文件里面制作表格String getCount(i) {  int temp = i  int count = 0  while (temp > 0) {    temp = temp / 10    count++  }  String space = ''  if (count == 1) {    space = "   "  } else if (count == 2) {    space = "  "  } else if (count == 3) {    space = "  "  } else if (count == 4) {    space = " "  }  return space}

4. 使用方法

本地需安装Gradle且配置环境变量;然后打开终端,按以下步骤输入命令(第一次执行会下载hive数据库驱动,耗时较长):

  • 进入到工程目录下(假设module名为executeSql):

    cd executeSql
  • 抓取android数据:

    gradle run -Dos='Android' -Dver='1.0.0'
  • 抓取iOS数据:

    gradle run -Dos='iPhone OS' -Dver='2.0.0'

    注:上述命令中,“-D”表示设置参数,在groovy代码中有接收参数的语句String os = System.properties['os']

以android为例,开始执行后,每个城市都会执行以下两句sql,即上述gradle脚本动态拼接成的sql:


SELECT count(DISTINCT udid) AS allCount FROM tablename WHERE dt>=date_sub(current_date,14) AND city='北京市' AND os='Android' AND ver='1.0.0';SELECT DISTINCT udid FROM tablename WHERE dt>=date_sub(current_date,14) AND city='北京市' AND os='Android' AND ver='1.1.0' LIMIT 2000

5. 数据产出

数据产出为两个文件,一个是各城市用户的总体情况,另一个是各城市用户z红20%的udid数据列表;

  • 各城市用户情况,summary_android.txt

    Android用户情况------------------- 城市  总数 抽取-------------------北京市 10000 2000-------------------上海市 20000 4000-------------------广州市 30000 6000-------------------深圳市 40000 8000------------------- 累计 100000 20000-------------------统计日期:2016-09-09
  • 各城市udid,udid_summary.txt(仅作示意)

    北京市:--------------------------------------00123456-2c9c-4ab7-a256-4b86a2490318,00234567-f9fb-4059-a1b8-49514fb17ac0,...--------------------------------------上海市:--------------------------------------00345678-4910-4db5-b82c-42f85450c85c,00456789-1047-470c-9bf2-af326fdac7f1,...--------------------------------------广州市:--------------------------------------01234567-d69f-40fa-aabd-88ac19f542cf,02345678-b1c2-4005-a418-f6d1704b7f81,...--------------------------------------深圳市:--------------------------------------03456789-0413-4cd1-9214-8544a07eecec,04567891-4ac2-49cd-a1c8-f49c5edd9d9b,...--------------------------------------

深入学习

  • Groovy 操作mysql数据库
  • 实战 Groovy: 用 Groovy 进行 JDBC 编程
  • Hive:用Java代码通过JDBC连接Hiveserver

查看原文:http://blog.csdn.net/u010818425/article/details/52490628