今日提示词:JAVA25 跨不同数据库的联合查询实现
在工作中,我们实际有很多的多表联合查询业务,在同一数据库中,可以采用SQL语句的方式实现,也可以用编码的方式实现。在跨不同数据库的时候,我们几乎总是采用编码的方式实现(除非使用一些复制的框架)。总之我们可以把这种多表联合查询,用以下的通用方式来解决。
前提有单表的增删改查几乎不需要编写,都是接口型反射实现的,如Mybatis-plus,JPA等。这样对于联合查询我们根本不需要去增加更多的SQL语句去实现,从 JAVA8 以后,利用 Stream流的强大功能实现过滤合并Set值等功能,从而完成模拟SQL的联合查询的功能。
此方案的优点:
- 减少SQL方面的语句,并避免复杂的SQL语句
- 因为是单表查询,可避免联合查询出现的慢查询(如忘了建立相应的索引等)
- 转化为Stream并过滤收集数据为Map型数据结构,我们知道Map型数据匹配几乎是O(1),所以在运行速度上是相当快的
缺点:可能内存中对象相对较多,需要更大的内存。
优化:先估算查询返回结果集少的,在从此结果集中提取需要关联的数据。【此方案AI没有实现】
本次实验采用最新的JDK,JAVA25以获取更好的性能。核心实现思路为:
核心实现思路
- 多数据源配置:为不同数据库(如 MySQL、PostgreSQL)分别配置独立的数据源和 JdbcTemplate,保证数据查询隔离;
- 并发分库查询:利用 Java 25 虚拟线程(VirtualThread)提升多库并行查询效率,减少等待时间;
- 应用层关联数据:通过 Java 25 增强的 Stream API 完成数据关联(模拟 SQL Join 逻辑),支持内连接、左连接等常见场景;
- 结果封装:将关联后的结果封装为统一的 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);
}
}


被折叠的 条评论
为什么被折叠?



