CacheException: Error serializing object. Cause: java.io.NotSerializableException
阿新 • • 發佈:2018-11-25
錯誤堆疊資訊如下:
at org.apache.ibatis.cache.decorators.SerializedCache.serialize(SerializedCache.java:102) at org.apache.ibatis.cache.decorators.SerializedCache.putObject(SerializedCache.java:56) at org.apache.ibatis.cache.decorators.LoggingCache.putObject(LoggingCache.java:51) at org.apache.ibatis.cache.decorators.SynchronizedCache.putObject(SynchronizedCache.java:45) at org.apache.ibatis.cache.decorators.TransactionalCache.flushPendingEntries(TransactionalCache.java:122) at org.apache.ibatis.cache.decorators.TransactionalCache.commit(TransactionalCache.java:105) at org.apache.ibatis.cache.TransactionalCacheManager.commit(TransactionalCacheManager.java:44) at org.apache.ibatis.executor.CachingExecutor.close(CachingExecutor.java:61) at org.apache.ibatis.session.defaults.DefaultSqlSession.close(DefaultSqlSession.java:264) at TestSelectAll.testSelectAll(TestSelectAll.java:34) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206) Caused by: java.io.NotSerializableException: org.entity.User at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348) at java.util.ArrayList.writeObject(ArrayList.java:747) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348) at org.apache.ibatis.cache.decorators.SerializedCache.serialize(SerializedCache.java:97) ... 33 more
錯誤分析:
錯誤的提示資訊翻譯後的意思是mybatis快取異常,正在序列化物件錯誤,原因是不能序列化異常。詳細的堆疊資訊如上,從堆疊資訊中可以看出 SerializedCache.serialize(SerializedCache.java:102)表示是SerializedCache物件102行呼叫serialize()方法報錯了,看看原始碼,
private byte[] serialize(Serializable value) { try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(value); oos.flush(); oos.close(); return bos.toByteArray(); } catch (Exception e) { throw new CacheException("Error serializing object. Cause: " + e, e); } }
上面程式碼的oos.writeObject(value);該行程式碼是寫物件,原始碼如下:
/** * Write the specified object to the ObjectOutputStream. The class of the * object, the signature of the class, and the values of the non-transient * and non-static fields of the class and all of its supertypes are * written. Default serialization for a class can be overridden using the * writeObject and the readObject methods. Objects referenced by this * object are written transitively so that a complete equivalent graph of * objects can be reconstructed by an ObjectInputStream. * * <p>Exceptions are thrown for problems with the OutputStream and for * classes that should not be serialized. All exceptions are fatal to the * OutputStream, which is left in an indeterminate state, and it is up to * the caller to ignore or recover the stream state. * * @throws InvalidClassException Something is wrong with a class used by * serialization. * @throws NotSerializableException Some object to be serialized does not * implement the java.io.Serializable interface. * @throws IOException Any exception thrown by the underlying * OutputStream. */ public final void writeObject(Object obj) throws IOException { if (enableOverride) { writeObjectOverride(obj); return; } try { writeObject0(obj, false); } catch (IOException ex) { if (depth == 0) { writeFatalException(ex); } throw ex; } }
方法說明中關於丟擲異常的第二條說明中寫:
NotSerializableException Some object to be serialized does not
* implement the java.io.Serializable interface.
因此當實體類沒有實現該介面的時候會報該異常。
解決方案:給實體類實現java.io.Serializable介面
思考為什麼要序列化:
在MyBatis的二級快取中我們分析了二級快取的快取裝飾器,其中有一個SerializedCache,該類中對PerpetualCahce的裝飾就是序列化,可以檢視詳細的部落格資訊https://blog.csdn.net/tony_java_2017/article/details/84321537