当前位置: 首页 > 知识库问答 >
问题:

oracle12c上的hibernate spatial-sdo_geometry对象在em.merge上变为空

朱海超
2023-03-14

有一个包含表示某些点的SDO_GEOMETRY类型列的表。稍后将执行像“显示距离x内的所有其他点”这样的空间查询。通过sqlloader将一些数据泵送到导入表后,如果业务键仍然存在,我将在合并时将这些数据集带入基表。

我的应用程序是一个使用< code>hibernate 5.0.9、< code > hibernate-spatial 5 . 0 . 9 final 、Oracle12c数据库和hibernate.dialect的可执行jar

org.hibernate.dialect.Oracle12cDialect

之前但现在改为

org.hibernate.spatial.dialect.oracle.OracleSpatial10gDialect

我知道只有一种空间方言,特别是用于Oracle10的,也有用于Orac莱11但用于Oracele12的测试者。

现在的问题是,对象通过hibernate存储到基表中,但是在SDO-Geometry中所有的坐标都是空的(而sdo_geometry对象不是)。

select
 businessKey,
 my_sdo_geometry.sdo_point.x longitude,
 my_sdo_geometry.sdo_point.y latitude
from my_import_table;

sqlloader之后,导入表中的所有坐标都显示良好。

但是在处理每个导入数据集后,它的列“导入”{Y, N}设置为“Y”。这样做我使用的是myEntityManager.merge(import Dataset)。由于这个原因(尽管alle坐标在sqlloader之后很好)导入数据集的坐标被清除为空。

//coordinates still viewable in database    
importObject.setImported(Boolean.TRUE);
em.merge(importObject);
//coordinates null now

我猜空间方言没有正常工作。我担心这是由于hibernate-spatial的上一个版本和oracle12c之间的不兼容造成的。

我写这篇文章是希望有人能在oracle12上成功地使用hibernate-spatial(澄清这是完全可能的),并希望我这边的任何不好的配置都能得到一些帮助。

我的应用程序的persistance.xml:

<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
    http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">

    <persistence-unit name="myUnit" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>

        <properties>
            <property name="hibernate.ejb.cfgfile" value="/hibernate.cfg.xml" />
            <property name="use_sql_comments" value="true" />
            <property name="hibernate.show_sql" value="false" />
            <property name="hibernate.format_sql" value="false" />
            <property name="hibernate.connection.driver_class" value="oracle.jdbc.driver.OracleDriver" />
            <property name="hibernate.connection.url" value="jdbc:oracle:thin:@123.456.789.1:1234/cm" />
            <property name="hibernate.connection.username" value="testMe" />
            <property name="hibernate.connection.password" value="********" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle12cDialect" />
        </properties>
    </persistence-unit> </persistence>

提前感谢。

编辑:在实体类中,sdo_geometry列(这里称为“位置”)的getter注释如下:

@Column(name = "POSITION", nullable = false)

public Point getPosition() {
    return this.position;
}

编辑2:启用Hibernatesql跟踪后,我发现Hibernate正在尝试此更新:

Hibernate: update IMPORT_TABLE set HB_VERSION=?, BUSINESS_KEY=?, IMPORTED=?, [...], POSITION=? where IMPORT_TABLE_ID=? and HB_VERSION=?

我指的是位置=


共有2个答案

权胜泫
2023-03-14

我发现了一个变通办法,它没有像我想的那样回答我的问题,但它是一个变通办法。

它不是使用hibernate对象和合并运算符,而是使用如下自定义查询时有效:

Query q = em.createQuery("INSERT INTO base_table"
            + "(techId, myBuildingFK, [...], my_sdo_geometry) "
            + "SELECT l.impTechId, b, [...], l.my_sdo_geometry"
            + "FROM import_table l, Buildiung b "
            + "WHERE l.businessKey = g.businessKey ");
q.executeUpdate();

有了这个HQL查询,我得到的坐标没有被清空。由于它仍然是一个HQL查询,可能仍然使用一些空间方言,但它似乎不能正常工作与实体管理器的合并命令。可能我仍然缺少一些注释在实体,以使它的工作可能与Oracle12不兼容。

我仍然希望其他人能给出比我更好的答案。

编辑:因为我需要合并行为,我想通过实体管理器合并对象,然后执行sql或hql更新以存储sdo_geometry,但由于事务未完成,因此没有要更新的数据集。

//        //not working
//        em.merge(mergeObject);

