Hibernate.orgCommunity Documentation

Hibernate OGM

Hibernate Object/Grid Mapper

Reference Guide

3.0.0.Alpha2


Preface
1. Goals
2. What we have today
3. Use cases
1. How to get help and contribute on Hibernate OGM
1.1. How to get help
1.2. How to contribute
1.2.1. how to build Hibernate OGM
1.2.2. How to contribute code effectively
2. Getting started with Hibernate OGM
3. Architecture
3.1. General architecture
3.2. How is data persisted
3.3. How is data queried
4. Configure and start Hibernate OGM
4.1. Bootstrapping Hibernate OGM
4.1.1. Using JPA
4.1.2. Using Hibernate Core native APIs
4.2. Environments
4.2.1. In a Java EE container
4.2.2. In a standalone JTA environment
4.2.3. Without JTA
4.3. Configuration options
4.4. Configuring Infinispan
4.5. Configuring Hibernate Search
5. Map your entities
5.1. Supported entity mapping
5.2. Supported Types
5.2.1. Types mapped as native Java Types
5.2.2. Types mapped as Strings
5.3. Supported association mapping
6. Query your entities
7. Infinispan

Hibernate Object/Grid Mapper (OGM) is a persistence engine providing Java Persistence (JPA) support for NoSQL storage solutions. It reuses Hibernate Core's object life cycle management and (de)hydration engine but persists entities into a key/value store instead of a relational database. It reuses the Java Persistence Query Language (JP-QL) as an interface to querying stored data.

Hibernate OGM is developed specifically with Infinispan - an open source distributed in-memory key/value store - in mind, but the longer term goal is to abstract Hibernate OGM to work with any NoSQL store, not just key/value stores, similar to the way Hibernate Core works with any SQL-based relational database, regardless of specific SQL dialect.

If you wish to help with this abstraction effort or with Hibernate OGM in general, please refer to Chapter 1, How to get help and contribute on Hibernate OGM.

Hibernate OGM is released under the LGPL open source license.

Warning

This documentation and this project are work in progress. Please give us feedback on

  • what you like

  • what you don't like

  • what is confusing

Check Section 1.2, “How to contribute” on how to contact us.

Hibernate OGM tries to achieve a few goals:

NoSQL can be very disconcerting as it is composed of many disparate solutions with different benefits and drawbacks. Speaking only of the main ones, NoSQL is at least categorized in four families:

Each have different benefits and drawbacks and one solution might fit a use case better than an other. However access patterns and APIs are different from one product to the others.

Hibernate OGM is not expected to the the Rosetta stone used to interact with all NoSQL solution in all use cases. But for people modeling their data as a domain model, it provides distinctive advantages over raw APIs and has the benefit of providing an API and semantic quite known to Java developers. Reusing the same programmatic model and trying different (No)SQL engines will hopefully help people to explore alternative datastores.

Hibernate OGM also aims at helping people scale traditional relational databases by providing a NoSQL front-end and keeping the same JPA APIs and domain model.

Hibernate OGM is a young project. The code, the direction and the documentation are all in flux and being built by the community. Come and help us shape it!

First of all, make sure to read this reference documentation. This is the most comprehensive formal source of information. Of course, it is not perfect, feel free to come and ask for help, comment or propose improvements in our Hibernate OGM forum.

You can also

  • open bug reports in JIRA

  • propose improvements on the development mailing list

  • and join us on IRC to discuss developments and improvements (#hibernate-dev on freenode.net ; you need to be registered on freenode, the room does not accept "anonymous" persons).

Welcome!

There are many ways to contribute:

  • report bugs in JIRA

  • give feedback in the forum, IRC or the development mailing list

  • improve the documentation

  • fix bug or contribute new features

Hibernate OGM's code is available on GitHub at https://github.com/hibernate/hibernate-ogm.

If you are familiar with JPA, you are almost good to go :) We will nevertheless walk you through the first few steps of persisting and retrieving an entity using Hibernate OGM.

Before we can start, make sure you have the following tools configured:

Hibernate OGM is published in the JBoss hosted Maven repositories. Adjust your ~/.m2/settings.xml file according to the guidelines found here.

Add org.hibernate.ogm:hibernate-ogm-core:3.0.0-SNAPSHOT to your project dependencies.


