8

与上一个问题有关。我有一个 Spring Roo 应用程序,它使用 Hibernate 使用 JTS 将 Geometry 对象写入 PostGIS 数据库。我相信我已经解决了我在定义 Geometry 对象时遇到的问题,现在 Hibernate 正在执行它的 persist() 方法,但是在它到达数据库之前出现了问题,我得到了下面的异常。

这里有一些有趣的线条。首先来自 Hibernate 日志,要持久化的对象,然后是 SQL 查询(大概是 ? 被替换了):

...
DEBUG org.hibernate.pretty.Printer - com.test.LandUse{id=1, centerPoint=POINT (5 6), version=0}
...
DEBUG org.hibernate.SQL - insert into land_use (center_point, version, id) values (?, ?, ?)
...

然后发生了更多的事情,虽然没有什么明显的坏事。但是我没有看到任何“最终”SQL,并且尝试回滚事务。然后:

org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$afterReturning$org_springframework_transaction_aspectj_AbstractTransactionAspect$3$2a73e96c(AbstractTransactionAspect.aj:78)
    at com.test.LandUse_Roo_Jpa_ActiveRecord.ajc$interMethod$com_test_LandUse_Roo_Jpa_ActiveRecord$com_test_LandUse$persist(LandUse_Roo_Jpa_ActiveRecord.aj:44)
    at com.test.LandUse.persist(LandUse.java:1)
    at com.test.LandUse_Roo_Jpa_ActiveRecord.ajc$interMethodDispatch1$com_test_LandUse_Roo_Jpa_ActiveRecord$com_test_LandUse$persist(LandUse_Roo_Jpa_ActiveRecord.aj)
    at com.test.LandUseController_Roo_Controller.ajc$interMethod$com_test_LandUseController_Roo_Controller$com_test_LandUseController$create(LandUseController_Roo_Controller.aj:29)
    at com.test.LandUseController.create(LandUseController.java:1)
...
Caused by: javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:93)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:512)
    ... 54 more
Caused by: java.lang.UnsupportedOperationException
    at org.hibernate.spatial.GeometrySqlTypeDescriptor.getBinder(GeometrySqlTypeDescriptor.java:52)
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:283)
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:278)
    at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:89)
    at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2184)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2430)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2874)
    at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:79)
    at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
    at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:76)
    ... 55 more

我一直试图让这个简单的用例(一个只有一个 Geometry 属性的对象)工作了一个多星期,现在我已经束手无策了。如果我用 String 替换 Geometry 对象,它就可以正常工作。有谁知道什么可能导致这样的错误?

编辑:蒂埃里在下面的回答让我浏览了源代码,我注意到异常被抛出GeometrySqlTypeDescriptor,其中有一些有趣的内容:

/**
 * A generic <code>SqlTypeDescriptor</code>, intended to be remapped
 * by the spatial dialect.
 *
 * @author Karel Maesen, Geovise BVBA
 *         creation-date: 7/27/11
 */
public class GeometrySqlTypeDescriptor implements SqlTypeDescriptor {

    public static final GeometrySqlTypeDescriptor INSTANCE = new GeometrySqlTypeDescriptor();

    @Override
    public int getSqlType() {
        return 3000; //this value doesn't conflict with presently defined java.sql.Types values.
    }

    @Override
    public boolean canBeRemapped() {
        return true;
    }

    @Override
    public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
        throw new UnsupportedOperationException();
    }

    @Override
    public <X> ValueExtractor<X> getExtractor(JavaTypeDescriptor<X> javaTypeDescriptor) {
        throw new UnsupportedOperationException();
    }
}

特别是,请注意类注释表明 Hibernate 方言映射明显有问题。不幸的是,我不知道这意味着什么,但我猜是由于某种版本不匹配。(还要注意 SQL 类型 3000 的声明,根据我之前的错误!)

org.hibernate.spatial.dialect.postgis.PostgisDialect根据Hibernate Spatial 使用指南,我目前的方言是。我正在使用 Hibernate Spatial 4.0-M1、JTS 1.12 和 PostGIS 2.0.1。我可能会尝试几个不同版本的 PostGIS,特别是因为这是 Hibernate Spatial 应该提供但似乎没有提供的一个依赖项。

