복붙노트

[SPRING] PostGIS Geometry로 Hibernate 지속 실패

SPRING

PostGIS Geometry로 Hibernate 지속 실패

이전 질문과 관련 있습니다. 나는 Hibernate를 사용하여 JTS를 사용하여 PostGIS 데이터베이스에 기하 객체를 작성하는 Spring Roo 애플리케이션을 가지고있다. 나는 내가 Geometry 객체를 정의 할 때의 문제를 고쳤다 고 생각한다. 그리고 지금 Hibernate는 persist () 메소드를 실행하고있다. 그러나 DB에 도달하기 전에 뭔가 잘못 될 것이고 나는 예외를 얻는다.

여기 몇 가지 흥미로운 내용이 있습니다. 먼저 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 속성이 하나 뿐인 객체)를 1 주일 이상 사용하려고했습니다. 기하학 객체를 String으로 대체하면 잘 동작합니다. 누구든지 그러한 오류를 일으키는 원인을 알 수 있습니까?

편집 : 티에리의 대답은 아래 소스를 통해 파고 있어요, 그리고 예외가 발생했습니다 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 dialect mapping에 뭔가 잘못되었다는 것을 제안하는 클래스 주석을 주목하라. 불행히도 그게 무슨 뜻인지는 모르겠지만 어떤 종류의 버전 불일치로 인해 추측하고 있습니다. (이전의 에러에 따라 SQL 타입 3000 선언에주의하십시오!)

현재 사용중인 dialect는 Hibernate Spatial 사용 설명서에 따라 org.hibernate.spatial.dialect.postgis.PostgisDialect입니다. 저는 Hibernate Spatial 4.0-M1, JTS 1.12 및 PostGIS 2.0.1을 사용하고 있습니다. 필자는 PostGIS의 몇 가지 다른 버전을 시도 할 것입니다. 특히 Hibernate Spatial이 제공 할 것으로 보이지만 보이지 않는 한 가지 종속성 때문입니다.

해결법

  1. ==============================

    1.문제는 PostgisDialect가 올바르게 선택되지 않아서 필요한 작업이 지원되지 않는다는 것입니다. 해결책은 Hibernate 3.6.9에서 최종 업그레이드하는 것만 큼 간단했습니다. 최종 4.1.6. 최종!

    문제는 PostgisDialect가 올바르게 선택되지 않아서 필요한 작업이 지원되지 않는다는 것입니다. 해결책은 Hibernate 3.6.9에서 최종 업그레이드하는 것만 큼 간단했습니다. 최종 4.1.6. 최종!

    자세한 내용은 메일 링리스트의 내 스레드를 참조하십시오.

    그 스레드에 따라 Hibernate Spatial 4.0-M1에서는 Geometry 타입 만이 Hibernate로 지정되어 있으므로 @Column 주석은 Point 나 다른 것이 아닌 columnDefinition = "Geometry"를 설정해야한다는 것을 알아야합니다. 이 문제는 앞으로 해결 될 수 있습니다.

    수정의 선집으로, 나는 마침내 데이터베이스에 포인트를 쓸 수 있습니다! 올바른 속성 지정은 다음과 같습니다.

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

    2.최대 절전 모드 구성 파일에 Postgis Dialect를 추가하는 것을 잊었을 때이 예외가 발생했습니다.

    최대 절전 모드 구성 파일에 Postgis Dialect를 추가하는 것을 잊었을 때이 예외가 발생했습니다.

    hibernate.cfg.xml에 다음 줄을 추가합니다.

    <property name="dialect">org.hibernate.spatial.dialect.postgis.PostgisDialect</property>
    
  3. ==============================

    3.그래? 저장해야하는 값으로 대체됩니다.

    그래? 저장해야하는 값으로 대체됩니다.

    GeometryType이 아닌 GeometryUserType 유형을 사용하려고 했습니까? 나는 GeometryType이 Hibernate Spatial Project의 API에 의해 직접적으로 지원되지 않는다고 생각한다. 어쩌면 어노테이션을 사용하여 데이터를 맵핑하기 위해 직접 인스턴스화 할 수없는 추상 클래스 일 것입니다. 이것은 우리가 실험 한 것처럼 장면 너머에서 작동합니다.

    원인 : 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은 PostgreSQL이라고 생각합니다.

    나는 Karel Maesen과 다른 사람들이 InnoDB 지원에 대해 이야기하는 몇 가지 주제를 발견하지 못했다. 그러나 그들은 아마도 구식 일 것이다 (05-2011).

    행운을 빕니다!

  4. from https://stackoverflow.com/questions/12236428/hibernate-persist-failure-with-postgis-geometry by cc-by-sa and MIT license