public class MyBatisSqlUtils { /** * 运行期获取MyBatis执行的SQL及参数 * @param id Mapper xml 文件里的select Id * @param parameterMap 参数 * @param sqlSessionFactory * @return */ public static MyBatisSql getMyBatisSql(String id, Map<String,Object> parameterMap,SqlSessionFactory sqlSessionFactory) { MyBatisSql ibatisSql = new MyBatisSql(); MappedStatement ms = sqlSessionFactory.getConfiguration().getMappedStatement(id); BoundSql boundSql = ms.getBoundSql(parameterMap); ibatisSql.setSql(boundSql.getSql()); List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); if (parameterMappings != null) { Object[] parameterArray = new Object[parameterMappings.size()]; ParameterMapping parameterMapping = null; Object value = null; Object parameterObject = null; MetaObject metaObject = null; PropertyTokenizer prop = null; String propertyName = null; String[] names = null; for (int i = 0; i < parameterMappings.size(); i++) { parameterMapping = parameterMappings.get(i); if (parameterMapping.getMode() != ParameterMode.OUT) { propertyName = parameterMapping.getProperty(); names = propertyName.split("\\."); if(propertyName.indexOf(".") != -1 && names.length == 2) { parameterObject = parameterMap.get(names[0]); propertyName = names[1]; } else if(propertyName.indexOf(".") != -1 && names.length == 3) { parameterObject = parameterMap.get(names[0]); // map if(parameterObject instanceof Map) { parameterObject = ((Map)parameterObject).get(names[1]); } propertyName = names[2]; } else { parameterObject = parameterMap.get(propertyName); } metaObject = parameterMap == null ? null : MetaObject.forObject(parameterObject); prop = new PropertyTokenizer(propertyName); if (parameterObject == null) { value = null; } else if (ms.getConfiguration().getTypeHandlerRegistry().hasTypeHandler(parameterObject.getClass())) { value = parameterObject; } else if (boundSql.hasAdditionalParameter(propertyName)) { value = boundSql.getAdditionalParameter(propertyName); } else if (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX) && boundSql.hasAdditionalParameter(prop.getName())) { value = boundSql.getAdditionalParameter(prop.getName()); if (value != null) { value = MetaObject.forObject(value).getValue(propertyName.substring(prop.getName().length())); } } else { value = metaObject == null ? null : metaObject.getValue(propertyName); } parameterArray[i] = value; } } ibatisSql.setParameters(parameterArray); } return ibatisSql; }
public class MyBatisSql { /** * 运行期 sql */ private String sql; /** * 参数 数组 */ private Object[] parameters; public void setSql(String sql) { this.sql = sql; } public String getSql() { return sql; } public void setParameters(Object[] parameters) { this.parameters = parameters; } public Object[] getParameters() { return parameters; } @Override public String toString() { if(parameters == null || sql == null) { return ""; } List<Object> parametersArray = Arrays.asList(parameters); List<Object> list = new ArrayList<Object>(parametersArray); while(sql.indexOf("?") != -1 && list.size() > 0 && parameters.length > 0) { sql = sql.replaceFirst("\\?", list.get(0).toString()); list.remove(0); } return sql.replaceAll("(\r?\n(\\s*\r?\n)+)", "\r\n"); }
以上贴的是实现代码,下面贴一段代码演示一下如何使用:
一、Mapper 文件
public interface AlarmMapper { public List<Alarm> queryAlarmData(@Param(value = "filter") Filter filter, @Param(value = "alarmStatus") AlarmStatus alarmStatus, @Param(value = "startDate") Date startDate, @Param(value = "endDate") Date endDate, @Param(value = "regionId") String regionId, @Param(value = "paramter") Map<String, Object> paramter, @Param(value = "startRow") int startRow, @Param(value = "endRow") int endRow) throws SQLException;}
二、Mapper 的xml文件此处就不写了,select 的ID 为 queryAlarmData
三、在service层调用 queryAlarmData方法
public List<Alarm> queryAlarmData(Filter filter, AlarmStatus alarmStatus, Date start, Date end, String regionId, Map<String, Object> paramter,int startRow, int endRow) { try { List<Alarm> alarms = mapper.queryAlarmData(filter, alarmStatus, start, end, regionId,paramter, startRow, endRow); Map<String,Object> parameterMap = new HashMap<String,Object>(); //存储参数 // key 要与Mapper中的参数名一致 parameterMap.put("filter", filter); parameterMap.put("alarmStatus", alarmStatus); parameterMap.put("startDate", start); parameterMap.put("endDate", end); parameterMap.put("regionId", regionId); parameterMap.put("paramter", paramter); parameterMap.put("startRow", startRow); parameterMap.put("endRow", endRow); logger.info(MyBatisSqlUtils.getMyBatisSql("queryAlarmData", parameterMap, sqlSessionFactory).toString()); return alarms; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } }
四、其实还可以用log4j来实现,将在下一篇博客贴出具体的实现代码(利用Spring的Aop以及自定义注解,实现系统日志功能)
五、欢迎各位指出本文的不妥之处,欢迎拍砖

1 楼 wufabeishang 2012-06-04
请问log4j怎么实现的啊?也能拦截到SQL执行的参数吗?
2 楼 cfqlove 2012-06-05
wufabeishang 写道
请问log4j怎么实现的啊?也能拦截到SQL执行的参数吗?
log4j.debug=truelog4j.rootLogger=INFO, stdout, alarmFile# Console output...log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%nlog4j.logger.org.junit=DEBUGlog4j.logger.junit=DEBUG# ehcache logger configlog4j.logger.net.sf.ehcache=DEBUG# ibatis logger configlog4j.logger.org.apache.mybatis=DEBUGlog4j.logger.java.sql.ResultSet=INFOlog4j.logger.java.sql=DEBUG# alarm logger configlog4j.logger.com.boco.monitor.*=INFO, alarmFilelog4j.appender.alarmFile=org.apache.log4j.DailyRollingFileAppenderlog4j.appender.alarmFile.File=${catalina.home}/alarm_logs/alarm_log.loglog4j.appender.alarmFile.layout=org.apache.log4j.PatternLayoutlog4j.appender.alarmFile.layout.ConversionPattern=%5p %d %C: %m%n# flex client logger configlog4j.logger.com.boco.monitor.flex.action.ClientLogger=DEBUG, clientLoglog4j.appender.clientLog=org.apache.log4j.DailyRollingFileAppenderlog4j.appender.clientLog.File=${catalina.home}/client_logs/client_log.loglog4j.appender.clientLog.layout=org.apache.log4j.PatternLayoutlog4j.appender.clientLog.layout.ConversionPattern=%5p %d %C: %m%n
这是我项目的log4j配置,你可以参考下。