一般线上项目都是将日志进行关闭,因为mybatis日志打印,时间长了,会占用大量的内存,如果我想在我指定的地方进行打印sql情况,怎么玩呢!
下面这个场景:
某天线上的项目出bug了,日志打印出来是更新成功的,但是数据库的数据却没有更新,这时候我想给执行这条sql打印出来,方便查看,但是一旦开启mybatis的日志打印功能,就回去全局打印所有的日志,我只想在我想打印的地方打印sql,这时候怎么办呢!见下面的列子:
我想在下面红色箭头处打印这句sql
这时候怎么做呢,咱们可以这样,先将SqlSessionFactory对象注入进来,
如下图:
private final SqlSessionFactory sqlSessionFactory;
@Autowired
public LoginService(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
然后在需要打印的地方加上下面的代码即可:
// 获取执行的SQL语句并打印
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Configuration sqlSessionConfiguration = sqlSession.getConfiguration();
BoundSql boundSql = sqlSessionConfiguration
.getMappedStatement("com.green.testlocalhost.mapper.AdminUserMapper.selectOneByExample")
.getSqlSource()
.getBoundSql(userExample);
String sql = StringUtils.getExecSql(sqlSessionConfiguration, boundSql);
System.out.println("本次执行的sql语句::" + sql);
}
注意:com.green.testlocalhost.mapper.AdminUserMapper.selectOneByExample 这个是StatementId,也就是你主动调用db框架的那个类或者接口的包路径(com.green.testlocalhost.mapper.AdminUserMapper),然后在路径后面拼接调用的方法(selectOneByExample )即可
用到的工具方法如下:
/**
* 获取执行的sql语句
* @param configuration
* @param boundSql
* @return
*/
public static String getExecSql(Configuration configuration, BoundSql boundSql) {
try {
Object parameterObject = boundSql.getParameterObject();
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
if (!parameterMappings.isEmpty() && parameterObject != null) {
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
sql = sql.replaceFirst("\\?", getParameterValue(parameterObject));
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
for (ParameterMapping parameterMapping : parameterMappings) {
String propertyName = parameterMapping.getProperty();
Object obj;
if (metaObject.hasGetter(propertyName)) {
obj = metaObject.getValue(propertyName);
sql = sql.replaceFirst("\\?", getParameterValue(obj));
} else if (boundSql.hasAdditionalParameter(propertyName)) {
obj = boundSql.getAdditionalParameter(propertyName);
sql = sql.replaceFirst("\\?", getParameterValue(obj));
}
}
}
}
return sql;
} catch (Exception var11) {
return "";
}
}
private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static String getParameterValue(Object obj) {
String value;
if (obj instanceof String) {
value = "'" + obj + "'";
} else if (obj instanceof Date) {
value = "'" + SIMPLE_DATE_FORMAT.format(obj) + "'";
} else if (obj != null) {
value = obj.toString();
} else {
value = "";
}
return value;
}
这样就可以在你指定的代码地方打印sql而不是全局打印sql了