Java tutorial
/** * Copyright (c) 2005-2009 springside.org.cn * * Licensed under the Apache License, Version 2.0 (the "License"); * * $Id: JdbcAppenderTask.java 353 2009-08-22 09:33:28Z calvinxiu */ package org.springside.examples.showcase.log.appender; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.Resource; import javax.sql.DataSource; import org.apache.log4j.spi.LoggingEvent; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils; import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; import org.springside.examples.showcase.queue.BlockingConsumer; import com.google.common.collect.Lists; import com.google.common.collect.Maps; /** * Queuelog4j event?. * * ??Queue,??Jdbc??. * ???,PeriodConsumer???. * * @see BlockingConsumer * * @author calvin */ public class JdbcLogWriter extends BlockingConsumer { protected String sql; protected int batchSize = 10; protected List<LoggingEvent> eventsBuffer = Lists.newArrayList(); protected SimpleJdbcTemplate jdbcTemplate; protected TransactionTemplate transactionTemplate; /** * Named Parameterinsert sql. * * Named Parameter???AppenderUtils?. */ public void setSql(String sql) { this.sql = sql; } /** * ???, 10. */ public void setBatchSize(int batchSize) { this.batchSize = batchSize; } /** * ?DataSourcejdbcTemplate. */ @Resource public void setDataSource(DataSource dataSource) { jdbcTemplate = new SimpleJdbcTemplate(dataSource); } /** * ?PlatformTransactionManagertransactionTemplate. */ @Resource public void setDefaultTransactionManager(PlatformTransactionManager defaultTransactionManager) { transactionTemplate = new TransactionTemplate(defaultTransactionManager); } /** * ??,?buffer,bufferbatchSize?. */ @Override protected void processMessage(Object message) { LoggingEvent event = (LoggingEvent) message; eventsBuffer.add(event); if (logger.isDebugEnabled()) { logger.debug("get event: {}", new LoggingEventWrapper(event).convertToString()); } //BufferSize??? if (eventsBuffer.size() >= batchSize) { updateBatch(); } } /** * Buffer???. */ @SuppressWarnings("unchecked") public void updateBatch() { try { //?, ?jdbc??. int i = 0; Map[] paramMapArray = new HashMap[eventsBuffer.size()]; for (LoggingEvent event : eventsBuffer) { paramMapArray[i++] = parseEvent(event); } final SqlParameterSource[] batchParams = SqlParameterSourceUtils.createBatch(paramMapArray); //??,?. transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { try { jdbcTemplate.batchUpdate(getActualSql(), batchParams); if (logger.isDebugEnabled()) { for (LoggingEvent event : eventsBuffer) { logger.debug("saved event: {}", new LoggingEventWrapper(event).convertToString()); } } } catch (DataAccessException e) { status.setRollbackOnly(); handleDataAccessException(e, eventsBuffer); } } }); //?Buffer eventsBuffer.clear(); } catch (Exception e) { logger.error("????.", e); } } /** * ?,?buffer??. */ @Override protected void clean() { if (!eventsBuffer.isEmpty()) { updateBatch(); } logger.debug("cleaned task {}", this); } /** * ?Event, Parameter Map, sqlNamed Parameter. */ protected Map<String, Object> parseEvent(LoggingEvent event) { Map<String, Object> parameterMap = Maps.newHashMap(); LoggingEventWrapper eventWrapper = new LoggingEventWrapper(event); parameterMap.put("thread_name", eventWrapper.getThreadName()); parameterMap.put("logger_name", eventWrapper.getLoggerName()); parameterMap.put("log_time", eventWrapper.getDate()); parameterMap.put("level", eventWrapper.getLevel()); parameterMap.put("message", eventWrapper.getMessage()); return parameterMap; } /** * ?????,?. */ protected void handleDataAccessException(DataAccessException e, List<LoggingEvent> errorEventBatch) { if (e instanceof DataAccessResourceFailureException) { logger.error("database connection error", e); } else { logger.error("other database error", e); } for (LoggingEvent event : errorEventBatch) { logger.error("event insert to database error, ignore it: " + new LoggingEventWrapper(event).convertToString(), e); } } /** * ???sql??,?sql?????? LOG_2009_02_31. */ protected String getActualSql() { return sql; } }