package com.yiqiniu.easytrans.log.impl; import java.util.Date; import java.util.List; import javax.annotation.Resource; import javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; import com.yiqiniu.easytrans.log.TransactionLogWritter; import com.yiqiniu.easytrans.log.vo.Content; import com.yiqiniu.easytrans.serialization.ObjectSerializer; public class DataBaseTransactionLogWritterImpl implements TransactionLogWritter { private DataSource dataSource; private Logger LOG = LoggerFactory.getLogger(this.getClass()); private DataSourceTransactionManager transactionManager; TransactionTemplate transactionTemplate; @Resource private ObjectSerializer objectSerializer; public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; transactionManager = new DataSourceTransactionManager(dataSource); transactionTemplate = new TransactionTemplate(transactionManager, new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW)); } private JdbcTemplate jdbcTemplate; private JdbcTemplate getJdbcTemplate(){ if(jdbcTemplate == null){ jdbcTemplate = new JdbcTemplate(dataSource); } return jdbcTemplate; } @Override public void appendTransLog(final String appId, final String busCode, final String trxId, final List<Content> newOrderedContent, final boolean finished) { transactionTemplate.execute(new TransactionCallback<Object>(){ @Override public Object doInTransaction(TransactionStatus status) { JdbcTemplate localJdbcTemplate = getJdbcTemplate(); //unfinished tag localJdbcTemplate.update("insert into `trans_log_unfinished` VALUES(?,?) on DUPLICATE KEY UPDATE create_time = create_time;", DataBaseTransactionLogDetailDo.getTransId(appId, busCode, trxId),new Date()); //concrete log int logUpdateConut = localJdbcTemplate.update("INSERT INTO `trans_log_detail` (`log_detail_id`, `trans_log_id`, `log_detail`, `create_time`) VALUES (NULL, ?, ?, ?);", DataBaseTransactionLogDetailDo.getTransId(appId, busCode, trxId), objectSerializer.serialization(newOrderedContent), new Date() ); if(logUpdateConut != 1){ throw new RuntimeException("write log error!"); } if(LOG.isDebugEnabled()){ LOG.debug(newOrderedContent.toString()); } if(finished){ //remove unfinished tag localJdbcTemplate.update("DELETE FROM trans_log_unfinished WHERE trans_log_id = ?;", DataBaseTransactionLogDetailDo.getTransId(appId,busCode,trxId)); } return null; } }); } @Override public void cleanFinishedLogs(String appId,final Date cleanBefore) { transactionTemplate.execute(new TransactionCallback<Object>(){ @Override public Object doInTransaction(TransactionStatus status) { JdbcTemplate localJdbcTemplate = getJdbcTemplate(); localJdbcTemplate.update("delete from trans_log_detail where create_time < ? and trans_log_id not in (select trans_log_id from trans_log_unfinished);",cleanBefore); return null; } }); } }