Java方法性能优化咨询:循环单查数据库导致性能低下
循环单查数据库的性能优化方案
当前代码在遍历Iterator时,对每个符合条件的FatturaArticoli对象单独执行一次数据库查询,频繁的数据库交互是性能瓶颈的核心原因。以下是针对性的优化方案:
1. 批量查询替代循环单查
将所有需要查询的商品ID收集后一次性从数据库获取,把N次数据库请求减少为1次,这是最有效的优化手段。
修改settaArticoliPreSalvataggio方法
先收集所有符合条件的商品ID和对应对象,再批量查询组装结果:
public List<ArticoliDett> settaArticoliPreSalvataggio(Iterator iteratore){ try{ List<Integer> articoloIds = new ArrayList<>(); List<FatturaArticoli> validArticoli = new ArrayList<>(); // 第一步:收集有效ID和对应对象 while(iteratore.hasNext()){ Object obj = iteratore.next(); if(obj instanceof FatturaArticoli){ FatturaArticoli articoloF = (FatturaArticoli) obj; if(articoloF.getIsLavoro() != null && articoloF.getIsLavoro()) continue; String codice = articoloF.getCodiceArticolo(); if(!codice.equalsIgnoreCase("-") && !codice.equals(WFConst.COD_RITENUTA_ACCONTO) && !codice.equals(WFConst.CODICE_IBAN)){ try { int id = Integer.parseInt(codice); articoloIds.add(id); validArticoli.add(articoloF); } catch (NumberFormatException e) { log.logStackTrace(e); return null; } } } } // 第二步:批量查询所有商品数据 if(articoloIds.isEmpty()){ return new ArrayList<>(); } Map<Integer, ArticoliDett> articoloMap = modelManager.getArticoliManager() .estraiArticoliCompletoBatch(articoloIds, false); // 第三步:组装结果列表 List<ArticoliDett> listaArticoliPre = new ArrayList<>(); for(FatturaArticoli articoloF : validArticoli){ int id = Integer.parseInt(articoloF.getCodiceArticolo()); ArticoliDett articoloPre = articoloMap.get(id); if(articoloPre == null){ return null; } if(articoloF.getNomeArticolo().contains("(Articolo Gratuito)")){ articoloPre.setNomeArticolo(articoloPre.getNomeArticolo() + " (Articolo Gratuito)"); } listaArticoliPre.add(articoloPre); } return listaArticoliPre; }catch(Exception e){ log.logStackTrace(e); return null; } }
新增批量查询方法estraiArticoliCompletoBatch
在ArticoliManager中实现批量查询逻辑,使用IN子句一次性获取所有数据:
public Map<Integer, ArticoliDett> estraiArticoliCompletoBatch(List<Integer> idArticoli, Boolean estraiArticoloPerFornitore){ Map<Integer, ArticoliDett> articoloMap = new HashMap<>(); if(idArticoli.isEmpty()){ return articoloMap; } // 构建IN子句占位符 StringBuilder placeholders = new StringBuilder(); for(int i=0; i<idArticoli.size(); i++){ if(i > 0){ placeholders.append(","); } placeholders.append("?"); } String query = "SELECT CODARTICOLO,nomearticolo,soglia,prezzomedio," + "quantita,prezzoattuale,prezzorivenditore, " + "prezzoingrosso,iva,quantitacartone,quantitaPedane, " + "IN_SCHEDA_LAVORO, IS_LAVORO " + "FROM VISTAARTICOLI " + "WHERE codarticolo IN (" + placeholders + ")"; // 用try-with-resources自动关闭资源,避免泄漏 try (PreparedStatement stmt = db.prepareStatement(query)) { // 设置参数 for(int i=0; i<idArticoli.size(); i++){ stmt.setInt(i+1, idArticoli.get(i)); } try (ResultSet rs = stmt.executeQuery()) { while(rs.next()) { ArticoliDett articolo = new ArticoliDett(); int nColumn = 1; int codArticolo = rs.getInt(nColumn++); articolo.setCodArticolo(codArticolo); articolo.setNomeArticolo(rs.getString(nColumn++)); articolo.setSoglia(rs.getInt(nColumn++)); articolo.setPrezzoMedioVendita(rs.getDouble(nColumn++)); Articoli artGiacenza = new Articoli(); artGiacenza.setCodArticolo(codArticolo); artGiacenza.setQuantita(rs.getInt(nColumn++)); artGiacenza.setPrezzoAttuale(rs.getDouble(nColumn++)); artGiacenza.setPrezzoRivenditore(rs.getDouble(nColumn++)); artGiacenza.setPrezzoIngrosso(rs.getDouble(nColumn++)); artGiacenza.setIva(rs.getInt(nColumn++)); artGiacenza.setPezziCartone(rs.getInt(nColumn++)); artGiacenza.setPezziPedana(rs.getInt(nColumn++)); artGiacenza.setNomeArticolo(articolo.getNomeArticolo()); artGiacenza.setInSchedaLavoro(rs.getInt(nColumn++) == 1); artGiacenza.setIsLavoro(rs.getInt(nColumn++) == 1); articolo.setArticoloGiacenze(artGiacenza); if(estraiArticoloPerFornitore){ articolo.getArticoloGiacenze().setArticoliFornitore(estraiArticoliPerFornitore(codArticolo)); } articoloMap.put(codArticolo, articolo); } } } catch (Exception e) { log.logStackTrace(e); } return articoloMap; }
2. 优化原单查方法的细节
即使保留单查逻辑,也可以做以下优化提升效率:
- 使用try-with-resources自动关闭资源:避免ResultSet、PreparedStatement未正确关闭导致的资源泄漏
- 修正空结果处理:原方法不管是否查到数据都返回new ArticoliDett(),改为无数据时返回null,让调用方能正确判断查询结果
- 检查索引:确保视图
VISTAARTICOLI的codarticolo字段有索引,这能极大提升单条查询的速度 - 简化布尔值转换:
rs.getInt(nColumn++) == 1 ? true : false可简化为rs.getInt(nColumn++) == 1
优化后的原单查方法:
public ArticoliDett estraiArticoloCompleto(int idArticolo, Boolean estraiArticoloPerFornitore){ String query = "SELECT CODARTICOLO,nomearticolo,soglia,prezzomedio," + "quantita,prezzoattuale,prezzorivenditore, " + "prezzoingrosso,iva,quantitacartone,quantitaPedane, " + "IN_SCHEDA_LAVORO, IS_LAVORO " + "FROM VISTAARTICOLI " + "WHERE codarticolo=?"; try (PreparedStatement stmt = db.prepareStatement(query)) { stmt.setInt(1, idArticolo); try (ResultSet rs = stmt.executeQuery()) { if(rs.next()) { ArticoliDett articolo = new ArticoliDett(); int nColumn = 1; int codArticolo = rs.getInt(nColumn++); articolo.setCodArticolo(codArticolo); articolo.setNomeArticolo(rs.getString(nColumn++)); articolo.setSoglia(rs.getInt(nColumn++)); articolo.setPrezzoMedioVendita(rs.getDouble(nColumn++)); Articoli artGiacenza = new Articoli(); artGiacenza.setCodArticolo(codArticolo); artGiacenza.setQuantita(rs.getInt(nColumn++)); artGiacenza.setPrezzoAttuale(rs.getDouble(nColumn++)); artGiacenza.setPrezzoRivenditore(rs.getDouble(nColumn++)); artGiacenza.setPrezzoIngrosso(rs.getDouble(nColumn++)); artGiacenza.setIva(rs.getInt(nColumn++)); artGiacenza.setPezziCartone(rs.getInt(nColumn++)); artGiacenza.setPezziPedana(rs.getInt(nColumn++)); artGiacenza.setNomeArticolo(articolo.getNomeArticolo()); artGiacenza.setInSchedaLavoro(rs.getInt(nColumn++) == 1); artGiacenza.setIsLavoro(rs.getInt(nColumn++) == 1); articolo.setArticoloGiacenze(artGiacenza); if(estraiArticoloPerFornitore){ articolo.getArticoloGiacenze().setArticoliFornitore(estraiArticoliPerFornitore(codArticolo)); } return articolo; } } } catch (Exception e) { log.logStackTrace(e); } // 无数据时返回null,而非空对象 return null; }
3. 额外优化建议
- 缓存常用商品数据:如果部分商品频繁被查询,可以引入本地缓存(如Guava Cache)或分布式缓存,避免重复查询数据库
- 提前过滤无效数据:在收集ID阶段就排除格式错误的codiceArticolo,减少无效查询
- 常量复用:将
"(Articolo Gratuito)"定义为常量,避免重复创建字符串对象
内容的提问来源于stack exchange,提问作者bircastri
相关产品推荐
相关产品推荐

