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

如何从Vert.x JDBCClient的SQLConnection获取底层java.sql.Connection?

在Vert.x中获取底层java.sql.Connection用于Liquibase

刚好我之前在Vert.x项目里集成Liquibase时也碰到过这个问题——Vert.x的SQLConnection是封装后的连接对象,没法直接给Liquibase用,必须拿到原生的java.sql.Connection才行。这里有两种靠谱的解决办法:

方案一:使用SQLConnection的unwrap方法(推荐)

Vert.x的SQLConnection接口其实提供了unwrap方法,这是JDBC标准的解包操作,可以直接获取底层的原生连接。这种方法通用性强,不需要耦合具体的连接池实现(比如C3P0)。

普通回调风格示例

JDBCClient jdbcClient = JDBCClient.createShared(vertx, config);

jdbcClient.getConnection(res -> {
    if (res.succeeded()) {
        SQLConnection vertxConn = res.result();
        
        // 调用unwrap获取底层JDBC连接
        vertxConn.unwrap(java.sql.Connection.class, unwrapResult -> {
            if (unwrapResult.succeeded()) {
                java.sql.Connection jdbcConn = unwrapResult.result();
                
                // 这里执行Liquibase操作
                try {
                    Database database = DatabaseFactory.getInstance()
                        .findCorrectDatabaseImplementation(new JdbcConnection(jdbcConn));
                    Liquibase liquibase = new Liquibase(
                        "db/changelog.xml", 
                        new ClassLoaderResourceAccessor(), 
                        database
                    );
                    liquibase.update(new Contexts());
                    System.out.println("Liquibase更新完成");
                } catch (LiquibaseException e) {
                    e.printStackTrace();
                } finally {
                    // 务必关闭连接,避免泄漏
                    try {
                        jdbcConn.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                    vertxConn.close();
                }
            } else {
                System.err.println("解包底层连接失败:" + unwrapResult.cause().getMessage());
                unwrapResult.cause().printStackTrace();
            }
        });
    } else {
        System.err.println("获取Vert.x连接失败:" + res.cause().getMessage());
        res.cause().printStackTrace();
    }
});

RxJava风格示例

如果你用的是RxJava版本的Vert.x SQL客户端,代码可以更简洁:

JDBCClient jdbcClient = JDBCClient.createShared(vertx, config);

jdbcClient.rxGetConnection()
    .flatMap(vertxConn -> vertxConn.rxUnwrap(java.sql.Connection.class)
        .doOnSuccess(jdbcConn -> {
            try {
                Database database = DatabaseFactory.getInstance()
                    .findCorrectDatabaseImplementation(new JdbcConnection(jdbcConn));
                Liquibase liquibase = new Liquibase(
                    "db/changelog.xml", 
                    new ClassLoaderResourceAccessor(), 
                    database
                );
                liquibase.update(new Contexts());
                System.out.println("Liquibase更新完成");
            } catch (LiquibaseException e) {
                throw new RuntimeException("Liquibase执行失败", e);
            } finally {
                // 关闭连接
                try {
                    jdbcConn.close();
                    vertxConn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        })
    )
    .subscribe(
        () -> {},
        error -> System.err.println("操作失败:" + error.getMessage())
    );

方案二:直接从C3P0数据源获取连接(不推荐)

如果你确定Vert.x底层用的是C3P0连接池,也可以直接创建并持有ComboPooledDataSource实例,然后从数据源直接获取原生连接。不过这种方法耦合了C3P0的实现,一旦换了连接池就会失效,所以不推荐。

// 创建C3P0数据源并配置
ComboPooledDataSource cpds = new ComboPooledDataSource();
try {
    cpds.setDriverClass("com.mysql.cj.jdbc.Driver");
    cpds.setJdbcUrl("jdbc:mysql://localhost:3306/test");
    cpds.setUser("root");
    cpds.setPassword("password");
} catch (PropertyVetoException e) {
    e.printStackTrace();
}

// 创建Vert.x的JDBC客户端
JDBCClient jdbcClient = JDBCClient.create(cpds);

// 直接从数据源获取原生连接用于Liquibase
try {
    java.sql.Connection jdbcConn = cpds.getConnection();
    // 执行Liquibase操作...
    jdbcConn.close();
} catch (SQLException e) {
    e.printStackTrace();
}

关键注意事项

  • 连接关闭:无论是哪种方案,用完后一定要关闭原生的java.sql.Connection和Vert.x的SQLConnection,避免连接池泄漏。
  • 异常处理:Liquibase操作可能抛出多种异常,务必做好捕获和处理。
  • 依赖检查:确保项目中已经引入了Liquibase的依赖,以及对应数据库的JDBC驱动。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:45:52