一. 引言
目前开发的XX出行系统,需要开发数据统计功能,鉴于约约出行系统已经在运营,并且有新版本的迭代,方便以后下个版本复用,遂新建一个子系统。
二. 架构设计
三. 具体实现
1.MySql数据库
(1)配置表:使用配置表,控制要执行的存储过程。
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='统计报表_配置表';
(2)存储过程:存储过程根据配置表给的视图名和存储表,将视图的数据存储到存储表中。
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
(3)视图(略):查询的SQL,放到新建视图就可以生成。假设存储过程的入参是1,那么就使用所有配置表中cycle=1的记录,每小时统计一次。
(4)远程表连接: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 '订单号', PRIMARY KEY (`uuid`), ) ENGINE=FEDERATED DEFAULT CHARSET=utf8 COMMENT='订单表' CONNECTION='mysql://user:password@ip:port/schema/tableName';
2.Java工程方面
(1)定时器类:
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); } }
(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>
(3) ConfigService:
package com.summersoft.ts.service; public interface ConfigService { void processReportConfig(int cycle); }
(4)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()); } } }
(5)ReportConfigMapper.xml对应的SQL写法:
<select id="processReportConfig" statementType="CALLABLE" parameterType="int"> {CALL P_REPORT_CONFIG(#{cycle, mode=IN, jdbcType=INTEGER})} </select>