4

3 回答 3

14

似乎问题在于没有正确拾取和集成 PostgisDialect,因此不支持所需的操作。解决方案就像从 Hibernate 3.6.9.Final 升级到 4.1.6.Final 一样简单!

有关详细信息,请参阅我在邮件列表中的主题

根据该线程,您还应该知道,从 Hibernate Spatial 4.0-M1 开始,只有 Geometry 类型被指定为 Hibernate,因此@Column注释必须设置columnDefinition="Geometry",而不是 Point其他任何内容。这可能会在未来得到解决。

有了这本修改集,我终于可以写一个指向数据库的点了!正确的属性规范是:

@Column(columnDefinition="Geometry")
@Type(type = "org.hibernate.spatial.GeometryType")
private Point centerPoint;
于 2012-09-04T10:04:04.673 回答
2

当我忘记在休眠配置文件中添加 Postgis 方言时,我得到了这个异常。

将以下行添加到hibernate.cfg.xml

<property name="dialect">org.hibernate.spatial.dialect.postgis.PostgisDialect</property>
于 2015-11-07T22:53:08.933 回答
1

是的,?它们被您需要存储的值替换。

您是否尝试使用以下类型:GeometryUserType而不是GeometryType? 我怀疑GeometryTypeHibernate Spatial Project 的 API 不直接支持。它可能是一个抽象类,您无法直接实例化它以使用注释映射您的数据 - 正如我们所试验的那样,它的作用超出了场景。

Caused by: java.lang.UnsupportedOperationException这让我这么说。

您遵循的教程中的最后一个 XML 内容很清楚:

...
<property name="geometry" type="org.hibernatespatial.GeometryUserType">
    <column name="geom" />
</property>
...

查看GeometryUserType中的代码,我只看到一个可能引发这些异常的地方。

public Object conv2DBGeometry(Geometry jtsGeom, Connection connection) {
        org.postgis.Geometry geom = null;
        jtsGeom = forceEmptyToGeometryCollection(jtsGeom);
        if (jtsGeom instanceof com.vividsolutions.jts.geom.Point) {
            geom = convertJTSPoint((com.vividsolutions.jts.geom.Point) jtsGeom);
        } else if (jtsGeom instanceof com.vividsolutions.jts.geom.LineString) {
            geom = convertJTSLineString((com.vividsolutions.jts.geom.LineString) jtsGeom);
        } else if (jtsGeom instanceof com.vividsolutions.jts.geom.MultiLineString) {
            geom = convertJTSMultiLineString((com.vividsolutions.jts.geom.MultiLineString) jtsGeom);
        } else if (jtsGeom instanceof com.vividsolutions.jts.geom.Polygon) {
            geom = convertJTSPolygon((com.vividsolutions.jts.geom.Polygon) jtsGeom);
        } else if (jtsGeom instanceof com.vividsolutions.jts.geom.MultiPoint) {
            geom = convertJTSMultiPoint((com.vividsolutions.jts.geom.MultiPoint) jtsGeom);
        } else if (jtsGeom instanceof com.vividsolutions.jts.geom.MultiPolygon) {
            geom = convertJTSMultiPolygon((com.vividsolutions.jts.geom.MultiPolygon) jtsGeom);
        } else if (jtsGeom instanceof com.vividsolutions.jts.geom.GeometryCollection) {
            geom = convertJTSGeometryCollection((com.vividsolutions.jts.geom.GeometryCollection) jtsGeom);
        }

        if (geom != null)
            return new PGgeometry(geom);
        else
            throw new UnsupportedOperationException("Conversion of "
                    + jtsGeom.getClass().getSimpleName()
                    + " to PGgeometry not supported");
    }

我认为PGgeometry代表PostGis Geometry(或者可能是PostgreSQL)。

我发现 Karel Maesen 和其他人谈论 InnoDB 支持的一些主题不是很好,但它们可能已经过时(05-2011)。

祝你好运!

于 2012-09-02T14:46:10.370 回答