问题描述
我试图在 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 中的语法错误。