我正在使用此StringBuilder以在查询中添加内容:
Integer lastEntryInEntityId = 1;//acquired through another query
Integer tmpValueForEntityId;
Integer lastEntryInEntity2Id = 1;//acquired through another query
StringBuilder queryString = new StringBuilder("insert
into entity(column,column_1,column_2,column_3) values");
StringBuilder queryString2 = new StringBuilder("insert
into entity2(column,column_1,column_2,column_3) values");
for(Object[] entityToCopy : entitiesToCopy){
Entity entity= (Entity )entityToCopy[0];
tmpValueForEntityId= lastEntryInEntityId ;
queryString.append("("+ lastEntryInEntityId ++ +","+entity.getProperty()+","+entity[1]+","+entity.getProperty2()+"),");
for(Entity2 entity2 : entity.getEntity2Collection()){
queryString2.append("("+lastEntryInEntity2Id ++ +","+tmpValueForEntityId+","+entity.getProperty2()+","+entity.getProperty3()+"),");
}
}
此代码需要太多时间和内存 . 它实际上会在一段时间后(当 entitiesToCopy
太多时)添加到第二个StringBuilder时抛出OutOfMemoryException .
How else can I write this code in order to make it faster and use less memory?
注意:首选java 8解决方案 .
注2:我使用EntityManager .
2 回答
您应该在
StringBuilder
内使用concat()
而不是+
为了获得更好的性能,请在事务中使用
PreparedStatement
:每个
?
代表一列 . 第一个代表ID,第二个代表column_1
,等等 . 保持每个的顺序 .注意:如果您使用的是1.10之前的Java,请将
var
更改为PreparedStatement
使用并发连接(多个线程插入数据库):
提交后不关闭数据库连接(程序退出时关闭)
插入数据的方法应为
synchronized
不要使用
prepareStatement()
,而是使用createStatement()
和Pattern
(正则表达式)来避免SQL注入 .注意:
PreparedStatement
好,快,安全 .数据库保留一个准备好的语句池,以避免每次都创建新语句 . 但同时,在一个线程引用现有语句 - >
PreparedStatement
之后,另一个线程可以使用它并且transactioin很慢(等待新实例或对现有的新引用) . 同时发生这种情况很多次 .EntityManager示例:
我每x次迭代执行一次查询,这样查询就不会太大 . 这解决了我的问题 .