Apache Druid資料查詢套件詳解計數、排名和分位數計算(送JSON-over-HTTP和SQL兩種查詢詳解)
資料查詢
今天這篇文章是之前兩篇文章的續篇,所以,大家如果直接上來幹,幹不懂的話,就需要先去了解下之前的兩篇文章,雖然跟上兩篇文章關聯性不是很強,但還是有一定關係。
提示到此結束! 欲看此文,必看如下兩篇文章:
Druid支援JSON-over-HTTP和SQL兩種查詢方式。除了標準的SQL操作外,Druid還支援大量的唯一性操作,利用Druid提供的演算法套件可以快速的進行計數,排名和分位數計算。
5.1 準備工作
5.1.1 匯入大量資料
準備大量資料提供查詢,我們插入1萬條隨機打車資料
http://localhost:8010/taxi/batchTask/100000
5.2.2 檢視資料攝取程序
我們發現數據攝取程序正在執行,可以等待資料攝取任務結束
5.3 原生查詢
Druid 最開始的時候是不支援 SQL 查詢的,原生查詢是通過查詢 Broker 提供的 http server 來實現的
5.3.1 查詢語法
curl -L -H'Content-Type:application/json' -XPOST --data-binary @<query_json_file> <queryable_host>:<port>/druid/v2/?pretty
5.3.2 查詢案例
5.3.2.1 編輯查詢JSON
# 建立查詢目錄
mkdir query
# 編輯查詢的JSON
vi query/filter1.json
json 內容如下
{
"queryType":"timeseries",
"dataSource":"message",
"granularity":"month",
"aggregations":[
{
"type":"count",
"name":"taxiNum"
}
],
"filter":{"type":"selector","dimension":"status","value":1},
"intervals":["2021-06-07/2022-06-07"]
}
5.3.2.2 引數解釋
- queryType:查詢型別,timeseries代表時間序列查詢
- dataSource:資料來源,指定需要查詢的資料來源是什麼
- granularity:分組粒度,指定需要進行分組的粒度是什麼樣的
- aggregations:聚合查詢:裡面我們聚合了count,對資料進行統計
- filter:資料過濾,需要查詢那些資料
- intervals:查詢時間的範圍,注意時間範圍是前閉後開的,後面的日期是查詢不到的
5.3.2.3 執行查詢命令
在命名行中執行下面的命令會將查詢json傳送到對應的broker中進行查詢
--data-binary
指定的查詢json的路徑
curl -L -H 'Content-Type:application/json' -XPOST --data-binary @query/filter1.json http://192.168.64.177:8082/druid/v2/?pretty
我們查詢了每個月發起打車的人數有多少
5.4 查詢型別
druid查詢採用的是HTTP RESTFUL方式,REST介面負責接收客戶端的查詢請求,客戶端只需要將查詢條件封裝成JSON格式,通過HTTP方式將JSON查詢條件傳送到broker節點,查詢成功會返回JSON格式的結果資料。瞭解一下druid提供的查詢型別
5.4.1 時間序列查詢
timeseries時間序列查詢對於指定時間段按照查詢規則返回聚合後的結果集,查詢規則中可以設定查詢粒度,結果排序方式以及過濾條件,過濾條件可以使用巢狀過濾,並且支援後聚合。
5.4.1.1 查詢屬性
時間序列查詢主要包括7個主要部分
屬性 | 描述 | 是否必須 |
---|---|---|
queryType |
該字串總是"timeseries"; 該欄位告訴Apache Druid如何去解釋這個查詢 | 是 |
dataSource |
用來標識查詢的的字串或者物件,與關係型資料庫中的表類似。檢視資料來源可以獲得更多資訊 | 是 |
descending |
是否對結果集進行降序排序,預設是false , 也就是升序排列 |
否 |
intervals |
ISO-8601格式的JSON物件,定義了要查詢的時間範圍 | 是 |
granularity |
定義了查詢結果的粒度,參見 Granularity | 是 |
filter |
參見 Filters | 否 |
aggregations |
參見 聚合 | 否 |
postAggregations |
參見Post Aggregations | 否 |
limit |
限制返回結果數量的整數值,預設是unlimited | 否 |
context |
可以被用來修改查詢行為,包括 Grand Total 和 Zero-filling。詳情可以看 上下文引數部分中的所有引數型別 | 否 |
5.4.1.2 案例
{
"queryType":"topN",
"dataSource":"taxi_message",
"dimension":"local",
"threshold":2,
"metric":"age",
"granularity":"month",
"aggregations":[
{
"type":"longMin",
"name":"age",
"fieldName":"age"
}
],
"filter":{"type":"selector","dimension":"sex","value":"女"},
"intervals":["2021-06-07/2022-06-07"]
}
5.4.2 TopN查詢
topn查詢是通過給定的規則和顯示維度返回一個結果集,topn查詢可以看做是給定排序規則,返回單一維度的group by查詢,但是topn查詢比group by效能更快。metric這個屬性是topn專屬的按照該指標排序。
5.4.2.1 查詢屬性
topn的查詢屬性如下
屬性 | 描述 | 是否必須 |
---|---|---|
queryType | 該字串總是"TopN",Druid根據該值來確定如何解析查詢 | 是 |
dataSource | 定義將要查詢的字串或者物件,與關係型資料庫中的表類似。 詳情可以檢視 資料來源 部分。 | 是 |
intervals | ISO-8601格式的時間間隔,定義了查詢的時間範圍 | 是 |
granularity | 定義查詢粒度, 參見 Granularities | 是 |
filter | 參見 Filters | 否 |
aggregations | 參見Aggregations | 對於數值型別的metricSpec, aggregations或者postAggregations必須指定,否則非必須 |
postAggregations | 參見postAggregations | 對於數值型別的metricSpec, aggregations或者postAggregations必須指定,否則非必須 |
dimension | 一個string或者json物件,用來定義topN查詢的維度列,詳情參見DimensionSpec | 是 |
threshold | 在topN中定義N的一個整型數字,例如:在top列表中返回多少個結果 | 是 |
metric | 一個string或者json物件,用來指定top列表的排序。更多資訊可以參見TopNMetricSpec | 是 |
context | 參見Context | 否 |
5.4.2.2 案例
查詢每個季度年齡最小的女性的前兩個的城市
vi query/topN.json
{
"queryType":"topN",
"dataSource":"message",
"dimension":"local",
"threshold":2,
"metric":"age",
"granularity":"quarter",
"aggregations":[
{
"type":"longMin",
"name":"age",
"fieldName":"age"
}
],
"filter":{"type":"selector","dimension":"sex","value":"女"},
"intervals":["2021-06-07/2022-06-07"]
}
5.4.2.3 執行查詢
curl -L -H 'Content-Type:application/json' -XPOST --data-binary @query/topN.json http://192.168.64.177:8082/druid/v2/?pretty
5.4.5 分組查詢
在實際應用中經常需要進行分組查詢,等同於sql語句中的Group by查詢,如果對單個維度和指標進行分組聚合計算,推薦使用topN查詢,能夠獲得更高的查詢效能,分組查詢適合多維度,多指標聚合查詢
5.4.5.1 查詢屬性
下表內容為一個GroupBy查詢的主要部分:
屬性 | 描述 | 是否必須 |
---|---|---|
queryType | 該字串應該總是"groupBy", Druid根據該值來確定如何解析查詢 | 是 |
dataSource | 定義將要查詢的字串或者物件,與關係型資料庫中的表類似。 詳情可以檢視 資料來源 部分。 | 是 |
dimension | 一個用來GroupBy的json List,詳情參見DimensionSpec來了解提取維度的方式 | 是 |
limitSpec | 參見limitSpec | 否 |
having | 參見Having | 否 |
granularity | 定義查詢粒度,參見 Granularities | 是 |
filter | 參見Filters | 否 |
aggregations | 參見Aggregations | 否 |
postAggregations | 參見Post Aggregations | 否 |
intervals | ISO-8601格式的時間間隔,定義了查詢的時間範圍 | 是 |
subtotalsSpec | 一個JSON陣列,返回頂級維度子集分組的附加結果集。稍後將更詳細地描述它。 | 否 |
context | 參見Context | 否 |
5.4.5.2 案例
每一季度統計年齡在21-31的男女打車的數量
vi query/groupBy.json
{
"queryType":"groupBy",
"dataSource":"taxi_message",
"granularity":"Quarter",
"dimensions":["sex"],
"aggregations":[
{
"type":"count",
"name":"taxiNum"
}
],
"filter":{
"type":"bound",
"dimension":"age",
"lower":"21",
"upper":"31",
"alphaNumeric":true
},
"intervals":["2021-06-07/2022-06-07"]
}
5.4.5.3 執行查詢
curl -L -H 'Content-Type:application/json' -XPOST --data-binary @query/groupBy.json http://192.168.64.177:8082/druid/v2/?pretty
5.5 查詢元件
在介紹具體的查詢之前,我們先來了解一下各種查詢都會用到的基本元件,如Filter,Aggregator,Post-Aggregator,Query,Interval等,每種元件都包含很多的細節
5.5.1 Filter
Filter就是過濾器,在查詢語句中就是一個JSON物件,用來對維度進行篩選和過濾,表示維度滿足Filter的行是我們需要的資料,類似sql中的where字句。Filter包含的型別如下:
5.5.1.1 選擇過濾器
Selector Filter的功能類似於SQL中的
where key=value
,它的json示例如下
"Filter":{"type":"selector","dimension":dimension_name,"value":target_value}
使用案例
vi query/filter1.json
{
"queryType":"timeseries",
"dataSource":"taxi_message",
"granularity":"month",
"aggregations":[
{
"type":"count",
"name":"taxiNum"
}
],
"filter":{"type":"selector","dimension":"status","value":1},
"intervals":["2021-06-07/2022-06-07"]
}
5.5.1.2 正則過濾器
Regex Filter 允許使用者使用正則表示式進行維度的過濾篩選,任何java支援的標準正則表示式druid都支援,它的JSON格式如下:
"filter":{"type":"regex","dimension":dimension_name,"pattern":regex}
使用案例,我們搜尋姓名包含數字的的使用者進行聚合統計
vi query/filter2.json
{
"queryType":"timeseries",
"dataSource":"taxi_message",
"granularity":"month",
"aggregations":[
{
"type":"count",
"name":"taxiNum"
}
],
"filter":{"type":"regex","dimension":"username","pattern":"[0-9]{1,}"},
"intervals":["2021-06-07/2022-06-07"]
}
執行查詢
curl -L -H 'Content-Type:application/json' -XPOST --data-binary @query/filter2.json http://192.168.64.177:8082/druid/v2/?pretty
5.5.1.3 邏輯過濾器
Logincal Expression Filter包含and,not,or三種過濾器,每一種都支援巢狀,可以構建豐富的邏輯表示式,與sql中的and,not,or類似,JSON表示式如下:
"filter":{"type":"and","fields":[filter1,filter2]}
"filter":{"type":"or","fields":[filter1,filter2]}
"filter":{"type":"not","fields":[filter]}
使用案例,我們查詢每一個月,進行打車並且是女性的數量
vi query/filter3.json
{
"queryType":"timeseries",
"dataSource":"taxi_message",
"granularity":"month",
"aggregations":[
{
"type":"count",
"name":"taxiNum"
}
],
"filter":{
"type":"and",
"fields":[
{"type":"selector","dimension":"status","value":1},
{"type":"selector","dimension":"sex","value":"女"}
]
},
"intervals":["2021-06-07/2022-06-07"]
}
進行資料查詢
curl -L -H 'Content-Type:application/json' -XPOST --data-binary @query/filter3.json http://192.168.64.177:8082/druid/v2/?pretty
5.5.1.4 包含過濾器
In Filter類似於SQL中的in, 比如 where username in('zhangsan','lisi','zhaoliu'),它的JSON格式如下:
{
"type":"in",
"dimension":"local",
"values":['四川省','江西省','福建省']
}
使用案例,我們查詢每一個月,在四川省、江西省、福建省打車的人數
vi query/filter4.json
{
"queryType":"timeseries",
"dataSource":"taxi_message",
"granularity":"month",
"aggregations":[
{
"type":"count",
"name":"taxiNum"
}
],
"filter":{
"type":"in",
"dimension":"local",
"values":["四川省","江西省","福建省"]
},
"intervals":["2021-06-07/2022-06-07"]
}
進行資料查詢
curl -L -H 'Content-Type:application/json' -XPOST --data-binary @query/filter4.json http://192.168.64.177:8082/druid/v2/?pretty
5.5.1.5 區間過濾器
Bound Filter是比較過濾器,包含大於,等於,小於三種,它預設支援的就是字串比較,是基於字典順序,如果使用數字進行比較,需要在查詢中設定alpaNumeric的值為true,需要注意的是Bound Filter預設的大小比較為>=或者<=,因此如果使用<或>,需要指定lowerStrict值為true,或者upperStrict值為true,它的JSON格式如下: 21 <=age<=31
{
"type":"bound",
"dimension":"age",
"lower":"21", #預設包含等於
"upper":"31", #預設包含等於
"alphaNumeric":true #數字比較時指定alphaNumeric為true
}
使用案例,我們查詢每一個月,年齡在21-31之間打車人的數量
vi query/filter5.json
{
"queryType":"timeseries",
"dataSource":"taxi_message",
"granularity":"month",
"aggregations":[
{
"type":"count",
"name":"taxiNum"
}
],
"filter":{
"type":"bound",
"dimension":"age",
"lower":"21",
"upper":"31",
"alphaNumeric":true
},
"intervals":["2021-06-07/2022-06-07"]
}
進行資料查詢
curl -L -H 'Content-Type:application/json' -XPOST --data-binary @query/filter5.json http://192.168.64.177:8082/druid/v2/?pretty
5.5.2 聚合粒度
聚合粒度通過granularity配置項指定聚合時間跨度,時間跨度範圍要大於等於建立索引時設定的索引粒度,druid提供了三種類型的聚合粒度分別是:Simple,Duration,Period
5.5.2.1 Simple的聚合粒度
Simple的聚合粒度通過druid提供的固定時間粒度進行聚合,以字串表示,定義查詢規則的時候不需要顯示設定type配置項,druid提供的常用Simple粒度:
all,none,minute,fifteen_minute,thirty_minute,hour,day,month,Quarter(季度),year;
-
all:會將起始和結束時間內所有資料聚合到一起返回一個結果集,
-
none:按照建立索引時的最小粒度做聚合計算,最小粒度是毫秒為單位,不推薦使用效能較差;
-
minute:以分鐘作為聚合的最小粒度;
-
fifteen_minute:15分鐘聚合;
-
thirty_minute:30分鐘聚合
-
hour:一小時聚合
-
day:天聚合
-
month:月聚合
-
Quarter:季度聚合
-
year:年聚合
編寫測試,我們這裡按照季度聚合,並且我們過濾年齡是21-31的資料,並且按照地域以及性別進行分組
vi query/filter6.json
{
"queryType":"groupBy",
"dataSource":"taxi_message",
"granularity":"Quarter",
"dimensions":["local","sex"],
"aggregations":[
{
"type":"count",
"name":"taxiNum"
}
],
"filter":{
"type":"bound",
"dimension":"age",
"lower":"21",
"upper":"31",
"alphaNumeric":true
},
"intervals":["2021-06-07/2022-06-07"]
}
進行查詢
curl -L -H 'Content-Type:application/json' -XPOST --data-binary @query/filter6.json http://192.168.64.177:8082/druid/v2/?pretty
5.5.2.2 Duration聚合粒度
duration聚合粒度提供了更加靈活的聚合粒度,不只侷限於Simple聚合粒度提供的固定聚合粒度,而是以毫秒為單位自定義聚合粒度,比如兩小時做一次聚合可以設定duration配置項為7200000毫秒,所以Simple聚合粒度不能夠滿足的聚合粒度可以選擇使用Duration聚合粒度。
注意:使用Duration聚合粒度需要設定配置項type值為duration
編寫測試,我們按照
vi query/filter7.json
{
"queryType":"groupBy",
"dataSource":"taxi_message",
"granularity":{
"type":"duration",
"duration":7200000
},
"dimensions":["local","sex"],
"aggregations":[
{
"type":"count",
"name":"taxiNum"
}
],
"filter":{
"type":"bound",
"dimension":"age",
"lower":"21",
"upper":"31",
"alphaNumeric":true
},
"intervals":["2021-06-07/2021-06-10"]
}
資料查詢
curl -L -H 'Content-Type:application/json' -XPOST --data-binary @query/filter7.json http://192.168.64.177:8082/druid/v2/?pretty
5.5.2.3 Period聚合粒度
Period聚合粒度採用了日期格式,常用的幾種時間跨度表示方法,一小時:PT1H,一週:P1W,一天:P1D,一個月:P1M;使用Period聚合粒度需要設定配置項type值為period,
編寫測試,我們按照一天進行聚合
vi query/filter8.json
{
"queryType":"groupBy",
"dataSource":"taxi_message",
"granularity":{
"type":"period",
"period":"P1D"
},
"dimensions":["sex"],
"aggregations":[
{
"type":"count",
"name":"taxiNum"
}
],
"filter":{
"type":"bound",
"dimension":"age",
"lower":"21",
"upper":"31",
"alphaNumeric":true
},
"intervals":["2021-06-07/2021-06-10"]
}
資料查詢
curl -L -H 'Content-Type:application/json' -XPOST --data-binary @query/filter8.json http://192.168.64.177:8082/druid/v2/?pretty
5.5.3 聚合器
Aggregator是聚合器,聚合器可以在資料攝入階段和查詢階段使用,在資料攝入階段使用聚合器能夠在資料被查詢之前按照維度進行聚合計算,提高查詢階段聚合計算效能,在查詢過程中,使用聚合器能夠實現各種不同指標的組合計算。
5.5.3.1 公共屬性
聚合器的公共屬性介紹
-
type:宣告使用的聚合器型別;
-
name:定義返回值的欄位名稱,相當於sql語法中的欄位別名;
-
fieldName:資料來源中已定義的指標名稱,該值不可以自定義,必須與資料來源中的指標名一致;
5.5.3.2 計數聚合
計數聚合器,等同於sql語法中的count函式,用於計算druid roll-up合併之後的資料條數,並不是攝入的原始資料條數,在定義資料模式指標規則中必須新增一個count型別的計數指標count;
比如想查詢Roll-up 後有多少條資料,查詢的JSON格式如下
vi query/aggregator1.json
{
"queryType":"timeseries",
"dataSource":"taxi_message",
"granularity":"Quarter",
"aggregations":[
{
"type":"count",
"name":"count"
}
],
"filter":{
"type":"bound",
"dimension":"age",
"lower":"21",
"upper":"31",
"alphaNumeric":true
},
"intervals":["2021-06-07/2022-06-07"]
}
5.5.3.3 求合聚合
求和聚合器,等同於sql語法中的sum函式,使用者指標求和計算,druid提供兩種型別的聚合器,分別是long型別和double型別的聚合器;
第一類就是longSum Aggregator ,負責整數型別的計算,JSON格式如下:
{"type":"longSum","name":out_name,"fieldName":"metric_name"}
第二類是doubleSum Aggregator,負責浮點數計算,JSON格式如下:
{"type":"doubleSum","name":out_name,"fieldName":"metric_name"}
示例
vi query/aggregator2.json
{
"queryType":"timeseries",
"dataSource":"taxi_message",
"granularity":"Quarter",
"aggregations":[
{
"type":"longSum",
"name":"ageSum",
"fieldName":"age"
}
],
"filter":{
"type":"bound",
"dimension":"age",
"lower":"21",
"upper":"31",
"alphaNumeric":true
},
"intervals":["2021-06-07/2022-06-07"]
}
5.6 Druid SQL
Druid SQL是一個內建的SQL層,是Druid基於JSON的本地查詢語言的替代品,它由基於 Apache Calcite的解析器和規劃器提供支援
Druid SQL將SQL轉換為查詢Broker(查詢的第一個程序)上的原生Druid查詢,然後作為原生Druid查詢傳遞給資料程序。除了在Broker上 轉換SQL) 的(輕微)開銷之外,與原生查詢相比,沒有額外的效能損失。
5.6.1 基本查詢
5.6.1.1 查詢資料總條數
可以在druid的控制檯進行查詢
select count(1) from "taxi_message"
5.6.1.2 查詢當前打車人數
我們可以統計出來當前的打車的人數
5.6.2 聚合功能
聚合函式可以出現在任何查詢的SELECT子句中。可以使用類似語法過濾任何聚合器
AGG(expr) FILTER(WHERE whereExpr)
。過濾的聚合器僅聚合與其過濾器匹配的行。同一SQL查詢中的兩個聚合器可能具有不同的篩選器。
只有COUNT聚合可以接受DISTINCT。
功能 | 筆記 |
---|---|
COUNT(*) |
計算行數。 |
COUNT(DISTINCT expr) |
計算expr的不同值,可以是string,numeric或hyperUnique。預設情況下,這是近似值,使用HyperLogLog的變體。要獲得準確的計數,請將“useApproximateCountDistinct”設定為“false”。如果這樣做,expr必須是字串或數字,因為使用hyperUnique列無法進行精確計數。另見APPROX_COUNT_DISTINCT(expr) 。在精確模式下,每個查詢只允許一個不同的計數。 |
SUM(expr) |
求和數。 |
MIN(expr) |
採用最少的數字。 |
MAX(expr) |
取最大數字。 |
AVG(expr) |
平均數。 |
APPROX_COUNT_DISTINCT(expr) |
計算expr的不同值,可以是常規列或hyperUnique列。無論“useApproximateCountDistinct”的值如何,這始終是近似值。另見COUNT(DISTINCT expr) 。 |
APPROX_COUNT_DISTINCT_DS_HLL(expr, [lgK, tgtHllType]) |
計算expr的不同值,可以是常規列或HLL草圖列。的lgK 和tgtHllType 引數的HLL草圖文件中描述。無論“useApproximateCountDistinct”的值如何,這始終是近似值。另見COUNT(DISTINCT expr) 。該DataSketches擴充套件必須載入使用此功能。 |
APPROX_COUNT_DISTINCT_DS_THETA(expr, [size]) |
計算expr的不同值,可以是常規列或Theta sketch列。該size 引數在Theta sketch文件中描述。無論“useApproximateCountDistinct”的值如何,這始終是近似值。另見COUNT(DISTINCT expr) 。該DataSketches擴充套件必須載入使用此功能。 |
APPROX_QUANTILE(expr, probability, [resolution]) |
計算numeric或approxHistogram exprs的近似分位數。“概率”應該在0和1之間(不包括)。“解析度”是用於計算的質心數。解析度越高,結果越精確,但開銷也越高。如果未提供,則預設解析度為50. 必須載入近似直方圖擴充套件才能使用此功能。 |
APPROX_QUANTILE_DS(expr, probability, [k]) |
計算數值或Quantiles草圖 exprs的近似分位數。“概率”應該在0和1之間(不包括)。該k 引數在Quantiles草圖文件中描述。該DataSketches擴充套件必須載入使用此功能。 |
APPROX_QUANTILE_FIXED_BUCKETS(expr, probability, numBuckets, lowerLimit, upperLimit, [outlierHandlingMode]) |
計算數字或固定桶直方圖 exprs的近似分位數。“概率”應該在0和1之間(不包括)。的numBuckets ,lowerLimit ,upperLimit ,和outlierHandlingMode 引數在固定桶中描述直方圖文件。在近似直方圖擴充套件必須載入使用此功能。 |
BLOOM_FILTER(expr, numEntries) |
根據生成的值計算布隆過濾器,在假定正比率增加之前expr 使用numEntries 最大數量的不同值。有關其他詳細資訊,請參閱bloom filter擴充套件文件 |
5.6.2.1 查詢資料總條數
可以在druid的控制檯進行查詢
select count(1) from "taxi_message"
5.7 客戶端API
我們在這裡實現SpringBoot+Mybatis實現SQL查詢ApacheDruid資料
5.7.1 引入Pom依賴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.calcite.avatica</groupId>
<artifactId>avatica</artifactId>
<version>1.18.0</version>
</dependency>
<dependency>
<groupId>org.apache.calcite.avatica</groupId>
<artifactId>avatica-server</artifactId>
<version>1.18.0</version>
</dependency>
</dependencies>
5.7.1.1 配置資料來源連線
在application.yml中配置資料庫的連線資訊
- 連線時需注意Druid時區和JVM時區,不設定時區時預設採用JVM時區
- 文件參考地址:http://calcite.apache.org/avatica/docs/client_reference.html
spring:
datasource:
# 連線池資訊
url: jdbc:avatica:remote:url=http://192.168.64.177:8082/druid/v2/sql/avatica/
# 驅動資訊
driver-class-name: org.apache.calcite.avatica.remote.Driver
5.7.2 編寫程式碼
5.7.2.1 編寫實體類
public class TaxiMessage {
private String __time;
private Integer age;
private Integer createDate;
private String local;
private String sex;
private Integer status;
private String statusText;
private String username;
//setter getter 忽略
@Override
public String toString() {
return "TaxiMessage{" +
"__time='" + __time + '\'' +
", age=" + age +
", createDate=" + createDate +
", local='" + local + '\'' +
", sex='" + sex + '\'' +
", status=" + status +
", statusText='" + statusText + '\'' +
", username='" + username + '\'' +
'}';
}
}
5.7.2.2 編寫mapper
所有欄位名、表名必須使用如下方式標識
\"表名\"
@Mapper
public interface TaxiMessageMapper {
@Select("SELECT * FROM \"taxi_message\" where username=#{username}")
public TaxiMessage findByUserName(String username);
}
5.7.2.3 編寫Service
@Service
public class TaxiMessageService {
@Autowired
private TaxiMessageMapper taxiMessageMapper;
public TaxiMessage findByUserName(String username) {
return taxiMessageMapper.findByUserName(username);
}
}
5.7.2.4 編寫啟動類
@SpringBootApplication
@MapperScan(basePackages = "com.heima.druid.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
5.7.2.5 編寫測試類
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class DruidTest {
@Autowired
private TaxiMessageService taxiMessageService;
@Test
public void test() {
TaxiMessage taxiMessage = taxiMessageService.findByUserName("eFQfLXmXD4");
System.out.println(taxiMessage);
Assert.assertNotNull(taxiMessage);
}
}
5.7.2.6 執行測試
本文由
傳智教育博學谷
教研團隊釋出。如果本文對您有幫助,歡迎
關注
和點贊
;如果您有任何建議也可留言評論
或私信
,您的支援是我堅持創作的動力。轉載請註明出處!
- ElasticSearch還能效能調優,漲見識、漲見識了!!!
- 【必須收藏】別再亂找TiDB 叢集部署教程了,這篇保姆級教程來幫你!!| 博學谷狂野架構師
- 【建議收藏】7000 字的TIDB保姆級簡介,你見過嗎
- Tomcat架構設計剖析 | 博學谷狂野架構師
- 你可能不那麼知道的Tomcat生命週期管理 | 博學谷狂野架構師
- 大哥,這是併發不是並行,Are You Ok?
- 為啥要重學Tomcat?| 博學谷狂野架構師
- 這是一篇純講SQL語句優化的文章!!!| 博學谷狂野架構師
- 捲起來!!!看了這篇文章我才知道MySQL事務&MVCC到底是啥?
- 為什麼99%的程式設計師都做不好SQL優化?
- 如何搞定MySQL鎖(全域性鎖、表級鎖、行級鎖)?這篇文章告訴你答案!太TMD詳細了!!!
- 【建議收藏】超詳細的Canal入門,看這篇就夠了!!!
- 從菜鳥程式設計師到高階架構師,竟然是因為這個字final
- 為什麼95%的Java程式設計師,都是用不好Synchronized?
- 99%的Java程式設計師者,都敗給這一個字!
- 8000 字,就說一個字Volatile
- 98%的程式設計師,都沒有研究過JVM重排序和順序一致性
- 來一波騷操作,Java記憶體模型
- 時隔多年,這次我終於把動態代理的原始碼翻了個地兒朝天
- 再有人問你分散式事務,把這篇文章砸過去給他