Java 连接 Doris 全解:Apache Doris JDBC 数据源配置与生产避坑指南
【免费下载链接】dorisApache Doris is an easy-to-use, high performance and unified analytics database.项目地址: https://gitcode.com/gh_mirrors/dori/doris
业务里越来越常见的一个场景:想在 Java 服务里直接查 Doris 数仓,报表接口、实时大盘都把 Apache Doris 当成查询后端。因为 Doris 的 FE 走的是 MySQL 协议,你几乎可以用现成的 JDBC 驱动把 Java 应用接进来,不必自己造协议轮子。本文按"先搞懂在连什么 → 打通连接 → 读写数据 → 交给框架托管 → 跑得稳"的顺序带你上手,全程以能跑通、能上生产为准。
1. 先搞清楚:Doris JDBC 到底在连什么
上手前先建立一个正确的认知,能少走很多弯路。🧭
你连的是 FE 的查询端口,不是 BE
Doris 分 FE 和 BE 两种节点。FE 管元数据、SQL 解析和查询调度,它对外暴露一个MySQL 协议的查询端口,默认 9030(在 conf/fe.conf 里能看到query_port = 9030)。你的 Java 连接就是打到这个端口上。
这就是为什么连接串前缀写jdbc:mysql而不是某个 Doris 专属前缀——Doris 直接兼容了 MySQL 协议,你拿 MySQL 那套客户端和驱动就能连。
驱动文件和 Maven 依赖是一回事
很多同学会问:到底要引一个"Doris 驱动"吗?
- 驱动文件(一个 jar)和Maven 依赖,本质是同一个 jar 的两种引入方式:用 Maven / Gradle 时,它被自动拉进本地仓库、放进 classpath;手动方式就是把 jar 丢进 classpath(
WEB-INF/lib或-cp指定)。 - Doris 的 spring-jdbc-demo 里,直接用MySQL Connector/J 8.0.28(
com.mysql.cj.jdbc.Driver)就连上了。官方也提供了org.apache.doris:doris-jdbc驱动,两者都能连,选其一即可。
2. 最快路径:把连接打通
这一节目标只有一个——最小闭环跑通。先引驱动,再配 URL,最后发一条 SQL 验证。
2.1 引入驱动(Maven / Gradle)
Maven:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency>Gradle:
implementation 'mysql:mysql-connector-java:8.0.28'想换官方驱动,就把坐标换成org.apache.doris:doris-jdbc。
2.2 读懂一条 JDBC URL
jdbc:mysql://<host>:<port>/<database>host:FE 节点的 IP / 域名port:查询端口,默认9030database:要连的库名user/password:账号密码,放在getConnection里传,不建议拼进 URL
例:jdbc:mysql://127.0.0.1:9030/test
2.3 最小可运行连接
String url = "jdbc:mysql://127.0.0.1:9030/test"; try (Connection conn = DriverManager.getConnection(url, "root", "")) { // 连接拿到了,后面用它发 SQL }try-with-resources会帮你自动关连接,别忘。
2.4 自检:SELECT version()
连上后发一条version(),确认链路真通了:
try (Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT version()")) { if (rs.next()) { System.out.println("Doris 版本: " + rs.getString(1)); } }能打印出版本号,就说明 JDBC 连接 Doris 这条路已经通了。✅
3. 把数据读写用起来
连接通了,接下来就是日常三件事:查、写、事务。💾
3.1 查询(PreparedStatement + ResultSet)
带参数就用PreparedStatement,防注入、还能复用执行计划:
String sql = "SELECT id, name, age FROM users WHERE age > ?"; try (PreparedStatement ps = conn.prepareStatement(sql)) { ps.setInt(1, 18); try (ResultSet rs = ps.executeQuery()) { while (rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); // 处理一行 } } }3.2 写入(insert / update / delete)
写入和查询同一套写法,只是把executeQuery换成executeUpdate:
String sql = "INSERT INTO users(id, name, age) VALUES(?, ?, ?)"; try (PreparedStatement ps = conn.prepareStatement(sql)) { ps.setInt(1, 1001); ps.setString(2, "John"); ps.setInt(3, 25); int n = ps.executeUpdate(); // 返回影响行数 }UPDATE、DELETE同理,把 SQL 换成对应语句即可:
// UPDATE users SET age = ? WHERE id = ? // DELETE FROM users WHERE id = ?小提醒:Doris 是分析型数据库,大批量写入更推荐 Stream Load / Broker Load(见 samples/doris-demo/),逐行
INSERT只适合小数据量。
3.3 事务边界(autoCommit / commit / rollback)
需要多条 SQL 要么全成、要么全滚时,关掉自动提交:
conn.setAutoCommit(false); try { // 执行多条 SQL conn.commit(); } catch (SQLException e) { conn.rollback(); throw e; } finally { conn.setAutoCommit(true); // 用完还原 }先setAutoCommit(false)划出事务边界,中间操作失败就rollback(),成功再commit(),最后记得把自动提交开关拨回去。
4. 进阶:把连接交给框架托管
手写DriverManager适合验证,生产里连接要交给框架和连接池管。这一节以 Spring Boot 为例。
4.1 Spring Boot 数据源配置
在application.properties里配好,Spring 会帮你建DataSource:
spring.datasource.url=jdbc:mysql://127.0.0.1:9030/test spring.datasource.username=root spring.datasource.password= spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver配置项和 2.2 那条 URL 完全对得上,改端口、改库名就改这里。
4.2 连接池(HikariCP / Druid)
不要自己反复建/关连接,用池子复用。
- HikariCP:Spring Boot 默认自带,开箱即用,调
spring.datasource.hikari.*即可。 - Druid:demo 里就用的它,监控和慢 SQL 日志更细。示例的 application-druid.yml 里能看到关键参数:
spring: datasource: type: com.alibaba.druid.pool.DruidDataSource druid: initialSize: 5 # 初始连接数 minIdle: 10 # 最小空闲 maxActive: 20 # 最大活跃连接 maxWait: 60000 # 拿连接的等待上限 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true # 空闲时探活池子大小(maxActive/maxWait)是连接超时最常见的根因,别配得太小。
4.3 一个 REST 查询示例(JdbcTemplate,返回 JSON)
用JdbcTemplate两行代码就能把查询结果吐成 JSON 接口:
@RestController @RequestMapping("/rest/demo") public class DemoController { @Autowired private JdbcTemplate jdbcTemplate; @GetMapping("/skulist") public List<Map<String, Object>> list() { return jdbcTemplate.queryForList("SELECT * FROM sku_info"); } @GetMapping("/skulist/{id}") public Map<String, Object> byId(@PathVariable int id) { return jdbcTemplate.queryForMap("SELECT * FROM sku_info WHERE id = ?", id); } }项目整体长这样,controller出接口、service接业务、mapper管数据访问:
跑起来后,查列表返回一列 JSON:
按 ID 查单条,返回单个对象:
5. 从"能跑"到"跑得稳"
跑通只是起点。生产上真正拉开差距的,是下面这张避坑清单。🛠️
5.1 连接超时怎么排查
连不上、或卡一下才返回,按这个顺序查:
- FE 起没起?
query_port是不是 9030,被防火墙 / 安全组拦没拦。 - URL 里的
host:port是否真能通(telnet <host> 9030试一下)。 - 账号密码、库名对不对,有没有权限。
- 连接池的
maxActive够不够、maxWait会不会太短,导致拿不到连接而超时。
前两个是"连不上",后两个是"时快时慢",症状不一样,别混着查。
5.2 性能调优清单
- 分页:大结果集别一次全拉,
LIMIT offset, size分页查,前端滚动加载。 - fetchSize:流式取数时调
fetchSize,配合服务端游标,减少一次性占内存。 - 预编译复用:高频 SQL 用
PreparedStatement复用,省掉反复解析。 - 连接池:别裸
DriverManager,交给 HikariCP / Druid,并给池子配监控。 - 写路径分流:大批量写入走 Stream Load,别让 JDBC 逐行
INSERT扛主力。
收尾
一句话收束:把"连 FE 的 9030 端口 + MySQL 协议"这件事想明白,Doris JDBC 接入 Java 应用就没有玄学,剩下都是工程化细节。
想继续深入,可以看仓库里的现成资料:
- 官方文档入口:docs/
- Spring JDBC 完整示例:samples/doris-demo/spring-jdbc-demo/
- FE 查询端口配置:conf/fe.conf
【免费下载链接】dorisApache Doris is an easy-to-use, high performance and unified analytics database.项目地址: https://gitcode.com/gh_mirrors/dori/doris
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考