You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Java和JDBC查询一对多关系数据时如何避免重复输出?

解决方案

提供两种纯Java+JDBC场景下的实现方式,可根据业务需求选择:

方案1:SQL层面直接聚合(推荐,性能最优)

你使用的是Oracle数据库,可以直接用Oracle内置的LISTAGG聚合函数完成邮箱拼接,无需修改过多Java逻辑:

修改后的查询语句

static final String QUERY = "select prs.person_id, prs.first_name, prs.last_name, " +
        "LISTAGG(pe.email, ',') WITHIN GROUP (ORDER BY pe.email) as emails " +
        "from persons prs " +
        "left join person_emails pe on prs.person_id = pe.person_fk " +
        "where prs.person_id = 1 " +
        "group by prs.person_id, prs.first_name, prs.last_name";

调用逻辑

查询结果仅返回1条记录,直接读取emails字段输出即可,无需调整遍历逻辑。该方案适合仅需要拼接输出邮箱、无后续单独处理邮箱需求的场景。

方案2:Java内存层面聚合

如果需要保留邮箱列表结构做后续业务处理,或后续可能切换非Oracle数据库,可以在内存中完成数据聚合:

修改后的Java代码

public class OneToManyDB {
   static final String DB_URL = "jdbc:oracle:thin:@1.1.1.1:1521:orcl";
   static final String USER = "user";
   static final String PASS = "pass";
   static final String QUERY = "select prs.person_id, prs.first_name, prs.last_name, pe.email" +
           " from persons prs" +
           " left join person_emails pe on prs.person_id = pe.person_fk" +
           " where prs.person_id = 1";

   public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            conn = DriverManager.getConnection(DB_URL, USER, PASS);
            stmt = conn.createStatement();
            rs = stmt.executeQuery(QUERY);
            
            Integer personId = null;
            String firstName = null;
            String lastName = null;
            List<String> emails = new ArrayList<>();

            while(rs.next()){
                // 人员基础信息仅首次赋值
                if (personId == null) {
                    personId = rs.getInt("person_id");
                    firstName = rs.getString("first_name");
                    lastName = rs.getString("last_name");
                }
                String email = rs.getString("email");
                if (email != null) {
                    emails.add(email);
                }
            }
            
            // 统一输出
            if (personId != null) {
                System.out.print("ID: " + personId);
                System.out.print(", First: " + firstName);
                System.out.print(", Last: " + lastName);
                System.out.println(", Email: " + String.join(",", emails));
            }
        } catch (SQLException e) {
            e.printStackTrace();       
        } finally {
            // 手动关闭资源避免泄漏
            try { if (rs != null) rs.close(); } catch (SQLException e) {}
            try { if (stmt != null) stmt.close(); } catch (SQLException e) {}
            try { if (conn != null) conn.close(); } catch (SQLException e) {}
        }
    }
}

方案说明

该方案无需修改SQL,聚合逻辑完全在Java层实现,可扩展性更高,后续如果需要查询多个人员的邮箱,只需要把存储结构替换为Map<Integer, 人员实体类>即可实现批量聚合。


内容的提问来源于stack exchange,提问作者NewJavaEnthusiast

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 09:09:02