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

如何用jOOQ从DuckDB中获取WKB(Blob类型)字段?

解决jOOQ读取DuckDB中WKB几何列的BufferUnderflowException问题

自定义jOOQ绑定处理WKB列

DuckDB JDBC驱动读取Blob时抛出的BufferUnderflowException,大概率是驱动对Blob的实现不符合JDBC标准导致的。可以通过自定义jOOQ绑定绕开默认Blob处理逻辑,直接读取原始字节:

import org.jooq.*;
import org.jooq.impl.AbstractBinding;
import java.sql.*;

public class WkbBinding extends AbstractBinding<byte[], byte[]> {
    @Override
    public Converter<byte[], byte[]> converter() {
        return Converters.identityConverter();
    }

    @Override
    public void set(BindingSetStatementContext<byte[]> ctx) throws SQLException {
        ctx.statement().setBytes(ctx.index(), ctx.value());
    }

    @Override
    public void get(BindingGetResultSetContext<byte[]> ctx) throws SQLException {
        byte[] bytes = ctx.resultSet().getBytes(ctx.index());
        ctx.value(bytes);
    }

    @Override
    public void get(BindingGetStatementContext<byte[]> ctx) throws SQLException {
        byte[] bytes = ctx.statement().getBytes(ctx.index());
        ctx.value(bytes);
    }
}

在jOOQ代码生成配置中,指定该绑定到所有WKB几何列:

<forcedTypes>
    <forcedType>
        <userType>byte[]</userType>
        <binding>com.yourpackage.WkbBinding</binding>
        <includeExpression>LOCATION\.GEOM|.*\.GEOM</includeExpression>
    </forcedType>
</forcedTypes>

升级DuckDB JDBC驱动

这类BufferUnderflowException通常是驱动的已知bug,后续版本大概率会修复。尝试升级到最新稳定版的DuckDB JDBC驱动:

<dependency>
    <groupId>org.duckdb</groupId>
    <artifactId>duckdb_jdbc</artifactId>
    <version>0.9.2</version> <!-- 替换为最新版本 -->
</dependency>

优化临时SQL函数方案的映射问题

如果暂时需要使用ST_AsText(ST_GeomFromWKB(LOCATION.GEOM))的临时方案,可以通过别名匹配解决Record映射问题:

Result<LocationRecord> result = dsl.select(
    LOCATION.ID,
    LOCATION.NAME,
    ST_AsText(ST_GeomFromWKB(LOCATION.GEOM)).as(LOCATION.GEOM.getName())
).from(LOCATION).fetchInto(LocationRecord.class);

或者自定义Converter,将WKT字符串直接转换为几何对象,并配置到代码生成器中,让自动生成的Record类直接映射为几何类型。

配置jOOQ代码生成器识别几何类型

如果使用JTS等几何库,可以直接将Blob类型的WKB列映射为几何对象:

  1. 添加JTS依赖
  2. 实现WKB与几何对象的Converter:
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.WKBReader;
import org.locationtech.jts.io.WKBWriter;
import org.jooq.Converter;

public class WkbToGeometryConverter implements Converter<byte[], Geometry> {
    private final WKBReader reader = new WKBReader();
    private final WKBWriter writer = new WKBWriter();

    @Override
    public Geometry from(byte[] t) {
        if (t == null) return null;
        try {
            return reader.read(t);
        } catch (Exception e) {
            throw new RuntimeException("解析WKB失败", e);
        }
    }

    @Override
    public byte[] to(Geometry u) {
        if (u == null) return null;
        return writer.write(u);
    }

    @Override
    public Class<byte[]> fromType() {
        return byte[].class;
    }

    @Override
    public Class<Geometry> toType() {
        return Geometry.class;
    }
}
  1. 在代码生成配置中指定该Converter:
<forcedTypes>
    <forcedType>
        <userType>org.locationtech.jts.geom.Geometry</userType>
        <converter>com.yourpackage.WkbToGeometryConverter</converter>
        <includeExpression>.*\.GEOM</includeExpression>
    </forcedType>
</forcedTypes>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 19:05:24