Gradle實戰:執行sql操作hive資料庫

来源:http://www.cnblogs.com/meishan/archive/2016/09/24/5903519.html
-Advertisement-
Play Games

查看原文:http://blog.csdn.net/u010818425/article/details/52490628 Gradle實戰系列文章: 《Gradle基本知識點與常用配置》 《Gradle實戰:Android多渠道打包方案彙總》 《Gradle實戰:不同編譯類型的包同設備共存》 《G ...


查看原文: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=xxx
Password=xxx
Driver=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  //關鍵點1

apply plugin: 'java'
apply plugin: 'groovy'
apply plugin: 'maven'

repositories {
    mavenCentral()
}

configurations {
    driver  //關鍵點2
}

dependencies {
    driver 'org.apache.hive:hive-jdbc:2.1.0' //資料庫連接驅動依賴,關鍵點3
}

//資料庫連接驅動下載,關鍵點4
URLClassLoader loader = GroovyObject.class.classLoader
configurations.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,
    
    ...
    --------------------------------------
    

深入學習

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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ...
  • 本文地址:http://www.cnblogs.com/wuyudong/p/5906735.html,轉載請註明源地址。 本文將實現標題欄下麵的textview中的文字跑馬燈的效果,就是將一行文字水平迴圈滾動,效果如下: 實現代碼如下: 如果其他地方也需要這樣的跑馬燈效果,複製代碼比較麻煩。這裡使 ...
  • 很多應用都會在界面中使用某種列表控制項:用戶可以選中、刪除或重新排列列表中的項目。這些控制項其實都是UITableView 對象,可以用來顯示一組對象,例如,用戶地址薄中的一組人名。 UITableView 對象雖然只能顯示一行數據,但是沒有行數限制。 編寫新的應用程式 JXHomepwner 應用 創 ...
  • 本文實現當從splash界面進入hone界面的時候,產生一種漸進淡入的動畫效果,在onCreate中調用一個方法initAnimation(),代碼如下: 其中rl_root在類中定義 private RelativeLayout rl_root; 其中rl_root為splash界面相對佈局的id ...
  • 開發中經常需要使用Shape和Selector,如果每個都用xml設置的話,會占用apk大小,同時命名多了也會混亂,使用代碼來設置會方便很多。 需要用到2個類:GradientDrawable和StateListDrawable 相關API: setColor(rgb); //填充顏色setGrad ...
  • 使用巨集的目的是什麼? 由於實際開發中,有時候一些設置信息需要重覆使用(例如設置列印信息、配置顏色、配置寬度等),如果每次都手動去敲每次都去創建會很麻煩。雖然巨集使用的時候會占用記憶體,可是目前來說大部分開發者都在使用。 1.創建PCH 文件 2.打開配置面板 按照下圖操作 3.按照下圖找到相關配置 4. ...
  • 1.Activity相關。launchmode,OnSaveInstnceState,生命周期等。 4種預設的launchmode,以及OnNewIntent的回調。 OnNewIntent->OnRestart->OnStart->onResume OnActivity->OnResume. On ...
  • 1.排隊機制 接收輸入TCP報文時,有三個隊列: ● 待處理隊列 ● 預排隊隊列 ● 接收隊列 接收隊列包含了處理過的TCP數據段,也就是說,去除了全部的協議頭,正準備將數據複製到用戶應用程式。接收隊列包含了所有按順序接收的數據段,在其他兩個隊列中的TCP數據段則需要進一步處理。 TCP報文首先由t ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...