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

Quarkus 3.2.4中Hibernate Reactive Geometry映射遇ClassCastException

Quarkus Hibernate Reactive Panache + MySQL空间类型 ClassCastException 问题分析

这确实是一个兼容性Bug,仅在MySQL + Hibernate Reactive场景下触发,PostgreSQL正常是因为对应的Reactive方言已适配了客户端的空间类型处理逻辑。

问题原因

Hibernate Spatial的MySQL方言在Reactive模式下,仍沿用传统JDBC的处理方式,尝试将数据库返回的空间类型读取为Buffer字节流;但Vertx MySQL客户端会直接把MySQL的POINT类型映射为io.vertx.mysqlclient.data.spatial.Point对象,而非原始WKB字节,这就导致了类型强制转换失败(Point无法转为Buffer)。

解决方案

方案1:升级Quarkus版本

Quarkus 3.3及后续版本已经修复了Hibernate Reactive与MySQL空间类型的适配问题,直接升级到最新稳定版即可解决该错误。

方案2:临时自定义类型适配(无法升级时)

如果暂时无法升级Quarkus,可以自定义一个JdbcType来适配Vertx返回的空间类型,实现io.vertx.mysqlclient.data.spatial.Point到org.locationtech.jts.geom.Point的转换:

  1. 自定义JdbcType实现类:
import io.vertx.mysqlclient.data.spatial.Point;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.BasicBinder;
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

public class MySQLReactiveGeometryType implements JdbcType {

    private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory();

    @Override
    public int getJdbcTypeCode() {
        return Types.OTHER;
    }

    @Override
    public <X> ValueBinder<X> getBinder(JavaType<X> javaType) {
        return new BasicBinder<>(javaType, this) {
            @Override
            protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
                org.locationtech.jts.geom.Point jtsPoint = javaType.unwrap(value, org.locationtech.jts.geom.Point.class, options);
                Point vertxPoint = new Point(jtsPoint.getX(), jtsPoint.getY());
                st.setObject(index, vertxPoint);
            }
        };
    }

    @Override
    public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
        return new BasicExtractor<>(javaType, this) {
            @Override
            protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
                Point vertxPoint = rs.getObject(paramIndex, Point.class);
                org.locationtech.jts.geom.Point jtsPoint = GEOMETRY_FACTORY.createPoint(
                        new Coordinate(vertxPoint.getX(), vertxPoint.getY())
                );
                return javaType.wrap(jtsPoint, options);
            }
        };
    }
}
  1. 在实体类的geom字段上指定该自定义类型:
@Column(columnDefinition = "geometry")
@Type(MySQLReactiveGeometryType.class)
public Point geom;

注意:确保项目依赖中已包含io.quarkus:quarkus-hibernate-reactive-spatial依赖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 17:00:33