数据查问

明天这篇文章是之前两篇文章的续篇,所以,大家如果间接上来干,干不懂的话,就须要先去理解下之前的两篇文章,尽管跟上两篇文章关联性不是很强,但还是有肯定关系。

提醒到此结束!

欲看此文,必看如下两篇文章:

  1. 【超具体】Apache Durid从入门到装置具体教程
  2. Apache Druid 数据摄取---本地数据和kafka流式数据
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# 编辑查问的JSONvi 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, 也就是升序排列
intervalsISO-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定义将要查问的字符串或者对象,与关系型数据库中的表相似。 详情能够查看 数据源 局部。
intervalsISO-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
intervalsISO-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草图列。的lgKtgtHllType参数的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之间(不包含)。的numBucketslowerLimitupperLimit,和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时区
  • 文档参考地址:https://calcite.apache.org/av...
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
所有字段名、表名必须应用如下形式标识 \"表名\"
@Mapperpublic interface TaxiMessageMapper {    @Select("SELECT * FROM \"taxi_message\" where username=#{username}")    public TaxiMessage findByUserName(String username);}
5.7.2.3 编写Service
@Servicepublic 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 运行测试

本文由传智教育博学谷教研团队公布。

如果本文对您有帮忙,欢送关注点赞;如果您有任何倡议也可留言评论私信,您的反对是我保持创作的能源。

转载请注明出处!