在 ContextInitializer 方法中从 schema.sql 文件执行 sql 语句

Executing sql statement from schema.sql file in ContextInitializer method

我试图在 Listener 的 contextInitialized 方法中执行 sql 语句,但是当我 运行 gretty 本地服务器时,它抛出 RuntimeException 错误。我想不通,为什么。当我注释掉 ps.executeQuery();.

时,它不会 运行 出现任何错误
@Override
    public void contextInitialized(ServletContextEvent sce){

        ServletContext sc = sce.getServletContext();
        DataSource pool = new ConnectionPoolFactory().createConnectionPool();
        String sql = "create table test (id int);";

        try (Connection conn = pool.getConnection();
             PreparedStatement ps = conn.prepareStatement(sql)) {
            
             ps.executeQuery();

        } catch (SQLException e) {
            throw new RuntimeException();
        }

    }

“医生,按这里很痛!”

好吧,那就别这样了。

这个:

 } catch (SQLException e) {
   throw new RuntimeException();
 }

总之是疯了。你犯了一个有用的错误,它包括 5 个方便的方面,可以帮助你找出问题所在:

  • 异常的实际类型(可以是 SQLException 的子类;例如 'DatabaseNotAvailableException')
  • 与之关联的消息
  • 精确指向导致它的代码行的堆栈跟踪
  • 原因 - 异常可以有原因,它们本身就是异常(好吧,throwables)。原因通常比异常本身更有用。
  • 吞噬异常链。这很少有用。

您已决定将它们 全部 扔进垃圾箱,用一个不提供任何有用信息的 RuntimeException 代替它。

不要那样做。

正确的异常处理包括减少对方法的 throws 子句的恐惧。得到一个做 DB 东西的方法,并且这个方法的设计清楚地表明这样做(如果方法被命名为 'query' 或者包含任何明显表明 SQL 的词,答案很清楚:是的,确实如此),那么该方法 应该 声明为 throws SQLException,例如。

其次,在极少数情况下向前抛出它不起作用,如果你捕获到一个异常,你不想只记录它并继续,并且你不想在没有设置的情况下抛出其他异常首先是一个原因。这是标准的 'I do not know what to do and I do not want to spend any further time on thinking about it' 异常处理程序:

} catch (ThingIDoNotWantToThinkAbout e) {
    throw new RuntimeException("Unhandled", e);
}

, e 至关重要,它将实际异常设置为原因,以便您在堆栈跟踪和日志中实际看到它。 非常 常见 e.printStackTrace() 的标准异常处理。 不要这样做 - java 中 90% 的例子都是错误的。这会导致各种问题,因为 'logs' 转到 standarderr(这比让它们转到您正在操作的上下文的异常处理程序要灵活得多。例如,如果编写 Web 处理程序, e.printStackTrace() 只是转储堆栈。向上抛出异常将转储堆栈 允许框架添加有关触发问题的请求的信息,并提供合适的 HTTO 状态 500 错误页面。此外,仅通过 运行 printStackTrace,代码将继续执行,这显然不是您想要的:出了点问题 - 盲目继续将保证您的软件默默地做错事,或导致进一步的异常,从而导致一个错误导致数百个堆栈跟踪淹没您的 syserr。

一旦您解决了这里和代码中其他任何地方的这个问题,实际问题很可能会一目了然。 SQL 服务器宕机或 SQL.

语法错误