比如说现在数据库表信息增加的很快,然后我们需要对每个表设置过期删除策略;
大概思路就是:定时任务调度,给每个表制定sql,然后执行删除数据的sql
//删除一个月前的数据
delete FROM test_info WHERE create_time < DATE_SUB(CURDATE(), INTERVAL 1 MONTH);
那么我们是不是可以把这条sql 在项目中进行执行,我这里是springboot+mybatis演示:
我们将上述sql的参数都提出来做成变量,然后调用,这里提取出来四个变量:
- table_name :表
- column_name:依据列(通常为时间字段 具体可以看看DATE_SUB 支:持哪些 我这里的时间类型是DATETIME)
- expired_num:过期num
- expired_unit:过期单位(月,天 等)
还有更多时间单位
现在code一下:
主要逻辑:
//思路:
//1、将表的过期处理信息制作成json,传入(这里的json可以管理起来,甚至于是数据表/redis的value),这里演示就直接以json的形式
//2、遍历 :拿到每个表的参数,并调用mybatis的mapper(绑定了xml)
//3、做好参数校验,防止注入风险,因为我们这块业务不对外暴露,所以只需要做简单的校验
//4、此时该方法就可以做成接口,甚至于定时任务等形式来处理过期数据
//5、做成这样放在项目内好管理,当然也可以做python脚本等形式,主要就是sql的调用,并做成合理的链
public void clearExpiredData() {
try {
String inputData = "[{\"table_name\":\"test_info\",\"column_name\":\"create_time\",\"expired_num\":\"4\",\"expired_unit\":\"MONTH\"}," +
"{\"table_name\":\"test_info\",\"column_name\":\"create_time\",\"expired_num\":\"30\",\"expired_unit\":\"DAY\"}]";
if (JSON.isValid(inputData)) {
String tableNameFiled = "table_name";
String columnNameFiled = "column_name";
String expiredNumFiled = "expired_num";
String expiredUnitFiled = "expired_unit";
JSONArray jsonArray = JSON.parseArray(inputData);
Iterator iterator = jsonArray.stream().iterator();
while (iterator.hasNext()) {
JSONObject next = (JSONObject) iterator.next();
//校验包含特定的key,和过期单位必须是 DAY或者MONTH (mysql支持更多,但是这是业务)
if (next.containsKey(tableNameFiled) && next.containsKey(columnNameFiled) && next.containsKey(expiredNumFiled) && next.containsKey(expiredUnitFiled)
&& (Objects.equals(next.get(expiredUnitFiled), "DAY") || (Objects.equals(next.get(expiredUnitFiled), "MONTH")))) {
String tableName = (String) next.get(tableNameFiled);
String columnName = (String) next.get(columnNameFiled);
String expiredNum = (String) next.get(expiredNumFiled);
String expiredUnit = (String) next.get(expiredUnitFiled);
int delExpiredDataNum = mysqlExpiredDataMapper.delExpiredData(tableName, columnName, Integer.parseInt(expiredNum), expiredUnit);
log.info("del expired mysql data table:{},column:{},expired:{}:{},size:{}", tableName, columnName, expiredNum, expiredUnit, delExpiredDataNum);
} else {
log.warn("current JSONObject param loss:{}", next.toJSONString());
}
}
} else {
log.warn("valid error :{}", inputData);
}
} catch (Exception e) {
e.printStackTrace();
}
}
mapper.java
@Repository
public interface MysqlExpiredDataMapper {
int delExpiredData(@Param("table_name") String table, @Param("column_name") String column, @Param("expired_num") int expiredNum, @Param("expired_unit") String expiredUnit);
}
mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhidaohulian.analysis.mapper.MysqlExpiredDataMapper">
<delete id="delExpiredData">
delete
FROM ${table_name}
WHERE ${column_name} < DATE_SUB(CURDATE(), INTERVAL #{expired_num} ${expired_unit});
</delete>
</mapper>
注意点:
1、${}和#{},的区别,是上面穿参数的关键;
2、< 是小于号
3、存在sql注入的危险,所以要在调用的时候做好参数校验,如果业务没有暴露的情况,那么这是一个不错的方案;
如果方案有不成熟的地方,欢迎大佬指出,小子优化