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

问题描述

我试图在 Listener 的 contextinitialized 方法中执行 sql 语句,但是当我运行 grtty 本地服务器时,它抛出 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”)
  • 与之关联的消息
  • 堆栈跟踪精确指向导致它的代码行
  • 原因 - 异常可以有原因,这些原因本身就是异常(好吧,可抛出的)。原因通常比异常本身更有用。
  • 吞入异常链。这很少有用。

您已决定将它们全部扔进垃圾桶,用单个 RuntimeException 替换它,该异常不提供任何类型的有用信息。

不要那样做。

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

其次,在极少数情况下继续抛出它不起作用,如果你捕捉到一个异常,你不想只是记录它并继续,你也不想在没有设置原因的情况下抛出其他一些异常第一的。这是标准的“我不知道该做什么,我不想再花时间考虑它”异常处理程序:

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

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

一旦您在这里和代码中的其他地方解决了这个问题,实际问题很可能会一目了然。 SQL 服务器出现故障或 SQL 中的语法错误。