Search code examples
javasqlitejdbcobjectinputstream

ObjectInputStream works for MySql, but not for sqlite


I use this code to get a Blob from a MySql database and it works fine, when i use it for an sqlite database it throws a StreamCorruptedException

public static SessionData getIvissSession(BigInteger id) throws IvissDatabaseException {
    SessionData sd = null;
    PreparedStatement pstmt = null;
    Connection con = null;
    try {
        con = getConnection();
        pstmt = con.prepareStatement("SELECT ivissblob FROM iviss_session_table WHERE id =?");
        pstmt.setLong(1, Long.parseLong(id.toString()));
        ResultSet rs = pstmt.executeQuery();
        while (rs.next()) {
            byte[] ivissblob = rs.getBytes("ivissblob");
            ObjectInputStream objectIn = new ObjectInputStream(new ByteArrayInputStream(ivissblob));
            sd = (SessionData) objectIn.readObject();
            objectIn.close();
        }

    } catch (SQLException e) {
        throw new IvissDatabaseException(Constants.ERROR_202);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally {

        try {
            if (pstmt != null) {
                pstmt.close();
            }
            if (con != null) {
                con.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

    return sd;

When I use the SqLite Database:

java.io.StreamCorruptedException: invalid stream header: 61742E75 at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:797) at java.io.ObjectInputStream.(ObjectInputStream.java:294)

Why is there a differnt behaviour?

Here how I write into the database:

public static void insertIntoTable(BigInteger id, SessionData sd, byte[] rtsd, IvissWorker ivissWorker) {
    PreparedStatement pstmt = null;
    Connection con = null;
    try {
        con = getConnection();
        pstmt = con
                .prepareStatement("REPLACE INTO iviss_session_table (id, ivissblob, rtblob, lastaccess) VALUES(?,?,?,?)");
        pstmt.setLong(1, Long.parseLong(id.toString()));
        pstmt.setObject(2, sd);
        pstmt.setObject(3, rtsd);
        pstmt.setDate(4, new Date(System.currentTimeMillis()));
        pstmt.executeUpdate();
    } catch (SQLException e) {
        ivissWorker.getIvissWorkerOutputHandler().addError(Constants.ERROR_205, "", DbConfiguration.getDbUri());
    } finally {
        try {
            if (pstmt != null) {
                pstmt.close();
            }
            if (con != null) {
                con.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Additional information sqlite driver version:

        <groupId>org.xerial</groupId>
        <artifactId>sqlite-jdbc</artifactId>
        <version>3.7.2</version>

Solution

  • a solution of the problem given from a colleague:

    Insert the object not with method .setObject, but with .setBytes instead.

    public static void insertIntoTable(BigInteger id, SessionData sd, byte[] rtsd, IvissWorker ivissWorker) {
        PreparedStatement pstmt = null;
        Connection con = null;
        try {
            con = getConnection();
            pstmt = con
                    .prepareStatement("REPLACE INTO iviss_session_table (id, ivissblob, rtblob, lastaccess) VALUES(?,?,?,?)");
            pstmt.setLong(1, Long.parseLong(id.toString()));
            pstmt.setBytes(2, IvissUtil.getBytes(sd));
            pstmt.setObject(3, rtsd);
            pstmt.setDate(4, new Date(System.currentTimeMillis()));
            pstmt.executeUpdate();
            // System.out.println("Stored/Replaced session with ID: " + id +
            // " in table.");
        } catch (SQLException e) {
            ivissWorker.getIvissWorkerOutputHandler().addError(Constants.ERROR_205, "", DbConfiguration.getDbUri());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (con != null) {
                    con.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    

    and the getBytes method:

    public static byte[] getBytes(Object obj) throws java.io.IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(obj);
        oos.flush();
        oos.close();
        bos.close();
        byte[] data = bos.toByteArray();
        return data;
    }
    

    Now it works with sqlite and MySql