一. 引言
目前开发的约约出行系统,需要开发数据统计功能,鉴于约约出行系统已经在运营,并且有新版本的迭代,方便以后下个版本复用,遂新建一个子系统。
二. 架构设计
三. 具体实现
1)MySql数据库
配置表:
CREATE TABLE `t_report_config` (
`uuid` varchar(32) NOT NULL COMMENT '主键ID',
`source_view` varchar(64) NOT NULL COMMENT '数据源视图',
`result_table` varchar(64) NOT NULL COMMENT '结果存储表',
`cycle` int(11) NOT NULL COMMENT '周期类型(1:小时,2:天)',
`status` int(11) DEFAULT NULL COMMENT '状态(0:失败,1:成功)',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='统计报表_配置表';
使用配置表,控制要执行的存储过程,存储过程调用配置表指定视图,存到配置表指定的存储表里面。
存储过程:
CREATE DEFINER=`admin`@`%` PROCEDURE `P_REPORT_CONFIG`(IN args_cycle INT)
BEGIN
-- 需要定义接收游标数据的变量
-- 配置表主键ID
DECLARE var_uuid CHAR (32);
-- 数据源视图
DECLARE var_source_view CHAR (64);
-- 结果存储表
DECLARE var_result_table CHAR (64);
-- 周期类型(1:小时,2:天)
DECLARE var_cycle INT;
-- 状态(0:失败,1:成功)
DECLARE var_status INT;
-- 动态SQL语句
DECLARE sqlStr VARCHAR(500);
-- 遍历数据结束标志
DECLARE done INT DEFAULT FALSE;
-- 游标
DECLARE cur CURSOR FOR SELECT
trc.uuid var_uuid,
trc.source_view var_source_view,
trc.result_table var_result_table,
trc.cycle var_cycle,
trc.status var_status
FROM
t_report_config trc WHERE trc.cycle = args_cycle
;
-- 将结束标志绑定到游标
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET done = TRUE;
-- 打开游标
OPEN cur;
-- 开始循环
read_loop :
LOOP
-- 提取游标里的数据,这里只有一个,多个的话也一样;
FETCH cur INTO
var_uuid,
var_source_view,
var_result_table,
var_cycle,
var_status;
-- 声明结束的时候
IF done THEN
LEAVE read_loop;
END
IF;
-- 这里做你想做的循环的事件
SET @tableName = var_result_table;
SET @viewName = var_source_view;
set sqlStr = CONCAT('INSERT INTO ',@tableName,' SELECT * FROM ',@viewName);
SET @sqlstr = sqlStr;
PREPARE stmt from @sqlstr;
EXECUTE stmt;
deallocate prepare stmt;
UPDATE t_report_config trc SET trc.`status` = 1,trc.update_time = NOW() WHERE trc.uuid = var_uuid;
END
LOOP
;
-- 关闭游标
CLOSE cur;
END
视图(略):查询的SQL,放到新建视图就可以生成。假设存储过程的入参是1,那么就使用所有配置表中cycle=1的记录,每小时统计一次。
远程表连接:
FEDERATED:FEDERATED存储引擎是访问远程数据库中的表,在平时开发中可以用此特性来访问远程库中的参数表之类的,还是非常方便的。使用时直接在本地构建一个federated表来链接远程数据表,
配置好之后本地数据库可以直接和远程数据表进行同步,实际上这个数据库并不是真实存放数据,所需要的数据都是存放在远程服务器上。
配置条件:mysql版本需要5.1以上;在安装是需要把federated引擎已经安装;
检查是否开启:show engines;
如果没开启,则:修改mysql的配置文件,在my.ini中[mysqld]标签下下直接加上一行 federated重启数据库服务即可。
建立远程表连接:
ENGINE=FEDERATED DEFAULT CHARSET=utf8 COMMENT='订单表'
CONNECTION='mysql://user:password@ip:port/schema/tableName';
例子:
CREATE TABLE `yy_order` (
`uuid` char(32) NOT NULL,
`order_no` varchar(32) DEFAULT NULL COMMENT '订单号',
`passenger_uuid` char(32) DEFAULT NULL COMMENT '订单创建乘客ID',
`assign_driver_uuid` char(32) DEFAULT NULL COMMENT '被改派司机UUID',
`actual_driver_uuid` char(32) DEFAULT NULL COMMENT '实际接单司机UUID',
`car_uuid` char(32) DEFAULT NULL COMMENT '所乘车辆uuid',
`type_time` int(11) NOT NULL COMMENT '订单类型(时效性):1 实时订单, 2 预约订单',
`type_trip` int(11) NOT NULL COMMENT '订单类型(行程):1 出租车;2 专车; 3 拼车; 4 接送机;5 日租/半日租',
`type_ent` int(11) NOT NULL COMMENT '订单类型(个人/企业):1 个人;2 企业',
`type_self` int(11) NOT NULL COMMENT '订单类型(本人/代客):1 本人;2 代客',
`type_main` int(11) NOT NULL COMMENT '订单类型(主/子订单):1 主订单;2 子订单',
`source` int(11) NOT NULL COMMENT '订单来源:1 APP移动端;2 微信公众号;3 电话叫车;4 pc网站;5 后台下单',
`main_status` int(11) NOT NULL COMMENT '订单主状态1:订单初识化,2订单进行中3:订单结束(待支付)4:支付完成5.取消',
`sub_status` int(11) NOT NULL COMMENT '100:乘客发单、等待应答;\r\n200:司机接单、行程确定;\r\n210:司机出发、去接乘客;\r\n220:司机到达、等待乘客;\r\n300:乘客上车、行程开始;\r\n400:司机送达目的地;\r\n500:司机确认费用,等待乘客支付;\r\n600:付款完成、行程结束;\r\n610:乘客完成对车主评价;\r\n900:乘客取消(新行程);\r\n901:乘客取消(行程确定后、司机未到达);\r\n902:乘客取消(行程确定后、司机到达);\r\n910:[新行程]司机取消;\r\n980:无人抢单,订单超时;\r\n990:客服关闭订单',
`pay_purpose` int(11) DEFAULT NULL COMMENT '支付目的(1.支付车费,2.账户充值)',
`pay_side` int(11) DEFAULT NULL COMMENT '支付端(1.乘客,2.司机)',
`pay_type` int(11) DEFAULT NULL COMMENT '支付方式: 1.微信 2.支付宝 3.现金 4.余额 5.优惠券抵扣 6.信用卡 7.ApplePay 10.零元支付',
`prepay_type` int(11) DEFAULT NULL COMMENT '预支付方式(1企业支付,2个人支付)',
`ent_uuid` char(32) DEFAULT NULL COMMENT '企业ID',
`mot_step` int(1) DEFAULT NULL,
`main_order_uuid` char(32) DEFAULT NULL COMMENT '主订单UUID',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`updater` char(32) DEFAULT NULL COMMENT '修改者',
`appid` char(32) NOT NULL,
`is_billed` int(11) unsigned DEFAULT NULL COMMENT '发票状态(0待开票、1待寄出、2已寄出、3已取消、4已作废)',
`pay_time` datetime DEFAULT NULL COMMENT '支付时间',
`is_allow_assigned` int(11) DEFAULT NULL COMMENT '是否允许指派其他司机(1 允许;2 不允许)',
`distribute_time` datetime DEFAULT NULL COMMENT '派单成功时间',
`passenger_lng` varchar(255) DEFAULT NULL COMMENT '乘客发单经度',
`passenger_lat` varchar(255) DEFAULT NULL COMMENT '乘客发单纬度',
`passenger_ip` varchar(20) DEFAULT '' COMMENT '乘客发单IP地址',
`passenger_port` int(11) DEFAULT '0' COMMENT '乘客发单端口号',
`passenger_imei` varchar(64) DEFAULT '' COMMENT '乘客发单imei',
`passenger_mac` varchar(64) DEFAULT '' COMMENT '乘客发单mac地址',
`seat_num` int(11) DEFAULT NULL COMMENT '订单座位',
`match_time` datetime DEFAULT NULL COMMENT '订单开始匹配时间',
`valid_json` varchar(1000) DEFAULT NULL COMMENT '数据验证',
`type_module` tinyint(2) DEFAULT '0' COMMENT '订单模块类型(1:出租车,2:专车,3:拼车,4:快车,5:货的,6:骑手,7:搬家)',
`type_trip_new` tinyint(2) DEFAULT '0' COMMENT '订单行程类型(1:用车,2:日租,3:半日租,4:送机,5:接机)',
`type_time_new` tinyint(2) DEFAULT '0' COMMENT '订单时效类型(1:实时,2:预约)',
`type_interactive` tinyint(2) DEFAULT '0' COMMENT '订单交互类型(1:推单,2:抢单)',
`car_level_uuid` varchar(32) DEFAULT '' COMMENT '订单车型ID',
`type_map` int(1) DEFAULT NULL COMMENT '地图类型:1.高德,2.谷歌',
`created_on` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`cost_department_uuid` varchar(32) DEFAULT '' COMMENT '公务用车成本部门',
`service_department_uuid` varchar(32) DEFAULT '' COMMENT '公务用车服务部门',
PRIMARY KEY (`uuid`),
KEY `idx_order_status` (`main_status`,`sub_status`) USING BTREE,
KEY `idx_passenger_uuid` (`passenger_uuid`) USING BTREE,
KEY `idx_assign_driver_uuid` (`assign_driver_uuid`) USING BTREE,
KEY `idx_actual_driver_uuid` (`actual_driver_uuid`) USING BTREE,
KEY `idx_create_time` (`create_time`) USING BTREE,
KEY `idx_order_no` (`order_no`),
KEY `idx_car_uuid` (`car_uuid`) USING BTREE
) ENGINE=FEDERATED DEFAULT CHARSET=utf8 COMMENT='订单表' CONNECTION='mysql://user:password@ip:port/schema/tableName';
2)Java工程方面:
定时器类:
package com.summersoft.ts.base;
import com.summersoft.ts.service.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("processTask")
public class ProcessTask {
@Autowired
private ConfigService configService;
/**
* 执行存储过程(小时)
*/
public void runHourProcess(){
configService.processReportConfig(1);
}
/**
* 执行存储过程(天)
*/
public void runDayProcess(){
configService.processReportConfig(2);
}
}
定时器配置:applicationContext.xml里面<beans></beans>添加配置
<!-- 定时任务配置 -->
<task:scheduled-tasks>
<task:scheduled ref="processTask" method="runHourProcess" cron="0 0 * * * *" />
<task:scheduled ref="processTask" method="runDayProcess" cron="0 0 3 * * *" />
</task:scheduled-tasks>
ConfigService:
package com.summersoft.ts.service;
public interface ConfigService {
void processReportConfig(int cycle);
}
ConfigServiceImpl:
package com.summersoft.ts.service.impl;
import com.summersoft.ts.dao.ReportConfigDao;
import com.summersoft.ts.service.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service("configService")
public class ConfigServiceImpl implements ConfigService {
@Autowired
private ReportConfigDao configDao;
@Override
public void processReportConfig(int cycle) {
try {
configDao.processReportConfig(cycle);
}catch (Exception e){
System.out.println("存储过程执行异常:"+e.getMessage());
}
}
}
ReportConfigMapper.xml对应的SQL写法:
<select id="processReportConfig" statementType="CALLABLE" parameterType="int">
{CALL P_REPORT_CONFIG(#{cycle, mode=IN, jdbcType=INTEGER})}
</select>