我正在使用JSF 1.2并尝试使用<a4j:keepAlive beanName="reportController">
,但是我不断收到此错误:
HTTP 状态 500
原因:java.io.NotSerializableException: com.mysql.jdbc.DatabaseMetaData at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1183
我正在尝试使用<a4j:keepAlive beanName="reportController">
因为当我搜索特定报表然后尝试对数据表中的数据进行排序时,它似乎丢失了数据表中的所有数据。
原因:java.io.NotSerializableException: com.mysql.jdbc.DatabaseMetaData
当您掌握java.sql.Connection
甚至直接DatabaseMetaData
作为可序列化类的实例变量时,就会发生这种情况,如下所示。
public class ReportController implements Serializable {
private Connection connection; // BAD!!
private DatabaseMetaData metadata; // BAD!!
// ...
}
您不应该声明和获取外部资源,例如java.sql.Connection
、Statement
和ResultSet
,也不应该将其属性声明和获取为类的实例变量。您应该尽快获取、使用和关闭它们,仅在方法本地范围内。从ReportController
bean 中删除这些实例变量,将它们移动到方法局部范围内,这个问题就会消失。只有 DataSource
(服务器管理的连接池(作为实例变量是可以的。
public class ReportController implements Serializable {
@Resource("jdbc/someDB")
private DataSource dataSource;
public void someMethod() {
try (Connection connection = dataSource.getConnection()) { // OK.
// ...
}
}
// ...
}
<a4j:keepAlive>
并不完全是此问题的原因。它只记住同一页面上跨 HTTP 回发请求的 HTTP 会话中的 Bean 实例。HTTP 会话属性本质上通常是序列化的。此序列化只是触发并暴露了隐藏的设计问题。易失性的一次性资源,如数据库连接、语句、元数据、输入流、输出流等,绝对不应该是可序列化的,因此会出现此异常。
另请参阅:
- 在多线程系统中使用静态 java.sql.Connection 实例是否安全?
- 返回结果集