<dependency>
  <groupId>org.hibernate.ogm</groupId>
  <artifactId>hibernate-ogm-core</artifactId>
  <version>3.0.0-SNAPSHOT</version>
</dependency>

Transitively, Hibernate OGM depends on JPA 2.0: we will use these APIs in this tutorial.

Let's now map our first Hibernate OGM entity.

@Entity

public class Dog {
   @Id @GeneratedValue(strategy = GenerationType.TABLE, generator = "dog")
   @TableGenerator(
      name = "dog",
      table = "sequences",
      pkColumnName = "key",
      pkColumnValue = "dog",
      valueColumnName = "seed"
   )
   public Long getId() { return id; }
   public void setId(Long id) { this.id = id; }
   private Long id;
   public String getName() { return name; }
   public void setName(String name) { this.name = name; }
   private String name;
   @ManyToOne
   public Breed getBreed() { return breed; }
   public void setBreed(Breed breed) { this.breed = breed; }
   private Breed breed;
}
@Entity
public class Breed {
   @Id @GeneratedValue(generator = "uuid")
   @GenericGenerator(name="uuid", strategy="uuid2")
   public String getId() { return id; }
   public void setId(String id) { this.id = id; }
   private String id;
   public String getName() { return name; }
   public void setName(String name) { this.name = name; }
   private String name;
}

I lied to you, we have already mapped two entities! If you are familiar with JPA, you can see that there is nothing specific to Hibernate OGM in our mapping.

In this tutorial, we will use JBoss Transactions for our JTA transaction manager. The final list of dependencies should look like this:


<dependencies>
    <dependency>
        <groupId>org.hibernate.ogm</groupId>
        <artifactId>hibernate-ogm-core</artifactId>
        <version>3.0.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.12.1.GA</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.6.1</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.6.1</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.jbossts</groupId>
        <artifactId>jbossjta</artifactId>
        <version>4.15.0.Final</version>
    </dependency>
</dependencies>

Next we need to define the persistence unit. Create a META-INF/persistence.xml file


<?xml version="1.0"?>
<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="org.hibernate.ogm.tutorial.jpa" transaction-type="JTA">
        <!-- Use Hibernate OGM provider: configuration will be transparent -->
        <provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>
        <properties>
            <property name="hibernate.transaction.manager_lookup_class"
                      value="org.hibernate.transaction.JBossTSStandaloneTransactionManagerLookup" />
        </properties>
    </persistence-unit>
</persistence>

Let's now persist a set of entities and retrieve them.

//accessing JBoss's Transaction can be done differently but this one works nicely

TransactionManager tm = new JBossTSStandaloneTransactionManagerLookup()
   .getTransactionManager( null );
//build the EntityManagerFactory as you would build in in Hibernate Core
EntityManagerFactory emf = Persistence.createEntityManagerFactory(
    "org.hibernate.ogm.tutorial.jpa");
final Logger logger = LoggerFactory.getLogger(DogBreedRunner.class);
[...]
//Persist entities the way you are used to in plain JPA
tm.begin();
EntityManager em = emf.createEntityManager();
Breed collie = new Breed();
collie.setName("Collie");
em.persist(collie);
Dog dina = new Dog();
dina.setName("Dina");
dina.setBreed(collie);
em.persist(dina);
Long dinaId = dina.getId();
em.flush();
em.close();
tm.commit();
[...]
//Retrieve your entities the way you are used to in plain JPA
tm.begin();
em = emf.createEntityManager();
dina = em.find(Dog.class, dinaId);
logger.debug(dina.getName());
logger.debug(dina.getBreed().getName());
em.flush();
em.close();
tm.commit();
[...]
emf.close();;

TODO: explain how to run a second Infinispan node to show how data does outlive the EntityManagerFactory lifecycle.

What have we seen?

  • Hibernate OGM is a JPA implementation and is used as such both for mapping and in API usage

  • It is configured as a specific JPA provider: org.hibernate.ogm.jpa.HibernateOgmPersistence

Let's explore more in the next chapters.

Note

Note that abstracting Infinispan is a work in progress and should be an easy enough task as tuples are represented as Maps.

In this chapter we will will explore:

  • the general architecture

  • how the data is persisted in the data grid

  • how we support JP-QL queries

Let's start with the general architecture.

Hibernate OGM is really made possible by the reuse of a few key components:

