Hibernate通过PostGIS Geometry持久化失败 [英] Hibernate persist failure with PostGIS Geometry

查看:72
本文介绍了Hibernate通过PostGIS Geometry持久化失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

上一个问题相关。我有一个使用Hibernate的Spring Roo应用程序使用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 - 插入到land_use(center_point,version,id)值(?,?,?)
...

然后再发生一些事情,虽然没有明显的坏处。但是,我没有看到任何'最终'的SQL,并且试图回滚事务。然后:

  org.springframework.transaction.TransactionSystemException:无法提交JPA事务;嵌套异常是javax.persistence.RollbackException:在org.springframework.transaction.support的org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521)
处提交事务
时出错。 AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
在org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
在org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(
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 $坚持(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)
在com.test.LandUseController_Roo_Controller.ajc $ interMethod $ com_test_LandUseController_Roo_Controller $ com_test_LandUseController $创建(LandUseController_Roo_Controller.aj:29)在com.test.LandUseController.create(LandUseController.java:1)

$ ... b $ b导致:javax.persistence.RollbackException:在提交事务时出错
在org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:93)
在org.springframework.orm.jpa java.lang.UnsupportedOperationException
在org.hibernate.spatial.GeometrySqlTypeDescriptor.getBinder(GeometrySqlTypeDescriptor.java:.JpaTransactionManager.doCommit(JpaTransactionManager.java:512)
... 54多个
所致:52)
在org.hibernate.type.AbstractStandardBasicTy pe.nullSafeSet(AbstractStandardBasicType.java:283)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:278)
at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java: 89)
。在org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2184)
。在org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2430)
。在org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2874)
在org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:79)
在org.hibernate作为.engine.ActionQueue.execute(ActionQueue.java:273)
在org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
在org.hibernate.engine.ActionQueue.executeActions(ActionQueue .java:184)
在org.hibernate.event.def.AbstractFlushingEventLi stener.performExecutions(AbstractFlushingEventListener.java:321)
在org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
在org.hibernate.impl.SessionImpl.flush(SessionImpl。
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属性的对象)工作了一个多星期,并且在我的智慧的结尾。如果我用一个字符串替换Geometry对象,它就可以工作。有人知道什么可能会导致这样的错误?



编辑: Thierry的答案让我戳穿源代码,我注意到异常被引入 GeometrySqlTypeDescriptor ,它有一些有趣的内容:

  / * * 
*通用的< code> SqlTypeDescriptor< / code>旨在通过空间方言重新映射
*。
*
* @author Karel Maesen,Geovise BVBA
* creation-date:7/27/11
* /
public class GeometrySqlTypeDescriptor实现SqlTypeDescriptor {

public static final GeometrySqlTypeDescriptor INSTANCE = new GeometrySqlTypeDescriptor();

@Override
public int getSqlType(){
return 3000; //此值不会与当前定义的java.sql.Types值冲突。
}

@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();






$ b特别要注意的是, 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应该提供的一种依赖关系,但似乎并不是这样。

解决方案

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

请参阅我的邮件列表以获取更多信息



根据该线程,您还应该知道,从Hibernate Spatial 4.0-M1开始,只有Geometry类型被指定给Hibernate,因此 @Column 注释必须设置 columnDefinition =几何或其他任何东西。这可能会在未来修复。



通过这个修改文集,我终于可以写一个Point到数据库了!正确的属性规范是:

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ .hibernate.spatial.GeometryType)
私人点centerPoint;


Related to previous question. I have a Spring Roo application using Hibernate to write a Geometry object to a PostGIS database using JTS. I believe I've fixed the problems I had in defining my Geometry object, and now Hibernate is executing its persist() method, but something is going wrong just before it hits the DB and I'm getting the exception below.

Here are some interesting lines. First from the Hibernate logs, the object to be persisted, and then an SQL query (presumably the ? are substituted):

...
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 (?, ?, ?)
...

Then some more things happen, though nothing obviously bad. However I don't see any 'final' SQL, and there is an attempt to roll back the transaction. Then:

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

I've been trying to get this simple use case (an object with just a single Geometry property) working for over a week now, and am about at my wits' end. If I replace the Geometry object with a String it works just fine. Does anyone know what might be causing such an error?

EDIT: Thierry's answer below got me poking through the source, and I noticed the exception is thrown in GeometrySqlTypeDescriptor, which has some interesting contents:

/**
 * 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();
    }
}

In particular, note the class comment suggesting something is clearly wrong with the Hibernate dialect mapping. Unfortunately I have no idea what that means, but I'm guessing due to some kind of version mismatch. (Note also the declaration of SQL type 3000, as per my previous error!)

My current dialect is org.hibernate.spatial.dialect.postgis.PostgisDialect, as per the Hibernate Spatial usage guide. I'm using Hibernate Spatial 4.0-M1, JTS 1.12, and PostGIS 2.0.1. I'll try with a couple of different versions of PostGIS perhaps, particularly since that's the one dependency that Hibernate Spatial is supposed to provide but doesn't seem to.

解决方案

It seems the problem was that the PostgisDialect was not been picked up and integrated correctly, and hence the required operations were not supported. The solution was as simple as upgrading from Hibernate 3.6.9.Final to 4.1.6.Final!

See my thread on the mailing list for more information.

As per that thread, you should also be aware that as of Hibernate Spatial 4.0-M1, only the Geometry type is specified to Hibernate, and hence the @Column annotation must set columnDefinition="Geometry", and not Point or anything else. This may be fixed in the future.

With this anthology of modifications, I can finally write a Point to a database! The correct property specification is:

@Column(columnDefinition="Geometry")
@Type(type = "org.hibernate.spatial.GeometryType")
private Point centerPoint;

这篇关于Hibernate通过PostGIS Geometry持久化失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