且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在定义PostGIS连接时未找到Oracle连接

更新时间:2022-10-14 19:20:00

正如所评论的,它让我觉得Hibernate将默认使用spatialDialect,它将首先从可用的中找到,在这种情况下,它是Oracle,尽管在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_nametransaction-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> 

或者:

 &LT; hibernate.mappingfile&GT; postgis.hbm.xml&LT; /hibernate.mappingfile> 

所以我会举例来说 postgis.hbm.xml file:

 <?xml version =1.0encoding =utf-8?> 
<!DOCTYPE hibernate-mapping PUBLIC
- // Hibernate / Hibernate映射DTD // EN
http://www.hibernate.org/dtd/hibernate-mapping- 3.0.dtd&GT;
< hibernate-mapping>
< typedef name =org.hibernatespatial.GeometryUserTypeclass =org.hibernatespatial.GeometryUserType>
< param name =dialect> org.hibernatespatial.postgis.PostgisDialect< / param>
< / typedef>
< / hibernate-mapping>

并且 oracle.hbm.xml

 <?xml version =1.0encoding =utf-8?> 
<!DOCTYPE hibernate-mapping PUBLIC
- // Hibernate / Hibernate映射DTD // EN
http://www.hibernate.org/dtd/hibernate-mapping- 3.0.dtd&GT;
< hibernate-mapping>
< typedef name =org.hibernatespatial.GeometryUserTypeclass =org.hibernatespatial.GeometryUserType>
< param name =dialect> org.hibernatespatial.oracle.OracleSpatial10gDialect< / param>
< / typedef>
< / hibernate-mapping>

我想知道是否有更好的方法来做到这一点,但在这些日子里我找不到,或者我在这里回答。希望这有助于某人。


I have an application running with Spring 3.1.1 , Hibernate 3.6.0.Final and Hibernate Spatial 1.1.1 on Tomcat 8.0.20. Until now, we were using Oracle 11.2.0.4 , but we want to migrate to PostgreSQL 9.2-1002.jdbc4 / PostGIS 2.1.6.

We will migrate the database schemas on different phases, so at some stage, we will need some connections to be working with Oracle and some with PostGIS. In order to begin developing and testing this, I removed any Oracle Maven dependency and added the necessary ones to work with Postgres as described in Hibernate Spatial 1.1.1 Tutorial, mostly :

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

In Tomcat context.xml I have configured one single connection by now :

<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" />

This works fine. I can insert a record into the database with an empty value in its Geometry field first, and then I will update it with a coordinate value for that point. The field is defined as :

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

That works, no problem. The issue comes as soon as I include Maven dependency for Oracle :

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

Even though I don't configure any additional connection nor change anything in my project in order to use Oracle, the record is inserted in Postgres as expected, but when it comes to update its Geometry field, I get the stacktrace pasted below, that is an unexpected "Problem finding Oracle Connection" even if the connection stays the same.

org.hibernatespatial.helper.FinderException: Couldn't get at the OracleSpatial Connection object from the PreparedStatement.

I can't understand why Hibernate would be able to insert the data into the database, but would look for an Oracle connection when trying to update spatial data, only when I add an Oracle Maven dependency which shouldn't be used, as I keep my connection configured for PostGIS.

Any idea about what I could be doing wrong?

Thanks in advance.

EDIT : It seems that when starting Tomcat and initializing GeometryUserType, the configure method is called with null as properties. So it defaults to a spatialDialect which will be the first it finds from the available. As there are two (Oracle and PostGIS) it will just pick the first one (which happens to be Oracle).

So I must be missing something in the configuration, but I thought it would be enough to go to the * persistence.xml * and declare that the persistence unit should use that dialect.

<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

As commented, it looked to me that Hibernate will default to a spatialDialect which will be the first it finds from the available, and in that case it was Oracle, despite whatever was specified in the persistence.xml.

The first workaround that I found was to annotate in the entity that for the GeometryUserType I would use Postgis dialect as in :

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

That would force Hibernate to use Postgis for that entity.

The second workaround, which worked better for me (I need to be able to configure this and use different dialects for one entity depending on the persistence unit and the environment) is to use a mapping file in the persistence unit.

<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>

In my pom file, I will make that mapping file to the one that I need, using Maven profiles and variables.

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

Or :

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

So I would have for example a postgis.hbm.xml file :

<?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>

And an 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>

I wonder if there is a better way to do this, but none that I could find during these days, or that I was answered here. Hope that this helps to somebody.