Java StAX—将base64字符串从xml读入数据库
我使用StAX读取文件,其中包含一些Base64数据,并使用Hibernate将其保存到db中 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
由于某些原因,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();