Java StAX—将base64字符串从xml读入数据库

Java StAX—将base64字符串从xml读入数据库,java,xml,hibernate,sax,stax,Java,Xml,Hibernate,Sax,Stax,我使用StAX读取文件,其中包含一些Base64数据,并使用Hibernate将其保存到db中 XML: 编辑 由于某些原因,xmlr.getElementText().getBytes()会导致大量内存使用。刷新实体的频率是多少 我认为您构建了太多的实体,并且没有足够频繁地刷新会话,这会导致创建的所有对象都保留在当前会话中 我想核实一下 编辑 下面的注释表明提交者想要一种将二进制blob数据直接插入数据库的方法 与hibernate不同,这可以通过JDBC实现 java.sql.Connect

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

XML:

编辑
由于某些原因,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();
现在请注意,这是真正的混乱。这是假设实体_表正在使用数据库生成的行标识符,并且除BASE64之外的列允许有空值或合理的默认值。executeUpdate将运行insert语句,将is的值作为blob数据的值


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

您是否分析了此代码的内存消耗情况?内存到哪里去了?我可以看到内存使用峰值是实际xml大小的6倍。我可以看到许多char[]和byte[]allocatedreplace
实体。添加(实体)
会话。保存或更新(e)Q:您需要在数据库中存储二进制base64编码blob的什么表示形式?只剩下base64中的编码文本,还是对setBase64的调用实际上将base64文本解码回作为blob存储在数据库中的二进制数据?这个细节可能会有帮助。为什么要关闭合并?我想知道您是否获得base64数据的事件堆栈。我在抓救命稻草,想想base64线有多大?更重要的是,base64字符串有多大,解码后的二进制文件有多大?好吧,这是我的想法,我希望其他SO能够支持我。当您读取在内存中表示的11m XML时,您请求字节,可能是现在分配的另一个11m字节数组,这将是一个双字节,可能还有更多。试着将visualvm运行到(我想包括在jdk 6和更高版本中)以查看您正在加热的位置。我不记得visualvm中具体在哪里指示内存分配。。。我还要检查以确保hibernate此时没有缓存实体。。。看起来你现在最想在数据库中存储这些东西。有。。。但您必须通过标识或自动递增列来处理记录的标识。请参阅答案正文以进行编辑(稍后将提供)
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<Entity> 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);
 }
    //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();
    }
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();