所以,雖然我還沒有找到一個完美的答案,但(仍希望),我已經至少發現了一種可能性:
通過使用Spring AOP我可以環繞每個映射方法方面(使用映射器接口)。然後,這個方面可以判斷,由映射器類名和調用的方法名,語句的ID,例如...
com.example.mappers.SomeMapper.findSomethingById
的看點可以使用配置(通過注入SqlSessionFactory
)趕上的PersistenceException通過MyBatis的拋出,並得到MappedStatement並提供給映射器的放慢參數(S)擁有的所有有關語句的細節(SQL +參數):
@Around("execution(* com.example.mappers..*(..))")
public Object beforeTransactional(final ProceedingJoinPoint joinPoint) throws Throwable {
try {
return joinPoint.proceed();
} catch (final PersistenceException ex) {
final MethodSignature signature = (MethodSignature) joinPoint.getSignature();
final Class<?> mapperInterface = findMapper(joinPoint.getTarget());
// StatementInfo : simple bean to store sql statement and parameter object
final StatementInfo info = findMappedStatement(signature.getMethod(), mapperInterface, joinPoint.getArgs());
// a custom Exception extends PersistenceException
throw new CustomPersistenceException(info, ex);
}
protected SQLException findSqlException(Throwable ex) {
while (ex != null && !(ex instanceof SQLException)) {
ex = ex.getCause();
}
return (SQLException) ex;
}
protected StatementInfo findMappedStatement(final Method method, final Class<?> mapperInterface, final Object[] args) {
final String statementId = mapperInterface.getPackage().getName() + "." + mapperInterface.getSimpleName() + "." + method.getName();
final MappedStatement mappedStatement = this.configuration.getMappedStatement(statementId);
final Object arg = args == null || args.length == 0 ? null : args[0];
final BoundSql boundSql = mappedStatement.getBoundSql(arg);
final String sql = StringUtils.normalizeSpace(boundSql.getSql());
return new StatementInfo(sql, arg);
}
不過,該解決方案是遠遠不夠完善,因爲它不允許我獲取實際創建錯誤的sql語句的sql代碼,只是調用「父」sql語句。例如:
如果我的(父)語句調用各種其他(子)語句,例如關聯或集合,並且其中一個會創建一個錯誤,那麼我的解決方案僅提供有關父語句而不是子語句的信息這實際上會導致錯誤。所以,另一種解決方案將是可取的。
另外我不能使用乾淨的PersistenceExceptionTranslator,因爲在mapper方法結束之前調用翻譯器,這是不幸的,因爲這意味着我將不得不通過AOP重新發明整個異常轉換。
你讀過的MyBatis文檔中的內容? https://mybatis.github.io/mybatis-3/logging.html –
我知道如何記錄生成的查詢,這不是問題。我只是沒有任何想法在錯誤處理過程中獲取這些信息,特別是在可以同時運行數十個查詢的多用戶設置中。 –