StAX – 从xml读取base64字符串到db

我正在使用StAX读取我的文件,其中包含一些Base64数据,并使用Hibernate将其保存到数据库中。

XML:

 lololencoded12 encodedlolos32 ...............................  

要读取和保存的代码:

 xmlif = (XMLInputFactory2) XMLInputFactory2.newInstance(); xmlif.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.FALSE); xmlif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE); xmlif.setProperty(XMLInputFactory.IS_COALESCING, Boolean.FALSE); xmlif.configureForLowMemUsage(); List entities = new ArrayList(); FileInputStream fis = new FileInputStream(filename); XMLStreamReader2 xmlr = (XMLStreamReader2) xmlif.createXMLStreamReader(filename, fis); int eventType = xmlr.getEventType(); String curElement = ""; while (xmlr.hasNext()) { eventType = xmlr.next(); switch (eventType) { case XMLEvent.START_ELEMENT: curElement=xmlr.getName().toString(); if ("base64".equals(curElement)) { Entity entity = new Entity(); entity.setBase64(xmlr.getElementText().getBytes()); session.save(entity); session.flush(); } break; } } iterator itr = entities.iterator(); while (itr.hasNext()) { Entity e = (Entity)itr.next(); session.saveOrUpdate(e); } 

这种方法吞噬内存的数量是我的xml大小的6-9倍。 我怎么能改善这个?

编辑

如果我注释掉entity.setBase64(),一切都很好。 将byte []保存到db内存使用时会变得疯狂。 为什么?

编辑实体getter和setter:

  //for me public byte[] getBase64() { return base64; } public void setBase64(byte[] base64) { this.base64= base64; } //for hibernate public Blob getBase64Blob() { if (this.base64!=null) { LobCreator lobok =Hibernate.getLobCreator(MainFrame.sessionFactory.getCurrentSession()); return lobok.createBlob(base64); } else { return null; } } public void setBase64Blob(Blob dataBlob) { if (dataBlob!=null) { this.base64= toByteArray(dataBlob); } } //utilities methods from blob to byte array private byte[] toByteArray(Blob fromBlob) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { return toByteArrayImpl(fromBlob, baos); } catch (SQLException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } finally { if (baos != null) { try { baos.close(); } catch (IOException ex) { } } } } private byte[] toByteArrayImpl(Blob fromBlob, ByteArrayOutputStream baos) throws SQLException, IOException { byte[] buf = new byte[4000]; InputStream is = fromBlob.getBinaryStream(); try { for (;;) { int dataSize = is.read(buf); if (dataSize == -1) break; baos.write(buf, 0, dataSize); } } finally { if (is != null) { try { is.close(); } catch (IOException ex) { } } } return baos.toByteArray(); } 

编辑 xmlr.getElementText()。getBytes()由于某种原因导致大量内存使用。

你多久一次冲出你的实体?

我认为你正在构建太多的实体而不是经常刷新你的会话,导致所有创建的对象都保留在当前会话中。

可能想检查一下。

编辑

以下评论表明提交者想要一种方法将二进制blob数据直接插入数据库。

而不是使用hibernate,只需使用JDBC即可实现。

 java.sql.Connection conn = ... java.sql.PreparedStatement pstmt= conn.prepareStatement("insert into ENTITY_TABLE (BASE64) VALUES (?)"); InputStream is= ... // byte data pstmt.setBinaryStream(1, is); int numUpdated= pstmt.executeUpdate(); 

现在建议,这是真正的粗糙和翻滚。 这假设ENTITY_TABLE正在使用数据库生成的行标识符,并且允许除BASE64之外的列具有空值或具有合理的默认值。 executeUpdate将运行insert语句,其值为is作为blob数据的值。

我希望这能让你更接近你的解决方案。