数据库查询获2行数据,返回Map仅保留最后一行的问题咨询
问题排查:Map仅保留最后一行数据的原因及解决办法
核心问题原因
你遇到的问题本质是Map的键唯一性约束:
- 你的SQL查询返回了2行记录,但这两行的
id字段值是完全相同的(毕竟WHERE条件是id="+id,能返回2行说明这两行的id一致但name不同,distinct是整行去重,所以会保留这两条记录)。 - 当你用重复的
id作为Map的键时,第二次调用put()方法会直接覆盖第一次存入的对应值——Map的规则就是键唯一,新值覆盖旧值,所以最终只会留下最后一次存入的键值对。
快速验证方式
你可以在循环里加一行打印,确认两次循环的键是否重复:
while (itr.hasNext()) { Object row1[] = (Object[]) itr.next(); Integer key = row1[0]==null?0:Integer.parseInt(row1[0].toString()); String value = (row1[1] == null)? "" : row1[1].toString(); System.out.println("当前键:" + key + ",对应值:" + value); // 打印验证 stylesMap.put(key, value); }
运行后你会发现两次循环的key是同一个值,这就是覆盖问题的直接证据。
针对性解决方案
根据你的业务需求,有两种常见的处理方式:
1. 保留同一ID下的所有Name:用List作为Map的值
如果业务上允许同一个ID对应多个Name,可以把Map的类型改成Map<Integer, List<String>>,这样同一个ID下的所有Name都能被保存:
public Map<Integer, List<String>> getname(int id) { Session session = sessionFactory.openSession(); Map<Integer, List<String>> stylesMap = new LinkedHashMap<>(); try { Query query = getSession().createSQLQuery("select distinct id,name from employee where id=:id"); query.setParameter("id", id); // 改用参数化查询避免SQL注入 List results = query.list(); Iterator itr = results.iterator(); while (itr.hasNext()) { Object row1[] = (Object[]) itr.next(); Integer key = row1[0]==null?0:Integer.parseInt(row1[0].toString()); String value = (row1[1] == null)? "" : row1[1].toString(); // 如果键不存在,先创建空List;存在则直接添加值 stylesMap.computeIfAbsent(key, k -> new ArrayList<>()).add(value); } } catch (Exception e) { logger.error("", e); } finally { if(session !=null) { session.close(); } } return stylesMap; }
2. 直接返回所有行数据:改用List存储
如果不需要用Map结构,直接返回包含所有行的List会更直观,比如用List<Map<String, Object>>存储每一行的id和name:
public List<Map<String, Object>> getname(int id) { Session session = sessionFactory.openSession(); List<Map<String, Object>> resultList = new ArrayList<>(); try { Query query = getSession().createSQLQuery("select distinct id,name from employee where id=:id"); query.setParameter("id", id); List results = query.list(); Iterator itr = results.iterator(); while (itr.hasNext()) { Object row1[] = (Object[]) itr.next(); Map<String, Object> rowMap = new HashMap<>(); rowMap.put("id", row1[0]==null?0:Integer.parseInt(row1[0].toString())); rowMap.put("name", (row1[1] == null)? "" : row1[1].toString()); resultList.add(rowMap); } } catch (Exception e) { logger.error("", e); } finally { if(session !=null) { session.close(); } } return resultList; }
额外提醒
你的原SQL存在SQL注入风险,上面的解决方案里已经改成了参数化查询,这是生产环境必须注意的安全细节。
内容的提问来源于stack exchange,提问作者Chakravarthirudhir Reddy
相关产品推荐
相关产品推荐

