gpt4 book ai didi

java - StringBuilder 替代方案可实现更好的内存分配

转载 作者:行者123 更新时间:2023-12-01 19:52:25 25 4
gpt4 key购买 nike

我使用此 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。

我还能如何编写此代码以使其更快并使用更少的内存?

注意:首选 java 8 解决方案。

注2:我使用EntityManager。

最佳答案

您应该在 StringBuilder 中使用 concat() 而不是 +

    for(Object[] entityToCopy : entitiesToCopy){
Entity entity= (Entity )entityToCopy[0];
tmpValueForEntityId= lastEntryInEntityId ;
queryString.append("(").append(lastEntryInEntityId++).append(",").append(entity.getProperty()).append(",").append(entity[1]).append(",").append(entity.getProperty2()).append("),");

for(Entity2 entity2 : entity.getEntity2Collection()){
queryString2.append("(").append(lastEntryInEntity2Id ++).append(",").append(tmpValueForEntityId).append(",").append(entity.getProperty2()).append(",").append(entity.getProperty3()).append("),");
}
}
<小时/>

为了获得更好的性能,请在事务中使用PreparedStatement:

dbCon.setAutoCommit(false);
var pst = dbCon.prepareStatement("insert into entity (columnID, column_1, column_2, column_3) values (?, ?, ?, ?)";
for(Object[] entityToCopy : entitiesToCopy){
var entity = (Entity )entityToCopy[0];
tmpValueForEntityId = lastEntryInEntityId;
pst.setInt(1, lastEntryInEntityId);
pst.setString(2, entity.getProperty());
pst.setString(3, entity[1]);
pst.setString(4, entity.getProperty2());
pst.addBatch();
}
pst.executeBatch();
dbCon.commit();
dbCon.setAutoCommit(true);
<小时/>

每个 ? 代表一列。第一个代表 ID,第二个代表 column_1,依此类推。保持每一个的顺序。

注意:如果您使用 1.10 之前的 Java,请将 var 更改为 PreparedStatement

<小时/>

使用并发连接(多个线程插入数据库):

  1. 提交后不要关闭数据库连接(程序退出时关闭)
  2. 插入数据的方法应该同步
  3. 不要使用 prepareStatement(),而是使用 createStatement()Pattern(正则表达式)以避免 SQL 注入(inject)。

注意:PreparedStatement 很好、快速且安全。

数据库保留一个准备好的语句池,以避免每次都创建新的语句。但同时,在一个线程引用现有语句 -> PreparedStatement 后,另一个线程可以使用它,并且事务处理速度很慢(等待新实例或对现有语句的新引用)。同时这种情况发生了很多很多次。

<小时/>

EntityManager 示例:

    var em = emf.createEntityManager();
EntityTransaction transaction = null;
try {
transaction = em.getTransaction();
transaction.begin();

for(Object[] entityToCopy : entitiesToCopy){
var entity = (Entity )entityToCopy[0];
...//insert here
}

tx.commit();
} catch (RuntimeException e) {
if (transaction != null && transaction.isActive()) {
tx.rollback();
e.printStackTrace();
}
} finally {
em.close();
}

关于java - StringBuilder 替代方案可实现更好的内存分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50923878/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com