2012-03-01 2 views
2

Я использую StAX для чтения моего файла, в котором есть некоторые данные Base64, и сохранения его в db с помощью Hibernate.StAX - чтение base64 строка из xml в db

XML:

<root> 
    <base64>lololencoded12</base64> 
    <base64>encodedlolos32</base64> 
    ............................... 
</root> 

код для чтения и сохранения:

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

Этот подход съедает память в количестве, 6-9 раз размер моего XML. Как я могу улучшить это?

EDIT

Если я закомментировать entity.setBase64() все нормально. При сохранении байта [] на использование памяти db происходит брокер. Зачем?

EDIT Entity геттеры и сеттеры:.

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

EDIT xmlr.getElementText() GetBytes() вызывает много использования памяти для какой-либо причине.

+1

Профилируйте этот код для потребления памяти? Куда идет память? –

+0

Я могу видеть, как всплески памяти используют 6-кратный размер фактического xml. – emmma1223

+0

Я могу видеть много символов char [] и byte [], выделенных – emmma1223

ответ

2

Как часто вы проводите промывку своих объектов?

Я думаю, что вы создаете слишком много объектов, а не слишком часто очищаете сеанс, что приводит к тому, что все созданные объекты сохраняются в текущем сеансе.

Возможно, я хочу проверить это.

Редактировать

Комментарии ниже указано, что заявитель хотел способ вставки двоичных данных больших двоичных объектов непосредственно в базе данных.

Вместо этого с помощью спящего режима это может быть достигнуто только с помощью 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, для которой значение равно как значение данных blob.

Надеюсь, это приблизит вас к вашему решению.

+0

Я тестирую с размером xml ~ 11mb с двумя объектами. Память идет 6 раз такого размера :( – emmma1223

+1

Почему у вас есть коалесценция выключена?Мне интересно, если вы получаете стеки событий для ваших данных base64. Я зацепился за соломинку здесь, хотя –

+0

Включено - ничего не меняется :( – emmma1223

Смежные вопросы