我的DAO实现在使用Tomcat7启动的服务器上抛出一个不可序列化的异常。知道是什么原因造成的吗?我的其他dao都没有这样做。
这是类:
package com.project.dao;
import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateTemplate;
import com.project.model.User;
public class UserDAOImpl implements UserDAO {
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
@Override
public void saveUser(User user) {
hibernateTemplate.saveOrUpdate(user);
}
@Override
@SuppressWarnings("unchecked")
public List<User> listUser() {
return hibernateTemplate.find("from User");
}
@Override
@SuppressWarnings("unchecked")
public User getUserByID(long userID) {
List<User> users= hibernateTemplate.find("from User where id = '" + userID + "'");
return users.size() > 0 ? users.get(0) : null;
}
}
这是我的配置:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<bean id="myDataSource"
class="org.apache.tomcat.dbcp.dbcp.BasicDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost/context</value>
</property>
<property name="username">
<value>someUser</value>
</property>
<property name="password">
<value>somePassword</value>
</property>
<!-- Disable the second-level cache -->
<!-- Echo all executed SQL to stdout -->
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="annotatedClasses">
<list>
<value>com.project.model.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="myUserDAO" class="com.project.dao.UserDAOImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</beans>
这是我的堆栈:
SEVERE: IOException while loading persisted sessions: java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: com.news.dao.UserDAOImpl
java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: com.project.dao.UserDAOImpl
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1332)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at org.apache.catalina.session.StandardSession.readObject(StandardSession.java:1600)
at org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:1073)
at org.apache.catalina.session.StandardManager.doLoad(StandardManager.java:284)
at org.apache.catalina.session.StandardManager.load(StandardManager.java:204)
at org.apache.catalina.session.StandardManager.startInternal(StandardManager.java:470)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5241)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1033)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:774)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1033)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:291)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:727)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.startup.Catalina.start(Catalina.java:620)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:303)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:431)
Caused by: java.io.NotSerializableException: com.project.dao.UserDAOImpl
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
at org.apache.catalina.session.StandardSession.writeObject(StandardSession.java:1676)
at org.apache.catalina.session.StandardSession.writeObjectData(StandardSession.java:1090)
at org.apache.catalina.session.StandardManager.doUnload(StandardManager.java:411)
at org.apache.catalina.session.StandardManager.unload(StandardManager.java:353)
at org.apache.catalina.session.StandardManager.stopInternal(StandardManager.java:497)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.StandardContext$4.run(StandardContext.java:5464)
at java.lang.Thread.run(Thread.java:662)
at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5481)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.ContainerBase.stopInternal(ContainerBase.java:1072)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.ContainerBase.stopInternal(ContainerBase.java:1072)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.StandardService.stopInternal(StandardService.java:502)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.StandardServer.stopInternal(StandardServer.java:748)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.startup.Catalina.stop(Catalina.java:693)
at org.apache.catalina.startup.Catalina.start(Catalina.java:654)
... 6 more
Jul 31, 2011 9:27:21 PM org.apache.catalina.session.StandardManager startInternal
SEVERE: Exception loading sessions from persistent storage
java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: com.project.dao.UserDAOImpl
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1332)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at org.apache.catalina.session.StandardSession.readObject(StandardSession.java:1600)
at org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:1073)
at org.apache.catalina.session.StandardManager.doLoad(StandardManager.java:284)
at org.apache.catalina.session.StandardManager.load(StandardManager.java:204)
at org.apache.catalina.session.StandardManager.startInternal(StandardManager.java:470)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5241)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1033)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:774)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1033)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:291)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:727)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.startup.Catalina.start(Catalina.java:620)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:303)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:431)
Caused by: java.io.NotSerializableException: com.project.dao.UserDAOImpl
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
at org.apache.catalina.session.StandardSession.writeObject(StandardSession.java:1676)
at org.apache.catalina.session.StandardSession.writeObjectData(StandardSession.java:1090)
at org.apache.catalina.session.StandardManager.doUnload(StandardManager.java:411)
at org.apache.catalina.session.StandardManager.unload(StandardManager.java:353)
at org.apache.catalina.session.StandardManager.stopInternal(StandardManager.java:497)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.StandardContext$4.run(StandardContext.java:5464)
at java.lang.Thread.run(Thread.java:662)
at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5481)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.ContainerBase.stopInternal(ContainerBase.java:1072)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.ContainerBase.stopInternal(ContainerBase.java:1072)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.StandardService.stopInternal(StandardService.java:502)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.StandardServer.stopInternal(StandardServer.java:748)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.startup.Catalina.stop(Catalina.java:693)
at org.apache.catalina.startup.Catalina.start(Catalina.java:654)
... 6 more
之所以会发生这种情况,是因为在代码的某个地方,您正在会话中存储UserDAO(或者您正在存储一个引用UserDAO的对象)。当您关闭Tomcat时,它会尝试序列化所有活动会话的完整对象图,然后当您重新启动它时,它会尝试恢复它们。问题的关键在于Tomcat使用"正常的"java对象序列化,这要求所有对象都是Serializable
。
如何补救:
- 不要在用户会话中存储不可序列化的对象(通常是一个好做法)。 使你的UserDAO可序列化。可能涉及实现
- 不要有Tomcat序列化会话(将
<Manager pathname="" />
添加到context.xml中,无论是在你自己的应用程序中,还是在conf/目录下的全局Tomcat context.xml中,在<Context>
元素中。这对您来说可能是最好的做法,除非您确实需要在重启时持久化会话。
Serializable
接口并将hibernateTemplate标记为transient
,因为我不认为HibernateTemplate
本身是可序列化的。如果你真的想让它工作,你可能需要添加一些代码来重新初始化hibernateTemplate。UserDaoImpl
如果要序列化,必须实现java.io.Serializable接口(您的堆栈跟踪表明尝试将类的实例写入对象流)。
要序列化的实例,以及该实例对象图中的所有对象,必须都是可序列化的。
来自javadocs for Serializable,
类的可序列化性是由类实现的java.io.Serializable接口……当遍历图时,对象可能遇到不支持Serializable接口的。在这种情况下,将抛出NotSerializableException并将标识不可序列化对象的类。
请注意,这些规则也有例外。我建议您阅读Java对象序列化规范,以全面了解对象序列化何时发生,以及如何避免NotSerializableException。
这里的其他答案很好地解释了序列化。因为这是谷歌的第一个结果,所以我想添加一些真正帮助我解决问题的信息。
异常消息本身并没有指明是哪个类中的哪个字段导致了这个问题。如果你不能使一个类可序列化,并且需要添加transient关键字,这样Java就不会尝试序列化一个字段,那么找出是哪个字段导致了这个问题可能会很棘手。
如果在Java/Tomcat启动时添加参数-Dsun.io.serialization.extendedDebugInfo=true
,异常将会更有用。下面是异常消息的示例:
java.io.NotSerializableException: za.co.abc.presentation.control.Three
- field (class "za.co.abc.presentation.control.Two", name: "three", type: "class za.co.abc.presentation.control.Three")
- object (class "za.co.abc.presentation.control.Two", za.co.abc.presentation.control.Two@fbbb20)
- field (class "za.co.abc.presentation.control.One", name: "two", type: "class za.co.abc.presentation.control.Two")
- object (class "za.co.abc.presentation.control.One", za.co.abc.presentation.control.One@17ee6c9)
- field (class "za.co.abc.presentation.control.Trail", name: "one", type: "class za.co.abc.presentation.control.One")
- root object (class "za.co.abc.presentation.control.Trail", {/click-tests/home.htm=home})
如果您确实使用transient关键字使字段不序列化,那么您可能必须在读取类时设置这些字段。您必须实现readObject()方法才能做到这一点。下面是一个例子:
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
// magically read all non-transient fields from input stream and populate their values
in.defaultReadObject();
someTransientField = new NotSerializableClass();
}