AI与工作场景(二)跨不同数据库的联合查询实现

今日提示词:JAVA25 跨不同数据库的联合查询实现

​ 在工作中,我们实际有很多的多表联合查询业务,在同一数据库中,可以采用SQL语句的方式实现,也可以用编码的方式实现。在跨不同数据库的时候,我们几乎总是采用编码的方式实现(除非使用一些复制的框架)。总之我们可以把这种多表联合查询,用以下的通用方式来解决。

​ 前提有单表的增删改查几乎不需要编写,都是接口型反射实现的,如Mybatis-plus,JPA等。这样对于联合查询我们根本不需要去增加更多的SQL语句去实现,从 JAVA8 以后,利用 Stream流的强大功能实现过滤合并Set值等功能,从而完成模拟SQL的联合查询的功能。

此方案的优点:

  • 减少SQL方面的语句,并避免复杂的SQL语句
  • 因为是单表查询,可避免联合查询出现的慢查询(如忘了建立相应的索引等)
  • 转化为Stream并过滤收集数据为Map型数据结构,我们知道Map型数据匹配几乎是O(1),所以在运行速度上是相当快的

缺点:可能内存中对象相对较多,需要更大的内存。

优化:先估算查询返回结果集少的,在从此结果集中提取需要关联的数据。【此方案AI没有实现】

本次实验采用最新的JDK,JAVA25以获取更好的性能。核心实现思路为:

核心实现思路

  1. 多数据源配置:为不同数据库(如 MySQL、PostgreSQL)分别配置独立的数据源和 JdbcTemplate,保证数据查询隔离;
  2. 并发分库查询:利用 Java 25 虚拟线程(VirtualThread)提升多库并行查询效率,减少等待时间;
  3. 应用层关联数据:通过 Java 25 增强的 Stream API 完成数据关联(模拟 SQL Join 逻辑),支持内连接、左连接等常见场景;
  4. 结果封装:将关联后的结果封装为统一的 DTO,便于业务使用。

我们给出应用层关联部分的代码,以观察相应的代码逻辑(代码由豆包AI生成),给出的提示词:JAVA25 跨不同数据库的联合查询实现

import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * 跨库联合查询核心逻辑(Java 25 虚拟线程 + Stream 关联)
 */
public class CrossDbJoinQuery {
    private final JdbcTemplate mysqlJdbcTemplate;
    private final JdbcTemplate pgJdbcTemplate;

    public CrossDbJoinQuery() {
        this.mysqlJdbcTemplate = MultiDataSourceConfig.getMysqlJdbcTemplate();
        this.pgJdbcTemplate = MultiDataSourceConfig.getPgJdbcTemplate();
    }

    // 1. 查询 MySQL 中的用户数据
    private List<User> queryUsersFromMysql() {
        String sql = "SELECT id, name, age FROM t_user";
        return mysqlJdbcTemplate.query(sql, new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet rs, int rowNum) throws SQLException {
                return new User(
                        rs.getLong("id"),
                        rs.getString("name"),
                        rs.getInt("age")
                );
            }
        });
    }

    // 2. 查询 PostgreSQL 中的订单数据
    private List<Order> queryOrdersFromPg() {
        String sql = "SELECT id, user_id, amount FROM t_order";
        return pgJdbcTemplate.query(sql, new RowMapper<Order>() {
            @Override
            public Order mapRow(ResultSet rs, int rowNum) throws SQLException {
                return new Order(
                        rs.getLong("id"),
                        rs.getLong("user_id"),
                        rs.getDouble("amount")
                );
            }
        });
    }

    // 3. 跨库联合查询(模拟 INNER JOIN)
    public List<UserOrderDTO> crossDbInnerJoin() throws Exception {
        // 使用 Java 25 虚拟线程池并行查询两个库的数据
        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
            // 并行执行两个查询任务
            var userFuture = executor.submit(this::queryUsersFromMysql);
            var orderFuture = executor.submit(this::queryOrdersFromPg);

            // 获取查询结果
            List<User> users = userFuture.get();
            List<Order> orders = orderFuture.get();

            // 将订单数据按 userId 分组,提升关联效率(Java 8+ Stream)
            Map<Long, List<Order>> orderMap = orders.stream()
                    .collect(Collectors.groupingBy(Order::getUserId));

            // 应用层关联(模拟 INNER JOIN:只保留有订单的用户)
            return users.stream()
                    .filter(user -> orderMap.containsKey(user.getId()))
                    .flatMap(user -> orderMap.get(user.getId()).stream()
                            .map(order -> new UserOrderDTO(
                                    user.getId(),
                                    user.getName(),
                                    user.getAge(),
                                    order.getId(),
                                    order.getAmount()
                            )))
                    .collect(Collectors.toList());
        }
    }

    // 测试方法
    public static void main(String[] args) throws Exception {
        CrossDbJoinQuery query = new CrossDbJoinQuery();
        List<UserOrderDTO> result = query.crossDbInnerJoin();
        // 打印关联结果
        result.forEach(System.out::println);
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值