Hibernate OGM

FAQ

Hibernate OGM is not maintained anymore.

Design for Hibernate OGM

Is JPA a good fit for NoSQL?

That’s the million dollars question but in essence, yes we think it is a good fit. Here is quickly a few key reasons why JPA makes sense.

Benefits of the abstraction level

JPA abstracts persistence at the object level, leaving room for a lot of tricks and optimizations. To name a few, think about declarative data / schema migration, declarative denormalization, polyglot persistence. Polyglot persistence is particularly interesting: storing data in several datastores and use the best one for a specific read job.

Of course if your dataset is by nature non domain model centric, then Hibernate OGM is not for you.

Things just fit

While we were skeptic initially, most of the logical model of JPA fit. For example, an @Embeddable object or @ElementCollection nicely fit the document datastore approach of nesting related objects.

We work hard in Hibernate OGM to use the most natural mapping for a given data pattern and we offer you the ability to override that if needed.

Known semantic and APIs

For better or worse, JPA is known to Java developers. They are familiar with its API and semantic. That’s a huge win compared to learning a specific lower level API or worse some pseudo-ORM level API. And we support both HQL and native backend queries!

Late backend choice

Choosing an NoSQL engine is not trivial. Having the freedom to switch backends without having to rewrite all of your data layer is certainly something to appreciate.

Do you support both relational and NoSQL databases?

Yes. You can start Hibernate ORM and Hibernate OGM in the same application. You can even start several Hibernate OGM instances in the same application. Just make sure that you do not share the same entities between persistence units and that there are no associations between two entities handled by different persistence unit.

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

However, you cannot put the same entities (or entities linked with associations) in both the relational and the NoSQL store. Or at least, Hibernate OGM does not do that for you yet. That is something we want to explore in the future.

Using Hibernate OGM

How does Hibernate OGM handle transactions?

Like Hibernate ORM, Hibernate OGM is orthogonal and agnostic to transactions, but integrates the flush event to them when possible.

Make sure to demarcate your transaction either via your application container or via the Hibernate OGM transaction demarcation methods. The reference documentation details how to set up Hibernate OGM in various transaction environments.

Note that even if your datastore does not support transactions, we recommend you use transaction demarcations with Hibernate OGM to trigger the flush operation transparently (on commit). But do not consider rollback as a possibility, this won’t work.

How does Hibernate OGM deal with failures upon transaction commit?

If the backend is transactional (Infinispan, Neo4j), the transaction can be rolled back upon failures. The data store will be in the same state as before, just as you know it from relation databases.

For non-transactional backends (e.g. MongoDB, CouchDB) some changes may already have been applied to the datastore if a failure occurs in the middle of a flush cycle. For such cases, Hibernate OGM provides an error handling and compensation API. This allows you to decide what to do upon failures during a flush (abort, continue) and gives you all the operations applied so far if a "rollback" is triggered.

Check out the reference guide for the details. Note that this API is currently under development; If you have any ideas or requirements around it, please let us know and get in touch!

In Neo4j, I get a org.neo4j.graphdb.NotInTransactionException

Neo4j does require to run all operations within a transaction, even read-only operations. Make sure you demarcate your transactions either explicitly or via a container like Java EE or Spring.

Using MongoDB, I get a java.lang.NoSuchFieldError: ERRORS_IGNORED exception

You are using MongoDB driver 3.x with Hibernate OGM 4.2. Hibernate OGM uses the MongoDB driver 2.13 at this stage. You shouldn’t see any feature loss and you can use this combination to access MongoDB 3 databases - I know that’s confusing.

We plan to upgrade to MongoDB 3 in the near future, we have identified bugs that are being tackled by the Mongo team.

My changes are not applied to the backend, where is the bug?

Most likely, you forgot to demarcate the transactions or manually call flush().

Even if your datastore does not support transactions, we recommend you use transaction demarcations with Hibernate OGM to trigger the flush operation transparently (on commit). But do not consider rollback as a possibility, this won’t work.

How can I query?

There are three main methods:

  • using Hibernate Search as indexing engine and use full-text queries

  • using JP-QL (we convert it into a native backend query)

  • pass a native backend query and bind it to the entity

The reference documentation details the various options.

When using MongoDB native queries, I get a com.mongodb.util.JSONParseException

It’s probable that you are not using JSON’s strict mode. In particular, use quotes around your attributes.

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

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

When using Hibernate OGM on top of WildFly, I’m getting a JndiException. What’s wrong?

In case you’re are seeing a JndiException saying "Unable to lookup JNDI name [---PlaceHolderDSForOGM---]", your application likely cannot access the application server module(s) of Hibernate OGM.

To change this, add the following line to the META-INF/MANIFEST.MF file of your archive (adapt it to match your chosen datastore):

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

Alternatively, you can configure this via the descriptor jboss-deployment-structure.xml. See the reference guide to learn more.

Why do I get a java.lang.NoClassDefFoundError: org/hibernate/search/batchindexing/spi/MassIndexerFactory?

This means that you need Hibernate Search on the classpath. You can add it via maven using the following coordinates:

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

You can include the right version using the BOM as describe in the getting started chapter of the documentation.

Hibernate Search is an optional dependency in OGM, you need to include it if you want to:

  • index entities and run full-text queries;

  • run HQL queries on datastores without a specific language query parser like Redis or Cassandra.

Developers of Hibernate OGM

How to skip some tests while in the development of a new Dialect?

To skip all tests (from the core suite) for example related to associations, add this configuration to the Maven Surefire plugin:

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

So the plugin configuration can look like:

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>
Back to top