java.io.NotSerializableException:com.mysql.jdbc.DatabaseMetaData

时间:2016-02-03 07:18:27

标签: java mysql jsf serialization jdbc

我正在使用JSF 1.2并尝试使用<a4j:keepAlive beanName="reportController">,但我继续收到此错误:

  

HTTP状态500

     

引起:java.io.NotSerializableException:java.io.ObjectOutputStream.writeObject0中的com.mysql.jdbc.DatabaseMetaData(ObjectOutputStream.java:1183

我正在尝试使用<a4j:keepAlive beanName="reportController">因为当我搜索特定报告然后尝试对dataTable中的数据进行排序时,它似乎丢失了dataTable中的所有数据。

1 个答案:

答案 0 :(得分:2)

  

引起: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.ConnectionStatementResultSet,也不应将其属性作为类的实例变量。您应该尽快获取,使用和关闭它们,完全在方法本地范围内。从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会话属性本质上通常是序列化的。此序列化仅触发并暴露了您隐藏的设计问题。易失性的一次性使用资源,如数据库连接,语句,元数据,输入流,输出流等,绝对不应该是可序列化的,因此这个例外。

另见: