2015-05-07 54 views
0

我有一個運行於Tomcat 8.0.20上的Spring 3.1.1,Hibernate 3.6.0.Final和Hibernate Spatial 1.1.1的應用程序。到目前爲止,我們使用的是Oracle 11.2.0.4,但我們希望遷移到PostgreSQL 9.2-1002.jdbc4/PostGIS 2.1.6。定義PostGIS連接時未找到Oracle連接

我們將在不同階段遷移數據庫模式,因此在某個階段,我們需要一些連接來與Oracle合作,一些連接使用PostGIS。爲了開始開發和測試這個,我刪除任何Oracle Maven的依賴,並增加有需要的與Postgres一起工作,在Hibernate Spatial 1.1.1 Tutorial描述,主要是:

<dependency> 
    <groupId>org.hibernatespatial</groupId> 
    <artifactId>hibernate-spatial-postgis</artifactId> 
    <version>1.1.1</version> 
</dependency> 

在Tomcat中的context.xml 配置了一個單連接現在:

<Resource accessToUnderlyingConnectionAllowed="true" auth="Container" 
    autoReconnect="true" driverClassName="org.postgresql.Driver" 
    logAbandoned="true" maxWait="5000" minEvictableIdleTimeMillis="60000" 
    name="jdbc/dbname" numTestsPerEvictionRun="3" password="xxx" 
    removeAbandoned="true" removeAbandonedTimeout="60" testOnBorrow="true" 
    testWhileIdle="true" timeBetweenEvictionRunsMillis="60000" 
    type="javax.sql.DataSource" url="jdbc:postgresql://servername:5432/dbname" 
    username="username" validationQuery="select 1" /> 

這工作得很好。我可以在數據庫中插入一條記錄,首先在其幾何字段中輸入一個空值,然後我將用該點的座標值更新它。該字段的定義如下:

@Type(type = "org.hibernatespatial.GeometryUserType") 
@Column(name = "geom", columnDefinition="Geometry", nullable = true) 
protected Geometry geom; 

這是行得通的,沒問題。

<dependency> 
      <artifactId>hibernate-spatial-oracle</artifactId> 
      <groupId>org.hibernatespatial</groupId> 
      <version>1.1.1</version> 
     </dependency> 

即使我不配置任何額外的連接,也沒有爲了使用Oracle在我的項目改變什麼,記錄插入Postgres的預期:這個問題,只要我包括甲骨文Maven的依賴來,但是當涉及到更新其幾何字段時,即使連接保持不變,我也會在下面粘貼堆棧跟蹤,這是意想不到的「發現Oracle連接問題」。

org.hibernatespatial.helper.FinderException:無法從PreparedStatement獲取OracleSpatial Connection對象。

我不明白爲什麼Hibernate能夠將數據插入到數據庫中,但在嘗試更新空間數據時會查找Oracle連接,僅當添加不應該是Oracle Maven依賴項時使用,因爲我保持爲PostGIS配置連接。

有關我可能做錯什麼的想法嗎?

在此先感謝。

編輯:看起來,當啓動Tomcat和初始化GeometryUserType時,configure方法被稱爲null作爲屬性。所以它默認爲一個spatialDialect,它將是第一個從可用的中找到的。由於有兩個(Oracle和PostGIS),它只會選擇第一個(恰好是Oracle)。

所以我必須在配置中丟失一些東西,但我認爲這足以進入* persistence.xml *並聲明持久化單元應該使用該方言。

<persistence-unit name="pu_name" transaction-type="JTA"> 
<provider>org.hibernate.ejb.HibernatePersistence</provider> 
     <jta-data-source>${jta.datasource.prefix}datasource_name</jta-data-source> 
     <class>com.myorganization.MyClass</class> 
     <exclude-unlisted-classes>true</exclude-unlisted-classes> 
     <properties> 
      <property name="hibernate.dialect" value="org.hibernatespatial.postgis.PostgisDialect" /> 
(...) 

