Mybatis分表操作,动态新建表

SpringbBoot + mybatis(直接在接口方法上写sql) + mysql

解决问题

1.怎么动态新建表

2.怎么一个查询/新增 方法映射多表

3.怎么知道什么是否该新建表,需要新建的表是否在数据库存在

实体类

public class HistoryRule {

    private Long sendruleHistoryId;
    private Long orderId;
    private String adminRule;
    private Date sendTime;
    private String isRollback;
}

dao层


import org.apache.ibatis.annotations.*;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @Description: 历史规则dao
 * @Author: cyg
 * @Date: 2019/8/2
 * @Version:
 **/
@Repository
@Mapper
public interface HistoryDao {


    //批量插入历史规则
    @Insert({""})
    @Cacheable(value = "historyCache", key = "#root.methodName")
    @Options(useGeneratedKeys = true, keyColumn = "pre_rollback_id")
    int insertMoreHistoryRule(@Param(value = "historyRules") List historyRules,
                              @Param("tableName") String tableName);

    //单条插入历史规则
    @Insert("insert into ${tableName}(order_id, admin_rule, send_time, is_rollback) values " +
            "(#{historyRule.orderId}, #{historyRule.adminRule}, #{historyRule.sendTime}, #{historyRule.isRollback})")
    @Cacheable(value = "historyCache", key = "#historyRule.sendruleHistoryId+#root.methodName")
    int insertOneHistoryRule(@Param(value = "historyRule") HistoryRule historyRule,
                             @Param("tableName") String tableName);

    //单条删除Rollback
    @Delete("delete from ${tableName} where sendrule_history_id = #{historyRule.sendruleHistoryId}")
    void deleteOneHistoryRule(@Param(value = "historyRule") HistoryRule historyRule,
                             @Param("tableName") String tableName);


    @Select("SELECT table_name FROM information_schema.`tables` WHERE TABLE_SCHEMA=#{dbName}" +
            "AND table_name LIKE 'aps_openresty_rule_history_%'")
    //查询表名list
    @Cacheable(value = "historyCache", key = "1")
    List getHistoryTableNameList(@Param("dbName") String dbName);


    @Update("create table ${tableName} (" +
            " `sendrule_history_id` bigint(12) NOT NULL AUTO_INCREMENT," +
            "  `order_id` bigint(12) NULL DEFAULT NULL," +
            "  `admin_rule` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL," +
            "  `send_time` datetime(0) NULL DEFAULT NULL," +
            "  `is_rollback` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL," +
            "  PRIMARY KEY (`sendrule_history_id`) USING BTREE)" +
            "ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic")
    //创建数据表
    @CacheEvict(value = "historyCache", key = "1")
    void createHistoryTable(@Param("tableName") String tableName);
}

 

上面dao层有一个 createHistoryTable 和 getHistoryTableNameList 是关键,一个是新建表,一个是查询某个数据库所有满足条件的表名,list返回。

工具类



import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.List;

/**
 * @Description: 分表util
 * @Author: cyg
 * @Date: 2019/8/8
 * @Version:
 **/
@Component
public class SubTableUtil {

    private final static String dbName = "base_aiop";
    private final static String preHistoryTableName = "aps_openresty_rule_history_";
    @Autowired
    private HistoryDao historyDao;
 

    //动态创建历史规则表
    public void createHistoryTable() {
        //得到当前表的所有分表
        List tableNameList = getHistoryTableNameList();
        String tableName = getHistoryTableNameByNowDate(preHistoryTableName);
        //如果所有分表中不包含当前月份的分表,则新建表
        if (!tableNameList.contains(tableName)) {
            historyDao.createHistoryTable(tableName);
            logger.info("创建历史规则分表:" + tableName);
        } else {
            logger.info("历史规则分表:" + tableName + "已经存在");
        }
    }


    //查询数据库类似 "aps_openresty_rule_history_"的表名
    public List getHistoryTableNameList() {
        return historyDao.getHistoryTableNameList(dbName);
    }


    //获取历史规则分表名
    public String getHistoryTableName() {
        String tableName = getHistoryTableNameByNowDate(preHistoryTableName);
        return tableName;
    }


    //根据当前日期返回表名
    private String getHistoryTableNameByNowDate(String preTableName) {
        String calendarYearAndMonth = getData();
        return preTableName + calendarYearAndMonth;
    }

    //获取当前日期,格式 201908
    private String getData() {
        Calendar calendar = Calendar.getInstance();
        String calendarMounth = null;
        //日历获取的月份为0-11,所以这里加1
        if (calendar.get(Calendar.MONTH) < 9) {
            calendarMounth = "0" + (calendar.get(Calendar.MONTH) + 1);
        } else {
            calendarMounth = String.valueOf((calendar.get(Calendar.MONTH) + 1));
        }
        return calendar.get(Calendar.YEAR) + calendarMounth;
    }
}

 

工具类里面实现了

1.获取所有分表名

2.获取当前月的分表名

3.创建表

 

 

新建表,定时类,使用定时任务、cron表达式,每月月初新建表

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Description: 定时新建表
 * @Author: cyg
 * @Date: 2019/8/8
 * @Version:
 **/
@Component
@Transactional
public class CreateTableTask {

    //private Logger logger = LoggerFactory.getLogger(Rollback2History.class);
    @Autowired
    private SubTableUtil subTableUtil;

    @Scheduled(cron = "0 0 0 1 1-12 ? ")
    public void createTable() {
        try {
            //新建历史规则表
            subTableUtil.createHistoryTable();
        } catch (Exception e) {
            //logger.info("新建表失败:" + e);
        }
    }
}

删除,插入代码

//得到当月分表名
String tableName = subTableUtil.getHistoryTableName();
//执行插入代码
historyDao.insertOneHistoryRule(historyRule,tableName)
//执行删除代码
historyDao.deleteOneHistoryRule(historyRule,tableName)

注意点:这样默认操作的都是最新的表,历史表的操作得另外写拼接表名的方法。

你可能感兴趣的:(技术积累,Java)