Hibernate OGM reuses as much as possible from the Hibernate Core infrastructure. There is no need to rewrite an entirely new JPA engine. The Persisters and the Loaders (two interfaces used by Hibernate Core) have been rewritten to persist data using Infinispan instead of JDBC. These implementations are the core of Hibernate OGM. We will see in Section 3.2, “How is data persisted” how the data is structured. Other than that, all the Create/Read/Update/Delete (CRUD) operations are implemented by Hibernate Core.

To implement JP-QL queries, Hibernate OGM converts the JP-QL string into an Hibernate Search query. This query is then executed against the Lucene indexes stored in Infinispan and return the list of matching entities. Hibernate Search also listens to entity changes thanks to Hibernate Core events and update the Lucene indexes accordingly.

Note

Complex JP-QL queries esp with collection joins will require capabilities beyond Hibernate Search's current approach. We have several ideas in mind to address this problem.

Hibernate OGM best works in a JTA environment. The easiest solution is to deploy it on a Java EE container. Alternatively, you can use a standalone JTA TransactionManager. We do explain how to in Section 4.2.2, “In a standalone JTA environment”.

Let's now see how and in which structure data is persisted in the NoSQL data store.

Hibernate OGM tries to reuse as much as possible the relational model concepts (at least when they are practical and make sense in OGM's case). For very good reasons, the relational model brought peace in the database landscape over 30 years ago. In particular, Hibernate OGM inherits the following philosophy traits:

If the application data model is too tightly coupled with your persistent data model a few issues arise including:

Entities are stored as tuples of values by Hibernate OGM. More specifically, each entity is represented by a Map<String,Object> conceptually where the key represents the column name (often the property name but not always) and the value represents the column value as a basic type. We favor basic types over complex ones to increase portability (across platforms and across type / class schema evolution over time). For example a URL object is store as its String representation.

The key where a given entity instance is stored is composed of:

This gives us several interesting properties. An entity is addressable by a single lookup. All entity types can leave in the same key name space as they are entirely isolated.

Associations are also stored as tuple as well or more specifically as a set of tuples. Hibernate OGM stores the information necessary to navigate from an entity to its associations. This is a departure from the pure relational model but it ensures that association data is reachable via key lookups based on the information contained in the entity tuple we want to navigate from. Note that this leads to some level of duplication as information has to be stored for both sides of the association.

The key in which association data are stored is composed of:

Using this approach, we favor fast read and (slightly) slower writes.

Note that this approach has benefits and drawbacks:

Some identifiers require to store a seed in the datastore (think about sequences for examples). The seed is stored in the value whose key is composed of:

Infinispan is a key/value store which means that per se it has no notion of schema. Likewise, the tuple stored by Hibernate OGM is not tied to a particular schema: the tuple is represented by a Map, not a typed Map specific to a given entity type. Nevertheless, JPA does describe a schema thanks to:

While tied to the application, it offers some robustness and explicit understanding when the schema is changed as the schema is right in front of the developers' eyes. This is an intermediary model between the strictly typed relational model and the totally schema-less approach pushed by some NoSQL families.

Hibernate OGM favors ease of use and convention over configuration. This makes its configuration quite simple by default.

Hibernate OGM can be used via the Hibernate native APIs (Session) or via the JPA APIs (EntityManager). Depending of your choice, the bootstrapping strategy is slightly different.

The good news is that if you use JPA as your primary API, the configuration is extremely simple. Hibernate OGM is seen as a persistence provider which you need to configure in your persistence.xml. That's it! The provider name is org.hibernate.ogm.jpa.HibernateOgmPersistence.


There are a couple of things to notice:

It is possible to configure how to connect to Infinispan, see ???.

From there, simply bootstrap JPA the way you are used to with Hibernate Core:

  • via Persistence.createEntityManagerFactory

  • by injecting the EntityManager / EntityManagerFactory in a Java EE container

  • by using your favorite injection framework (CDI - Weld, Spring, Guice)

If you want to bootstrap Hibernate OGM using the native Hibernate APIs, you will have some more work to do.

You need to configure a few of the internals of Hibernate OGM namely:


There are a couple of things to notice:

It is possible to configure how to connect to Infinispan, see ???.

Hibernate OGM runs in various environments, pretty much what you are used to with Hibernate Core. There are however environments where it works better and has been more thoroughly tested.

You don't have to do much in this case. You need three specific settings:

If you use JPA, simply set the transaction-type to JTA and the transaction factory will be set for you.

If you use Hibernate Core native APIs only, then set hibernate.transaction.factory_class to either:

Set the transaction manager lookup strategy to the right Java EE container. The property is hibernate.transaction.manager_lookup_class and must contain the fully qualified class name of the lookup implementation. The list of available values are listed in Hibernate Core's configuration section. For example, in JBoss AS, use org.hibernate.transaction.JBossTransactionManagerLookup.

In your persistence.xml, you also need to define an existing datasource. It is not needed by Hibernate OGM and won't be used but the JPA specification mandates this setting.


java:DefaultDS will work for out of the box JBoss AS deployments.

There is a set of common misconceptions in the Java community about JTA

None of that is true of course, let me show you how to use JBoss Transaction in a standalone environment with Hibernate OGM.

In Hibernate OGM, make sure to set the following properties:

On the JBoss Transaction side, add JBoss Transaction in your classpath, if you use maven, it should look like this:


The next step is you get access to the transaction manager. The easiest solution is to do as followed

//accessing JBoss's Transaction can be done differently but this one works nicely

TransactionManager transactionManager = new JBossTSStandaloneTransactionManagerLookup()
   .getTransactionManager( null );

Then use the standard JTA APIs to demarcate your transaction and you are done!


That was not too hard, was it? Note that application frameworks like Seam or Spring Framework should be able to initialize the transaction manager and call it to demarcate transactions for you. Check their respective documentation.

Talk about supported approaches (properties, embedded objects, inheritance

Talk about associations

Talk about identifier recommendations

This section is a work in progress, if you find something that does not work as expected, let us know and we will update it (and fix the problem of course).

Pretty much all entity related constructs should work out of the box in Hibernate OGM. @Entity, @Table, @Column, @Enumarated, @Temporal, @Cacheable and the like will work as expected. If you want an example, check out Chapter 2, Getting started with Hibernate OGM or the documentation of Hibernate Core. Let's concentrate of the features that differ or are simply not supported by Hibernate OGM.

The various inheritance strategies are not supported by Hibernate OGM, only the table per concrete class strategy is used. This is not so much a limitation but rather an acknowledgment of the dynamic nature of NoSQL schemas. If you feel the need to support other strategies, let us know (see Section 1.2, “How to contribute”). Simply do not use @Inheritance nor @DiscriminatorColumn.

Secondary tables are not supported by Hibernate OGM at the moment. If you have needs for this feature, let us know (see Section 1.2, “How to contribute”).

All SQL related constructs as well as HQL centered mapping are not supported in Hibernate OGM. Here is a list of feature that will not work:

  • Named queries

  • Native queries

Finally, identifier generators as not all supported at the moment. All memory-based generators will work as expected. JPA's TABLE generator works as expected. JPA's IDENTITY, SEQUENCE and AUTO are planned. If you need support for additional generators, let us know (see Section 1.2, “How to contribute”). We recommend you use a UUID based generator as this type of generator allows maximum scalability to the underlying data grid as no cluster-wide counter is necessary.

All association types are supported (@OneToOne, @OneToMany, @ManyToOne, @ManyToMany). Likewise, all collection types are supported (Set, Map, List). The way Hibernate OGM stores association information is however quite different than the traditional RDBMS representation. Check Section 3.2, “How is data persisted” for more information.

Keep in mind that collections with many entries won't perform very well in Hibernate OGM (at least today) as all of the association navigation for a given entity is stored in a single key. If your collection is made of 1 million elements, Hibernate OGM stores 1 million tuples in the association key.

Hibernate Search works perfectly well with Hibernate OGM. You can wrap an Hibernate OGM Session or EntityManager with a FullTextSession or FullTextEntityManager like you would do with Hibernate Core (via the static methods hosted on Search).

The same configurations options available in Hibernate Search when using Hibernate Core are also relevant.

Of course, make sure to add the necessary Hibernate Search mapping annotations on your domain model to properly index your entities.

TODO: talk about Hibernate Search queries.

Talk about the JP-QL parser when we have that integrated.

Short description of what Infinispan is

Describe the various deployment options for Hibernate OGM: how to deploy several nodes

Explain how to monitor it

Write a how to fix with the most common errors (IPv6 etc).