Hibernate OGM

常见问题解答

Hibernate OGM 已经不再维护了。

Hibernate OGM 设计

JPA 是否适合 NoSQL?

这是一个百万美元的问题,但本质上,我们认为它非常适合。以下是 JPA 有意义的几个主要原因。

抽象级别的优势

JPA 在对象级别抽象持久性,留下了很多技巧和优化空间。举几个例子,想想声明式数据/模式迁移、声明式反规范化、多语言持久性。多语言持久性尤其有趣:将数据存储在多个数据存储中,并使用最适合特定读取作业的数据存储。

当然,如果您的数据集本质上不是以领域模型为中心的,那么 Hibernate OGM 不适合您。

事情很合适

虽然我们最初持怀疑态度,但 JPA 的大多数逻辑模型都适合。例如,一个 @Embeddable 对象或 @ElementCollection 很好地适合嵌套相关对象的文档数据存储方法。

我们在 Hibernate OGM 中努力使用最自然的映射来匹配给定的数据模式,并且我们提供您在需要时覆盖该映射的能力。

已知语义和 API

无论好坏,JPA 对 Java 开发人员来说都是耳熟能详的。他们熟悉它的 API 和语义。与学习特定低级 API 或更糟的是一些伪 ORM 级 API 相比,这是一个巨大的胜利。我们还支持 HQL 和原生后端查询!

后期后端选择

选择 NoSQL 引擎并非易事。能够自由地切换后端而无需重写所有数据层绝对是值得赞赏的。

您是否支持关系型数据库和 NoSQL 数据库?

是的。您可以在同一个应用程序中启动 Hibernate ORM 和 Hibernate OGM。您甚至可以在同一个应用程序中启动多个 Hibernate OGM 实例。只需确保您不在持久性单元之间共享相同的实体,并且没有两个由不同持久性单元处理的实体之间的关联。

<?xml version="1.0" encoding="UTF-8"?>
<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_2_0.xsd"
             version="2.0">
    <persistence-unit name="ogm-mongodb" transaction-type="JTA">
        <provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <class>com.acme.domain.catalog.Catalog</class>
        <properties>
            <property name="hibernate.ogm.datastore.provider" value="mongodb" />
            <property name="hibernate.ogm.datastore.database" value="catalog" />
        </properties>
    </persistence-unit>
    <persistence-unit name="orm-oracle" transaction-type="JTA">
        <datasource>some/db/Oracle</datasource>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <class>com.acme.domain.order.Order</class>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>
        </properties>
    </persistence-unit>
</persistence>

但是,您不能将相同的实体(或与关联链接的实体)同时放入关系型存储和 NoSQL 存储中。或者至少,Hibernate OGM 还没有为您做到这一点。这是我们将来想要探索的事情。

使用 Hibernate OGM

Hibernate OGM 如何处理事务?

与 Hibernate ORM 一样,Hibernate OGM 与事务正交且无关,但在可能的情况下将 flush 事件集成到事务中。

请务必通过应用程序容器或通过 Hibernate OGM 事务分界方法来分隔您的事务。参考文档详细介绍了如何在各种事务环境中设置 Hibernate OGM。

请注意,即使您的数据存储不支持事务,我们也建议您使用 Hibernate OGM 的事务分界来透明地触发 flush 操作(在提交时)。但不要将回滚视为一种可能性,这将不起作用。

Hibernate OGM 如何处理事务提交时的错误?

如果后端是事务性的(Infinispan、Neo4j),则事务可以在错误发生时回滚。数据存储将处于与之前相同的状态,就像您从关系型数据库中知道的那样。

对于非事务性后端(例如 MongoDB、CouchDB),如果在 flush 周期的中间发生错误,一些更改可能已经应用于数据存储。对于这种情况,Hibernate OGM 提供了错误处理和补偿 API。这允许您决定在 flush 期间发生错误时该做什么(中止、继续),并为您提供迄今为止应用的所有操作,如果触发了“回滚”。

查看参考指南以了解详细信息。请注意,此 API 目前正在开发中;如果您有任何想法或要求,请告知我们并与我们联系!

在 Neo4j 中,我收到 org.neo4j.graphdb.NotInTransactionException

Neo4j 确实要求在事务中运行所有操作,即使是只读操作。请务必显式或通过 Java EE 或 Spring 等容器来分隔您的事务。

使用 MongoDB 时,我收到 java.lang.NoSuchFieldError: ERRORS_IGNORED 异常

您正在使用 MongoDB 驱动程序 3.x 与 Hibernate OGM 4.2。Hibernate OGM 在此阶段使用 MongoDB 驱动程序 2.13。您不应该看到任何功能损失,您可以使用这种组合来访问 MongoDB 3 数据库 - 我知道这令人困惑。

我们计划在不久的将来升级到 MongoDB 3,我们已经确定了 Mongo 团队正在解决的错误。

我的更改未应用于后端,错误在哪里?

很可能您忘记了分隔事务或手动调用 flush()。

即使您的数据存储不支持事务,我们也建议您使用 Hibernate OGM 的事务分界来透明地触发 flush 操作(在提交时)。但不要将回滚视为一种可能性,这将不起作用。

我如何查询?

主要有三种方法

  • 使用 Hibernate Search 作为索引引擎并使用全文查询

  • 使用 JP-QL(我们将其转换为原生后端查询)

  • 传递原生后端查询并将其绑定到实体

参考文档详细介绍了各种选项。

使用 MongoDB 原生查询时,我收到 com.mongodb.util.JSONParseException

您可能没有使用 JSON 的严格模式。特别是,在您的属性周围使用引号。

// not good
String query = "db.Book.find({ author: 'smith' })";

// good
String query = "db.Book.find({ 'author': 'smith' })";

在 WildFly 上使用 Hibernate OGM 时,我收到 JndiException。出了什么问题?

如果您看到 JndiException 说是“无法查找 JNDI 名称 [---PlaceHolderDSForOGM---]”,那么您的应用程序可能无法访问 Hibernate OGM 的应用程序服务器模块。

要更改此设置,请将以下行添加到您的存档的 META-INF/MANIFEST.MF 文件中(将其调整为匹配您选择的数据存储)

Dependencies: org.hibernate.ogm services, org.hibernate.ogm.mongodb services

或者,您可以通过描述符 jboss-deployment-structure.xml 来配置此设置。查看参考指南以了解更多信息。

为什么我收到 java.lang.NoClassDefFoundError: org/hibernate/search/batchindexing/spi/MassIndexerFactory

这意味着您需要在类路径中包含 Hibernate Search。您可以使用以下坐标通过 maven 添加它

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-search-orm</artifactId>
</dependency>

您可以按照文档的入门章节中所述的 BOM 来包含正确的版本。

Hibernate Search 是 OGM 中的一个可选依赖项,如果您想要使用它,则需要包含它

  • 索引实体并运行全文查询;

  • 在没有特定语言查询解析器(如 Redis 或 Cassandra)的数据存储上运行 HQL 查询。

Hibernate OGM 的开发人员

在开发新的方言时如何跳过一些测试?

例如,要跳过与关联相关的(来自核心套件)所有测试,请将此配置添加到 Maven Surefire 插件中

<excludes>
    <exclude>**/associations/**/*Test.java</exclude>
</excludes>

因此,插件配置可能如下所示

pom.xml
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <excludes>
                    <exclude>**/associations/**/*Test.java</exclude>
                </excludes>
                <forkMode>once</forkMode>
            </configuration>
        </plugin>
    </plugins>
</build>
返回顶部