//        String updateQueryString =
//                "update BaseTable set sdo_geometry = :sdoGeometry" + " where baseTableId = :baseTableId";
//        Query updateQuery = em.createQuery(updateQueryString);
//        updateQuery.setParameter("sdoGeometry", mergeObject.getSdoGeometry());
//        updateQuery.setParameter("baseTableId", mergeObject.getBaseTableId());
//        int cnt = updateQuery.executeUpdate();

由于这个原因,我现在正在做一个原生的oracle合并语句,它确实可以按预期工作,但可以逃脱所有Hibernate行为,并且我认为它的架构很差。

String mergeQueryString = "MERGE INTO Base_Table gl "
    + "USING (SELECT * FROM Import_Table WHERE import_table_id = :importTableId) igl "
    + "ON (gl.base_table_id = :baseTableId) "
    + "WHEN MATCHED THEN UPDATE SET gl.my_sdo_geometry = igl.my_sdo_geometry "
    + "WHEN NOT MATCHED THEN INSERT (gl.baseTableId, gl.anyFkId, gl.my_sdo_geometry) "
    + "VALUES (id_gen_function, :anyFkId, igl.my_sdo_geometry)";
Query mergeQuery = em.createNativeQuery(mergeQueryString);
mergeQuery.setParameter("importTableId", importObject.getImportTableId());
mergeQuery.setParameter("baseTableId", refModelObject.getBaseTableId());
mergeQuery.setParameter("anyFkId", refModelObject.getAnyFkObject().getAnyFkId());
int cnt = mergeQuery.executeUpdate();
濮阳宏硕
2023-03-14

默认情况下,Hibernate空间将坐标存储在SDO_Ordinates数组中,即使对于点也是如此。不使用 SDO_Geometry.SDO_Point 字段,因此将始终为 null。在 SQL 中,您可以使用SDO_UTIL。GetVertices() 函数来访问坐标数据

在geo latte-geom 1.1或更高版本中,您应该能够设置geo latte _ USE _ SDO _ POINT _ TYPE Java系统属性。使用该属性集,点几何将存储在SDO_Geometry中。SDO_Point字段。如果您的Hibernate版本使用较旧的Geolatte-geom版本,您可能希望在类路径中添加一个较新的版本,以便使用该特性。

顺便说一句。Hibernate空间通过将Java几何编码为可以在准备好的语句中设置的值来工作,因此生成的SQL中的“...位置=?”部分很好。

 类似资料:
  • 问题内容: 代码段-1 代码段-2 我在第一个代码段中遇到了竞争。我知道这是因为我正在获得对不可变对象(类型为Integer)的锁定。 我已经写了第二个代码片段,这再次使“布尔”不变。但这有效(输出运行中不显示竞争条件)。如果我正确理解了上一个问题的解决方案,则以下是出现问题的一种可能方法 线程1锁定由指向的对象(例如A) 线程2现在试图获取由指向的对象的锁,并进入A的等待队列。 线程1进入同步块

  • 问题内容: 考虑以下数据框: 以下命令起作用: 但以下任何一项均无效: 为什么? 文档中的示例似乎建议通过调用transform组,可以进行行操作处理: 换句话说,我认为转换本质上是一种特定的应用类型(不聚合的类型)。我哪里错了? 供参考,以下是上面原始数据帧的构造: 问题答案: apply和之间的两个主要区别transform 和方法之间有两个主要区别。 输入: 将每个组的所有列作为DataFr

  • 好的,这是我的代码。包装Mypanal;

  • 问题内容: 为什么这项工作无效: 我得到: 问题答案: 将的定义更改为 将方法的返回值分配给后面的名称。您的退货,已分配给。 我还将该类更改为一种新式的类(使其起作用并不关键)。

  • 问题内容: 我知道您无法在中初始化对象。我一直在互联网上搜索,但只找到了一个可能的答案,可以使用但在实现方面没有太多细节。我要问他们是成功实施它还是有实现它的想法的人,可以通过以外的其他方式来确定。 目前,我仅使用以下内容: 我正在寻找实现的东西是这样的。 PS。我是selenium的新手,也是回来的Java开发人员,所以请好好对待我:) 问题答案: 由于没有人分享某些东西,因此我将分享我的做法。

  • 我有两个程序。第一个分配共享内存文件,第二个从中读取。。我使用placement new将对象放置到此内存中,以确保对象不会使用新的或分配共享内存文件之外的任何内存。 我的阵列结构: 方案1: 方案2: > 程序一将SHMArray放置在内存中,位置为new。程序二在程序一已经放置的对象上做同样的事情(覆盖它)。这是未定义的行为吗?我认为不是,但我想确认一下。 两个程序都不调用析构函数数组- 我基