javax.persistence.PersistenceException: org.hibernate.HibernateException: Problem finding Oracle Connection 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1389) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1317) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1323) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:965) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365) 
    at com.sun.proxy.$Proxy62.flush(Unknown Source) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240) 
    at com.sun.proxy.$Proxy45.flush(Unknown Source) 
    at com.mapflow.geotagdata.common.processing.impl.ProcessorInnerStepsImpl$6.executeTransactionalCommand(ProcessorInnerStepsImpl.java:1056) 
    at com.mapflow.geotagdata.common.processing.impl.ProcessorInnerStepsImpl$6.executeTransactionalCommand(ProcessorInnerStepsImpl.java:1) 
    at com.mapflow.geotagdata.common.transactions.TransactionalCommandExecutor.executeTxRequiresNew(TransactionalCommandExecutor.java:37) 
    at com.mapflow.geotagdata.common.transactions.TransactionalCommandExecutor$$FastClassByCGLIB$$7beb81b5.invoke(<generated>) 
    at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191) 
    at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622) 
    at com.mapflow.geotagdata.common.transactions.TransactionalCommandExecutor$$EnhancerByCGLIB$$4c535b1b.executeTxRequiresNew(<generated>) 
    at com.mapflow.geotagdata.common.processing.impl.ProcessorInnerStepsImpl.synchPendingTaggedBatchToDB(ProcessorInnerStepsImpl.java:1012) 
    at com.mapflow.geotagdata.common.processing.impl.ProcessorInnerStepsImpl.access$0(ProcessorInnerStepsImpl.java:996) 
    at com.mapflow.geotagdata.common.processing.impl.ProcessorInnerStepsImpl$5.call(ProcessorInnerStepsImpl.java:969) 
    at com.mapflow.geotagdata.common.processing.impl.ProcessorInnerStepsImpl$5.call(ProcessorInnerStepsImpl.java:1) 
    at com.mapflow.geotagdata.common.processing.utility.RetryOnExceptionBuilder.execute(RetryOnExceptionBuilder.java:96) 
    at com.mapflow.geotagdata.common.processing.impl.ProcessorInnerStepsImpl.dataTaggingPhase(ProcessorInnerStepsImpl.java:964) 
    at com.mapflow.geotagdata.common.processing.impl.ProcessorOuterStepsImpl.doOuterStepLineByLineInnerSteps(ProcessorOuterStepsImpl.java:107) 
    at com.mapflow.geotagdata.common.processing.impl.ProcessorImpl.process(ProcessorImpl.java:149) 
    at com.mapflow.geotagdata.common.processing.impl.ProcessorImpl.processFile(ProcessorImpl.java:80) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    at org.springframework.aop.interceptor.AsyncExecutionInterceptor$1.call(AsyncExecutionInterceptor.java:80) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: org.hibernate.HibernateException: Problem finding Oracle Connection 
    at org.hibernatespatial.oracle.OracleJDBCTypeFactory.createStruct(OracleJDBCTypeFactory.java:38) 
    at org.hibernatespatial.oracle.SDOGeometry.store(SDOGeometry.java:154) 
    at org.hibernatespatial.oracle.SDOGeometryType.conv2DBGeometry(SDOGeometryType.java:88) 
    at org.hibernatespatial.oracle.SDOGeometryType.nullSafeSet(SDOGeometryType.java:77) 
    at org.hibernatespatial.GeometryUserType.nullSafeSet(GeometryUserType.java:201) 
    at org.hibernate.type.CustomType.nullSafeSet(CustomType.java:140) 
    at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2184) 
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2559) 
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2495) 
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2822) 
    at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:113) 
    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:185) 
    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.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:962) 
    ... 44 more 
Caused by: org.hibernatespatial.helper.FinderException: Couldn't get at the OracleSpatial Connection object from the PreparedStatement. 
    at org.hibernatespatial.oracle.DefaultConnectionFinder.find(DefaultConnectionFinder.java:82) 
    at org.hibernatespatial.oracle.DefaultConnectionFinder.find(DefaultConnectionFinder.java:68) 
    at org.hibernatespatial.oracle.DefaultConnectionFinder.find(DefaultConnectionFinder.java:68) 
    at org.hibernatespatial.oracle.DefaultConnectionFinder.find(DefaultConnectionFinder.java:51) 
    at org.hibernatespatial.oracle.OracleJDBCTypeFactory.createStruct(OracleJDBCTypeFactory.java:36) 
    ... 61 more 

回答

0

至於評論,它看起來對我來說,Hibernate會默認爲spatialDialect這將是第一個從現有的發現,在這種情況下,它是甲骨文,儘管無論指定在persistence.xml中。

第一個解決方法,我發現是,對於GeometryUserType我會用POSTGIS方言作爲實體註釋:

@TypeDefs({@TypeDef(name="org.hibernatespatial.GeometryUserType", 
     parameters={@org.hibernate.annotations.Parameter(name="dialect",value="org.hibernatespatial.postgis.PostgisDialect")}, 
     typeClass=org.hibernatespatial.GeometryUserType.class)}) 

這將強制Hibernate使用POSTGIS該實體。

第二個解決方法對我更好(我需要能夠配置此方法,並根據持久性單元和環境對一個實體使用不同的方言)是在持久單元中使用映射文件。

<persistence-unit name="persistence_unit_name" transaction-type="JTA"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <jta-data-source>jta_data_source_name</jta-data-source> 
    <mapping-file>${hibernate.mappingfile}</mapping-file> 
    <class>(...)</class> 

在我的POM文件,我會作出這樣的映射文件的一個,我需要,使用Maven型材和變量。

<hibernate.mappingfile>oracle.hbm.xml</hibernate.mappingfile> 

或者:

<hibernate.mappingfile>postgis.hbm.xml</hibernate.mappingfile> 

所以我不得不例如postgis.hbm.xml文件:

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN" 
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping> 
    <typedef name="org.hibernatespatial.GeometryUserType" class="org.hibernatespatial.GeometryUserType" > 
     <param name="dialect">org.hibernatespatial.postgis.PostgisDialect</param> 
    </typedef> 
</hibernate-mapping> 

而一個oracle.hbm.xml

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN" 
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping> 
    <typedef name="org.hibernatespatial.GeometryUserType" class="org.hibernatespatial.GeometryUserType" > 
     <param name="dialect">org.hibernatespatial.oracle.OracleSpatial10gDialect</param> 
    </typedef> 
</hibernate-mapping> 

我不知道是否有一個更好的方法這個,但在這些日子裏我找不到,或者我在這裏得到了答覆。希望這有助於某人。