gpt4 book ai didi

java - MyBatis-Spring PersistenceExceptionTranslator - SQL 语句?

转载 作者:行者123 更新时间:2023-11-30 10:57:44 27 4
gpt4 key购买 nike

有没有机会从 Spring DataSource 或类似的东西以某种方式在 MyBatis 中获取当前的 sql 语句?不幸的是,MyBatisExceptionTranslator 只将语句放在消息中,这使得它很难使用。此外,它似乎没有将实际参数放在某处。

我想做的是为 MyBatis/Oracle 编写一个 PersistenceExceptionTranslator,它能够使用当前语句和给该语句的参数来确定最终的异常,从而允许更好的错误消息。有机会这样做吗?

有机会吗?

最佳答案

因此,虽然我还没有找到完美的答案(仍然希望如此),但我至少找到了一种可能性:

通过使用 Spring AOP,我可以围绕每个映射器方法包装一个方面(使用映射器接口(interface))。然后这方面可以通过映射器类名和调用的方法名来确定语句的id,例如...

com.example.mappers.SomeMapper.findSomethingById

Aspect 可以使用 Configuration(通过注入(inject)的 SqlSessionFactory)捕获 MyBatis 抛出的 PersistenceException 并获取 MappedStatement 和提供给映射器的参数,以获取有关语句的所有详细信息(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,因为转换器会在映射器方法完成之前被调用,这很不幸,因为这意味着我将不得不通过 AOP 重新发明整个异常转换。

关于java - MyBatis-Spring PersistenceExceptionTranslator - SQL 语句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32475595/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com