ObjectInputStream 适用于 MySql,但不适用于 sqlite

ObjectInputStream works for MySql, but not for sqlite

提问人:Ande Hofer 提问时间:3/3/2012 最后编辑:Ande Hofer 更新时间:3/5/2012 访问量:793

问:

我使用此代码从 MySql 数据库中获取 Blob,它工作正常,当我将其用于 sqlite 数据库时,它会抛出 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;

当我使用 SqLite 数据库时:

java.io.StreamCorruptedException:无效的流标头:61742E75 在 java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:797) 在 java.io.ObjectInputStream。(ObjectInputStream.java:294)

为什么会有不同的行为?

以下是我如何写入数据库:

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();
        }
    }
}

附加信息 sqlite 驱动程序版本:

        <groupId>org.xerial</groupId>
        <artifactId>sqlite-jdbc</artifactId>
        <version>3.7.2</version>
java sqlite jdbc 对象输入流

评论

0赞 Perception 3/3/2012
如何写入数据库?
0赞 Perception 3/3/2012
尝试以下代码来创建对象流 -Blob blob = rs.getBlob("ivissblob"); ObjectInputStream objectIn = new ObjectInputStream(new ByteArrayInputStream(blob.getBinaryStream()));
0赞 Ande Hofer 3/3/2012
sqlite Driver 没有实现 rs.getBlob,所以这不起作用。
0赞 Has QUIT--Anony-Mousse 3/3/2012
您的 SQL 架构是什么?你能排除字符串编码是一个问题吗?
0赞 Ande Hofer 3/3/2012
在 Mysql 中,datafieldtype 是 MEDIUMBLOB,在 sqlite 中是 BLOB。我认为这与字符串编码无关。

答:

1赞 Ande Hofer 3/5/2012 #1

同事给出的问题解决方案:

不要使用 .setObject 方法插入对象,而是使用 .setBytes 插入对象。

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();
        }
    }
}

和 getBytes 方法:

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;
}

现在它适用于 sqlite 和 MySql