Oracle BLOB deserialization error

Source: Internet
Author: User
Tags object object

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

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.