jeesite是一个开源的springMVC+Mybatis框架,其功能十分强大,节省了很多基础编码的时间,尤其是生成代码的功能。相关文章网上已有很多,不做赘述。此篇文章仅为平时使用笔记,欢迎各位留言探讨。
(一)打印SQL,让每次操作数据库都在控制台打印SQL语句。
1、在 spring-context.xml 配置文件的 sqlSessionFactory 中添加如下配置:
<!-- 性能拦截器,用于输出每条SQL语句及其执行时间,会影响一定性能,正式环境要关闭 -->
<property name="plugins">
<array>
<bean class="com.thinkgem.jeesite.common.utils.PerformanceInterceptor"></bean>
</array>
</property>
2、在包 com.thinkgem.jeesite.common.utils 下添加一个 java 文件:
package com.thinkgem.jeesite.common.utils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.type.TypeHandlerRegistry;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Properties;
/**
* MyBatis 性能拦截器,用于输出每条 SQL 语句及其执行时间
*
* @author huangyong
* @since 1.0.0
*/
@Intercepts({
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class PerformanceInterceptor implements Interceptor {
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
Object parameterObject = null;
if (invocation.getArgs().length > 1) {
parameterObject = invocation.getArgs()[1];
}
String statementId = mappedStatement.getId();
BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
Configuration configuration = mappedStatement.getConfiguration();
String sql = getSql(boundSql, parameterObject, configuration);
long start = System.currentTimeMillis();
Object result = invocation.proceed();
long end = System.currentTimeMillis();
long timing = end - start;
System.out.println("耗时:" + timing + " ms" + " - id:" + statementId + " - Sql:" + sql);
return result;
}
@Override
public Object plugin(Object target) {
if (target instanceof Executor) {
return Plugin.wrap(target, this);
}
return target;
}
@Override
public void setProperties(Properties properties) {
}
private String getSql(BoundSql boundSql, Object parameterObject, Configuration configuration) {
String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
if (parameterMappings != null) {
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) {
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
sql = replacePlaceholder(sql, value);
}
}
}
return sql;
}
private String replacePlaceholder(String sql, Object propertyValue) {
String result;
if (propertyValue != null) {
if (propertyValue instanceof String) {
result = "'" + propertyValue + "'";
} else if (propertyValue instanceof Date) {
result = "'" + DATE_FORMAT.format(propertyValue) + "'";
} else {
result = propertyValue.toString();
}
} else {
result = "null";
}
return sql.replaceFirst("\\?", result);
}
}