【问题标题】:Java Catch and Display SqlExceptionHelperJava 捕获并显示 SqlExceptionHelper
【发布时间】:2019-06-16 19:43:12
【问题描述】:

由于其复杂性,使用 Hibernate JPA 在 Oracle DB 中执行本机查询, 我想捕捉从SqlExceptionHelper 类抛出的" ORA-01722: Nombre non valide " 之类的异常,但捕捉到的是:

类 javax.persistence.PersistenceException: 无法提取 结果集

记录器错误跟踪我但未捕获:

jdbc.spi.SqlExceptionHelper   : ORA-01722: Nombre non valide


BigDecimal customerId = null;
try {
    Query q = entityManager.createNativeQuery(
            "select acc.account_id as customerId from Account ...");
    customerId = (BigDecimal) q.getSingleResult();

} catch (Exception e) {

    logger.info("CLASS : " + e.getClass());
    if (e instanceof PersistenceException) {  // should display ORA-01722: Nombre non valide ?
        logger.info("ERRROR : " + e.getMessage());
        throw new SQLException(e.getMessage());
    }else
    if (e instanceof SQLException) {
        logger.info("ERRROR : " + e.getMessage());
        throw new SQLException(e.getMessage());
    }
    logger.info("NOOOOOOOOOOOOO : " + e.getMessage());
    throw new Exception(e.getMessage());
}

【问题讨论】:

  • 您不需要将其作为通用异常捕获。做检查实例是不必要的。您可以在不同的 catch 块中捕获不同的异常。
  • 我同意,但我想向前面的用户显示这个异常 [ORA-01722: Nombre non valide] 让他知道他的问题!

标签: java sql oracle hibernate


【解决方案1】:
@Entity
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "continentName" }) })
public class Continent implements Serializable 

    @NotEmpty(message = "continentName is a required field")
    private String continentName;

在你的控制器中,你可以用这个来处理@NotEmpty:

@ExceptionHandler({ ConstraintViolationException.class })
    public ResponseEntity<String> handleError1(HttpServletRequest req, Exception ex) {

        String msg = null;
        if (ex.getCause().getCause() instanceof ConstraintViolationException) {
            ConstraintViolationException e = (ConstraintViolationException) ex.getCause().getCause();
            Optional<ConstraintViolation<?>> optional = e.getConstraintViolations().stream().findFirst();
            msg = optional.isPresent() ? optional.get().getMessageTemplate() : ex.getMessage();
        }

        return new ResponseEntity<>(msg, HttpStatus.CONFLICT);
    }

这将返回“continentName 是必填字段”

再次在控制器中,此方法将处理唯一约束违规。假设您已经输入了一个值“Brucrumus”并尝试再次输入:

@ExceptionHandler({ DataIntegrityViolationException.class })
    public ResponseEntity<String> handleError2(HttpServletRequest req, Exception ex) {

        String msg = ex.getMessage();
        if (ex.getCause().getCause() instanceof SQLException) {
            SQLException e = (SQLException) ex.getCause().getCause();

            if (e.getMessage().contains("Key")) {
                msg = e.getMessage().substring(e.getMessage().indexOf("Key"));
            }
        }

【讨论】:

    【解决方案2】:

    SQLException 作为参数传递给SQLGrammarException 构造函数。

    您可以捕获它,提取根并显示本机 sql 错误或简单地重新抛出它:

    } catch (SQLGrammarException e) {
        logger.info("CLASS : " + e.getClass());
        throw e.getSQLException();
    } catch (Exception e){
       ...
    }
    

    【讨论】:

    • 捕获的类是 : CLASS : class javax.persistence.PersistenceException
    • 所以编辑帖子.. 明确指出 SQLGrammarException 被捕获
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-08
    • 2014-07-23
    相关资源
    最近更新 更多