1. 程式人生 > >異步往數據庫中插入每個用戶的增刪改操作日誌

異步往數據庫中插入每個用戶的增刪改操作日誌

run while empty sem 批量 異步 exp rri des

  • [x] ++我們需要一個工具類++

用工具類異步向數據庫中插入用戶的操作日誌

工具類代碼如下:
package com.dp.api.util;

import com.dp.common.dao.DaoUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.model.TSysUpdateLog;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @Author: DaleyZou
 * @Description: 用於向數據庫中寫入操作日誌,十個數據寫一條記錄
 * @Date: Created in 14:56 2018/12/28
 * @Modified By:
 */
@Service
public class OperationLogSaver {

    protected static Logger logger = LoggerFactory.getLogger(OperationLogSaver.class);

//    @Autowired
//    private TSysUpdateLogMapper tSysUpdateLogMapper;

    @Autowired
    private DaoUtil daoUtil;
    private LinkedBlockingQueue<TSysUpdateLog> queue;

    private static int dbCacheSize = 500;
    private static Thread saverdbThread;

    public OperationLogSaver() {
        init();
    }

    public void putRecord(List<TSysUpdateLog> records){
        queue.addAll(records);
    }

    public void putRecord(TSysUpdateLog record){
        try {
            queue.put(record);
        } catch (InterruptedException e) {
            logger.error(e.getMessage(),e);
        }
    }

    public void init() {
        queue = new LinkedBlockingQueue<TSysUpdateLog>();

        saverdbThread = new Thread("operationLog-Saver") {
            @Override
            public void run() {
                try {
                    while (true) {
                        if(null == queue || queue.isEmpty()){
                            Thread.sleep(500);
                            continue;
                        }
                        List<TSysUpdateLog> list = new ArrayList<TSysUpdateLog>();
                        queue.drainTo(list, dbCacheSize);
                        if(null != list && list.size() > 0){
//                            tSysUpdateLogMapper.batchInsert(list);
                            daoUtil.batchInsert("tk.mybatis.mapper.dao.TSysUpdateLogMapper","insertSelective",list);
                            Thread.sleep(1000);
                        }
                    }
                } catch (Exception t) {
                    logger.error("Unexpected exception on Thread %s!", t);
                }
            }
        };
        saverdbThread.start();
    }
}
借用 mybatis 向數據庫批量插入操作記錄
package com.dp.common.dao;

import java.util.List;

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;


@Repository("daoUtil")
public class DaoUtil {
    protected final Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private SqlSessionTemplate sqlSessionTemplate;

    public final <O> boolean batchInsert(String sqlMapNameSpace,String statementName, final List<O> list) {
        boolean rt = true;
        // 此代碼沒有使用spring的事務,改動手動控制,如果和原spring事務一起使用,將無法回滾,必須註意,最好單獨使用;
        SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
        int size = list.size();
        try {
            for (int i = 0; i < size; i++) {
                O paramObj = list.get(i);
                sqlSession.insert(sqlMapNameSpace + "." + statementName, paramObj);
                if ((i + 1) % 200 == 0 || (i + 1) == (size)) {
                    // 手動每200條提交一次,提交後無法回滾
                    sqlSession.commit();
                    // 清理緩存,防止溢出
                    sqlSession.clearCache();
                }
            }
        } catch (Exception e) {
            // 沒有提交的數據可以回滾
            sqlSession.rollback();
            logger.error(e.getMessage(),e);
            rt = false;
        } finally {
            sqlSession.close();
        }
        return rt;
    }
}
在正常業務程序中這樣使用異步寫日誌的工具類
@Autowired
private OperationLogSaver operationLogSaver;

// 保存操作記錄
List<TSysUpdateLog> records = new ArrayList<>();

// 異步寫日誌
operationLogSaver.putRecord(records);

異步往數據庫中插入每個用戶的增刪改操作日誌