【发布时间】:2021-11-17 08:41:55
【问题描述】:
我用reflect来关闭资源,就像这样
public static void closeResource(Object ... resources) throws Exception {
String methodName = "close";
for (Object obj : resources){
System.out.println(obj);
Method m = obj.getClass().getDeclaredMethod(methodName);
m.setAccessible(true);
m.invoke(obj);
}
}
但是当我用这个方法关闭PreparedStatement的时候,出现了一个Exception,就像这样
JDBCUtils.closeResource(resultSet, connection, preparedStatement);
异常如下
java.lang.NoSuchMethodException: com.mysql.cj.jdbc.ClientPreparedStatement.close()
at java.base/java.lang.Class.getDeclaredMethod(Class.java:2613)
at JDBC.Utils.JDBCUtils.closeResource(JDBCUtils.java:45)
at JDBC.Query.jobsQueryTest.query(jobsQueryTest.java:63)
at JDBC.Query.jobsQueryTest.main(jobsQueryTest.java:22)
前两个资源已经关闭成功,但最后一个失败了。
我尝试打印 PreparedStatement(java.sql.PreparedStatement) 的对象,但输出是 com.mysql.cj.jdbc.ClientPreparedStatement
我感到很困惑。
【问题讨论】:
-
你为什么要使用这个,而不仅仅是使用 try-with-resources?另外,考虑使用
AutoCloseable而不是Object和反射。 -
关闭连接也可能关闭语句。此外,
ClientPreparedStatement类上没有 close() 方法。 -
无论如何,您可能需要使用
getMethod,因为getDeclaredMethod只返回在类本身中声明的方法,而不是在超类或超接口中声明和实现的方法。 -
ClientPreparedStatement和PreparedStatement是什么关系
-
com.mysql.cj.jdbc.ClientPreparedStatement是java.sql.PreparedStatement的实现。但是,它没有声明close(),因为它已经在其父类com.mysql.cj.jdbc.StatementImpl中实现了。但我再次重申,你不应该使用JDBCUtils.closeResource这样的东西。请改用 try-with-resources。