The purpose of the code is to first serialize a configuration class jobconfig into a blob in Oracle and then deserialize it when it is checked.
Check the console error first
# # Cause:com.audaque.lib.core.exception.AdqRuntimeException:error on GetResult; Nested exception is Java.io.StreamCorruptedException:invalid stream header:00540001At org.apache.ibatis.exceptions.ExceptionFactory.wrapException (Exceptionfactory.java:23) at Org.apache.ibatis.session.defaults.DefaultSqlSession.selectList (Defaultsqlsession.java:107) at Org.apache.ibatis.session.defaults.DefaultSqlSession.selectList (Defaultsqlsession.java:98) at Sun.reflect.GeneratedMethodAccessor133.invoke (Unknown Source) at Sun.reflect.DelegatingMethodAccessorImpl. Invoke (Delegatingmethodaccessorimpl.java:43) at Java.lang.reflect.Method.invoke (Method.java:498) at Org.mybatis.spring.sqlsessiontemplate$sqlsessioninterceptor.invoke (Sqlsessiontemplate.java:354) ... 84morecaused by:com.audaque.lib.core.exception.AdqRuntimeException:error on GetResult; nested exception is Java.io.StreamCorruptedException:invalid Stream Header:00540001At Com.audaque.datadiscovery.mybatis.SerializeHandler.getResult (Serializehandler.java:50) at Org.apache.ibatis.executor.resultset.FastResultSetHandler.getPropertyMappingValue ( Fastresultsethandler.java:325) at Org.apache.ibatis.executor.resultset.FastResultSetHandler.applyPropertyMappings ( Fastresultsethandler.java:301) at Org.apache.ibatis.executor.resultset.NestedResultSetHandler.getRowValue (Nestedresultsethandler.java: 135) at Org.apache.ibatis.executor.resultset.NestedResultSetHandler.handleRowValues (Nestedresultsethandler.java :102) at Org.apache.ibatis.executor.resultset.FastResultSetHandler.handleResultSet (Fastresultsethandler.java: 188) at Org.apache.ibatis.executor.resultset.NestedResultSetHandler.handleResultSet (Nestedresultsethandler.java :73)
Mybatis Resultmap
<resultmap type= "Com.audaque.datadiscovery.job.model.po.Job" id= "job" > <id property= "jobId" column= " job_id "/> <result property=" JobName "column=" job_name "/> <result property=" Createtime "column= "Create_time"/> <result property= "description" column= "description"/> <result property= " Executetime "column=" Executetime "/> <result property=" Jobconfig "column=" Job_config "typeHandler=" Com.audaque.datadiscovery.mybatis.SerializeHandler "/> <association property=" creator "columnprefix=" Creator_ "resultmap=" User "/> </resultMap>
The reason for the error is that the Jobconfig property of the Job object fails to deserialize when the result is set after the query.
Using the MyBatis framework, for this jobconfig configuration class, do a typehanlder, here is the Typehandlder
public class Serializehandler implements typehandler<object> {
@Override
public void Setparameter (preparedstatement ps, int i, Object parameter, Jdbctype jdbctype) throws SQLException {
if (parameter = = null) {
Ps.setstring (i, NULL);
Return
}
try {
byte[] ss = serializeutils.serializeobject (parameter);
Ps.setbytes (i, SS);
} catch (IOException e) {
throw new Adqruntimeexception ("Error on Setparameter", e);
}
}
@Override
Public Object GetResult (ResultSet rs, String columnName) throws SQLException {
Object object = null;
try {
Deserialization error
object = Serializeutils.deserializeobject (Rs.getbytes (ColumnName));
} catch (IOException e) {
throw new Adqruntimeexception ("Error on GetResult", e);
} catch (ClassNotFoundException e) {
throw new Adqruntimeexception ("Error on GetResult", e);
}
return object;
}
@Override
Public Object GetResult (callablestatement cs, int columnindex)
Throws SQLException {
Object object = null;
try {
Object = Serializeutils.deserializeobject (Cs.getbytes (columnindex));
} catch (IOException e) {
throw new Adqruntimeexception ("Error on GetResult", e);
} catch (ClassNotFoundException e) {
throw new Adqruntimeexception ("Error on GetResult", e);
}
return object;
}
@Override
Public Object GetResult (ResultSet rs, int columnindex) throws SQLException {
Object object = null;
try {
Object = Serializeutils.deserializeobject (Rs.getbytes (columnindex));
} catch (IOException e) {
throw new Adqruntimeexception ("Error on GetResult", e);
} catch (ClassNotFoundException e) {
throw new Adqruntimeexception ("Error on GetResult", e);
}
return object;
}
}
There is a serialization tool class in Typehandler
Public Final classSerializeutils {/** * * @paramobject is want to serialize *@return * @throwsIOException*/ Public Static<T>byte[] SerializeObject (T object)throwsIOException {byte[] buffer =NULL; Bytearrayoutputstream Bos=NULL; ObjectOutputStream Oos=NULL; LongStart =System.currenttimemillis (); Try{BOS=NewBytearrayoutputstream (); Oos=NewObjectOutputStream (BOS); Oos.writeobject (object); Oos.flush (); Buffer=Bos.tobytearray (); }Catch(IOException ex) {Throwex; }finally{ if(Oos! =NULL) {oos.close (); } if(Bos! =NULL) {bos.close (); } LongEnd =System.currenttimemillis ();//System.out.println ("SerializeObject" +new SimpleDateFormat ("Yyyy-mm-dd HH:mm:ss"). Format (new Date (start)) + "Costs" + (End-start) + "MS"); } returnbuffer; } /** * * @parambuf is want to deserialize *@return * @throwsIOException *@throwsclassnotfoundexception*/@SuppressWarnings ({"Unchecked" }) Public Static<T> T Deserializeobject (byte[] buf)throwsIOException, ClassNotFoundException {T object=NULL; Bytearrayinputstream bis=NULL; ObjectInputStream Ois=NULL; LongStart =System.currenttimemillis (); Try{bis=NewBytearrayinputstream (BUF); Ois=NewObjectInputStream (bis); Object=(T) ois.readobject (); }Catch(IOException ex) {Throwex; }finally{ if(Ois! =NULL) {ois.close (); } if(bis! =NULL) {bis.close (); } LongEnd =System.currenttimemillis ();//System.out.println ("Deserializeobject" +new SimpleDateFormat ("Yyyy-mm-dd HH:mm:ss"). Format (new Date (start) ) + "costs" + (End-start) + "MS"); } returnobject; }
I first tested the tool class serializeutils whether there is a problem, test it is no problem.
I have no problem with calling the deserialization method after serialization.
The problem is that after querying from the database, we check the Java code that reads the Blob object to byte, and the Java.sql.Blob object converts the byte array and the Oracle.sql.Blob object to a byte array differently, if you use the Oracle.sql.Blob.getBytes method Conversion, the Java.io.StreamCorruptedException:invalid stream header:006c0001 error will be reported
Queryrunner Run =NewQueryrunner (true); String Querysql= "Select Job_config from adqm_job where job_id = 141"; Object[] Array= Run.query (Con, Querysql,NewArrayhandler ()); Blob blob= (Blob) array[0]; byte[] returnvalue = blob.getbytes (1, (int ) blob.length ()); System.out.println (arrays.tostring (returnvalue)); InputStream is= null; Blob blob1 = (BLOB) (array[0]); Byte[] B = null; try {is = Blob1.getbinarystream (); b = new byte[(int) blob1.length ()]; Is.read (b); } catch (Exception e) {e.printstacktrace (); }
But the system code is using the Rs.getbytes (columnName) code, is that a problem with the GetBytes code?
Connection con = dbutil.getconnection (); String querysql = "Select Job_config from adqm_job where job_id = 141"; = con.preparestatement (querysql); = preparedstatement.executequery (); while (Resultset.next ()) { byte []bytes= resultset.getbytes ("Job_config"); Serializeutils.deserializeobject (bytes); } Dbutil.close (con);
It is no problem to test the use of Rs.getbytes (columnName) to remove a byte array for deserialization.
The cause of the bug is still not found, I guess the reason is Object = Serializeutils.deserializeobject (Rs.getbytes (columnName)); The underlying implementation of Rs.getbytes (ColumnName) is ((BLOB) (Rs.getblob)). GetBytes ();
Finally, I will change the GetResult method of Typehandler to
@Override PublicObject GetResult (ResultSet rs, String columnName)throwsSQLException {Object Object=NULL; //Integrated workflow bug fixes Try{ blob blob = Rs.getblob (columnName); byte[] returnvalue = null; if (null! = BLOB) {returnvalue = Blob.getbytes (1, (int) blob.length ()); Object = Serializeutils.deserializeobject (returnvalue); } //Code//object = Serializeutils.deserializeobject (Rs.getbytes (ColumnName)); } Catch(IOException e) {Throw NewAdqruntimeexception ("Error on GetResult", E); } Catch(ClassNotFoundException e) {Throw NewAdqruntimeexception ("Error on GetResult", E); } returnobject; }
It can be correctly deserialized.
Oracle BLOB deserialization error