Red Hat

In Relation To Davide D'Alto

In Relation To Davide D'Alto

Hibernate OGM 5.1 Beta3 and 5.0.4 are out

Posted by    |       |    Tagged as Hibernate OGM Releases

Hello everybody, holidays are over and we decided to start back with a small release.

Hibernate OGM 5.1 Beta3 and a new 5.0 maintainance releases are now available.

In these releases we fixed some issues around sequence generation and queries on entities using the single table per class inheritance strategy. An update is highly recommended.

Hibernate OGM 5.0.4.Final is backward compatible with 5.0.3.Final. If you need to upgrade from a version before 5.0, you can find help on the migration notes.

All the details about these releases are on the 5.0.4.Final changelog, the 5.1.0.Beta2 changelog and the 5.1.0.Beta3 changelog.

What happened to 5.1 Beta2?

Think of it as the crazy uncle nobody wants to talk about, you should check 5.1 Beta3 instead.

Where can I get them?

5.0.4.Final

You can get the required core library using the following Maven coordinates:

  • org.hibernate.ogm:hibernate-ogm-core:5.0.4.Final

and these are the backends currently available:

  • Cassandra: org.hibernate.ogm:hibernate-ogm-cassandra:5.0.4.Final

  • CouchDB: org.hibernate.ogm:hibernate-ogm-couchdb:5.0.4.Final

  • Infinispan: org.hibernate.ogm:hibernate-ogm-infinispan:5.0.4.Final

  • Ehcache: org.hibernate.ogm:hibernate-ogm-ehcache:5.0.4.Final

  • MongoDB: org.hibernate.ogm:hibernate-ogm-mongodb:5.0.4.Final

  • Neo4j: org.hibernate.ogm:hibernate-ogm-neo4j:5.0.4.Final

  • Redis: org.hibernate.ogm:hibernate-ogm-redis:5.0.4.Final

Alternatively, you can download archives containing all the binaries, source code and documentation from Sourceforge.

5.1.0.Beta3

You can get the required core library using the following Maven coordinates:

  • org.hibernate.ogm:hibernate-ogm-core:5.1.0.Beta3

and these are the backends currently available for 5.1.0.Beta3:

  • Cassandra: org.hibernate.ogm:hibernate-ogm-cassandra:5.1.0.Beta3

  • CouchDB: org.hibernate.ogm:hibernate-ogm-couchdb:5.1.0.Beta3

  • Infinispan

    • Embedded: org.hibernate.ogm:hibernate-ogm-infinispan:5.1.0.Beta3

    • Remote: org.hibernate.ogm:hibernate-ogm-infinispan-remote:5.1.0.Beta3

  • Ehcache: org.hibernate.ogm:hibernate-ogm-ehcache:5.1.0.Beta3

  • MongoDB: org.hibernate.ogm:hibernate-ogm-mongodb:5.1.0.Beta3

  • Neo4j: org.hibernate.ogm:hibernate-ogm-neo4j:5.1.0.Beta3

  • Redis: org.hibernate.ogm:hibernate-ogm-redis:5.1.0.Beta3

Alternatively, you can download archives containing all the binaries, source code and documentation from Sourceforge.

What’s next?

We are getting ready for the first 5.1 candidate release.

How can I get in touch?

You can find us through the following channels:

We are looking forward to hear your feedback!

The first hibernate OGM 5.1 Alpha and 5.0.2 Final

Posted by    |       |    Tagged as Hibernate OGM Releases

Good news!

We released Hibernate OGM 5.1 Alpha1 and 5.0.2 Final!

What’s new?

Hibernate OGM 5.0.2.Final

Hibernate OGM 5.0.2.Final now supports MongoDB 3.2 and it’s still backward compatible with Hibernate OGM 5.0.1.Final.

If you need to upgrade from a version before 5.0, you can find help on the migration notes.

The 5.0.2.Final changelog contains all the details about the changes in this release.

Hibernate OGM 5.1.0.Alpha1

Hibernate OGM 5.1.0.Alpha1 brings support for Neo4j in remote mode. The user will have the option to choose between the new Bolt protocol or the more familiar HTTP interface.

We also started to re-work the way Hibernate OGM groups operations before running them; this reduce the number of calls and commands to execute on the datastore, leading to better performance.

The 5.1.0.Alpha1 changelog contains all the details about the changes in this release.

How can I try the remote Neo4j dialect?

You can test Hibernate OGM support for Neo4j adding the following dependency to your project:

<dependency>
    <groupId>org.hibernate.ogm</groupId>
    <artifactId>hibernate-ogm-neo4j</artifactId>
    <version>5.1.0.Alpha1</version>
</dependency>

and setting the following properties:

# Required
hibernate.ogm.datastore.provider = neo4j_bolt # or neo4j_http

# Optional
hibernate.ogm.datastore.host = myproject.example.com:8989
hibernate.ogm.datastore.username = example_username
hibernate.ogm.datastore.password = example_password

You can get more information about this integration and how to configure it in the Neo4j section of the documentation.

Where can I get them?

5.0.2.Final

You can get the required core library using the following Maven coordinates:

  • org.hibernate.ogm:hibernate-ogm-core:5.0.2.Final

and these are the backends currently available:

  • Cassandra: org.hibernate.ogm:hibernate-ogm-cassandra:5.0.2.Final

  • CouchDB: org.hibernate.ogm:hibernate-ogm-couchdb:5.0.2.Final

  • Infinispan: org.hibernate.ogm:hibernate-ogm-infinispan:5.0.2.Final

  • Ehcache: org.hibernate.ogm:hibernate-ogm-ehcache:5.0.2.Final

  • MongoDB: org.hibernate.ogm:hibernate-ogm-mongodb:5.0.2.Final

  • Neo4j: org.hibernate.ogm:hibernate-ogm-neo4j:5.0.2.Final

  • Redis: org.hibernate.ogm:hibernate-ogm-redis:5.0.2.Final

Alternatively, you can download archives containing all the binaries, source code and documentation from Sourceforge.

5.1.0.Alpha1

You can get the required core library using the following Maven coordinates:

  • org.hibernate.ogm:hibernate-ogm-core:5.1.0.Alpha1

and these are the backends currently available for 5.1.0.Alpha1:

  • Cassandra: org.hibernate.ogm:hibernate-ogm-cassandra:5.1.0.Alpha1

  • CouchDB: org.hibernate.ogm:hibernate-ogm-couchdb:5.1.0.Alpha1

  • Infinispan: org.hibernate.ogm:hibernate-ogm-infinispan:5.1.0.Alpha1

  • Ehcache: org.hibernate.ogm:hibernate-ogm-ehcache:5.1.0.Alpha1

  • MongoDB: org.hibernate.ogm:hibernate-ogm-mongodb:5.1.0.Alpha1

  • Neo4j: org.hibernate.ogm:hibernate-ogm-neo4j:5.1.0.Alpha1

  • Redis: org.hibernate.ogm:hibernate-ogm-redis:5.1.0.Alpha1

Alternatively, you can download archives containing all the binaries, source code and documentation from Sourceforge.

What’s next?

The major addition in the next release will be the integration with Infinispan remote via the HotRod protocol.

How can I get in touch?

You can find us through the following channels:

We are looking forward to hear your feedback!

On the way to the remote Neo4j server integration

Posted by    |       |    Tagged as Hibernate OGM

Hibernate OGM has been able for a while to work with an embedded Neo4j instance. In the next release, we want to add the ability to connect to a remote Neo4j server.

A new binary protocol is available since Neo4j 3 to connect to a remote server: Bolt.

In addition to Bolt, Neo4j comes also with a RESTful API and we are wondering if we should add an option to switch between the two approaches.

To sum up, given the option, would you choose the RESTful API instead of Bolt to connect to Neo4j using Hibernate OGM?

This is the right time to let us know what you think.

First Hibernate OGM 5 maintenance release

Posted by    |       |    Tagged as Hibernate OGM Releases

We released Hibernate OGM 5.0.1.Final!

What’s new?

Here some of the most interesting bug fixes and improvements in this release:

  • OGM-818 - Autodetection support for @Entity annontated classes will now work

  • OGM-356 - Object comparison in JPQL queries for MongoDB and Neo4j

  • OGM-1065 - You can now use Hibernate OGM with Cassandra 3 (Thanks joexner!)

You can find all the details in the changelog.

This release is backward compatible with Hibernate OGM 5.0.0.Final but if you need to upgrade from a previous version, you can find help on the migration notes.

Where can I get it?

You can get Hibernate OGM 5.0.1.Final core via Maven using the following coordinates:

  • org.hibernate.ogm:hibernate-ogm-core:5.0.1.Final

and these are the back-ends currently available:

  • Cassandra: org.hibernate.ogm:hibernate-ogm-cassandra:5.0.1.Final

  • CouchDB: org.hibernate.ogm:hibernate-ogm-couchdb:5.0.1.Final

  • Infinispan: org.hibernate.ogm:hibernate-ogm-infinispan:5.0.1.Final

  • Ehcache: org.hibernate.ogm:hibernate-ogm-ehcache:5.0.1.Final

  • MongoDB: org.hibernate.ogm:hibernate-ogm-mongodb:5.0.1.Final

  • Neo4j: org.hibernate.ogm:hibernate-ogm-neo4j:5.0.1.Final

  • Redis: org.hibernate.ogm:hibernate-ogm-redis:5.0.1.Final

Alternatively, you can download archives containing all the binaries, source code and documentation from SourceForge.

How can I get in touch?

You can find us through the following channels:

We are looking forward to hear your feedback!

Hibernate OGM 5 is out!

Posted by    |       |    Tagged as Hibernate OGM Releases

Hibernate OGM 5.0.0.Final is finally here!

What’s new?

Compared to the 4.2.Final, this version includes:

There are also several bug fixes and you can find all the details in the changelog.

A nice Getting started guide is available on our website for people who want to start playing with it. A more in depth explanation of all the details around Hibernate OGM is in the reference documentation.

If you need to upgrade from a previous version, you can find help on the migration notes.

What’s coming next?

Now that Hibernate OGM 5 is out, we can focus on working on some new integrations like Neo4j remote and Hot Rod.

You can also have a look at the roadmap for up-to-date news about what’s coming next.

If you think that something is missing or if you have some opinion about what we should include, please, let us hear your voice.

Where can I get it?

You can get Hibernate OGM 5.0.0.Final core via Maven using the following coordinates:

  • org.hibernate.ogm:hibernate-ogm-core:5.0.0.Final

and these are the back-ends currently available:

  • Cassandra: org.hibernate.ogm:hibernate-ogm-cassandra:5.0.0.Final

  • CouchDB: org.hibernate.ogm:hibernate-ogm-couchdb:5.0.0.Final

  • Infinispan: org.hibernate.ogm:hibernate-ogm-infinispan:5.0.0.Final

  • Ehcache: org.hibernate.ogm:hibernate-ogm-ehcache:5.0.0.Final

  • MongoDB: org.hibernate.ogm:hibernate-ogm-mongodb:5.0.0.Final

  • Neo4j: org.hibernate.ogm:hibernate-ogm-neo4j:5.0.0.Final

  • Redis: org.hibernate.ogm:hibernate-ogm-redis:5.0.0.Final

Alternatively, you can download archives containing all the binaries, source code and documentation from SourceForge.

How can I get in touch?

You can find us through the following channels:

We are looking forward to hear your feedback!

We are getting closer and closer to the final release of Hibernate OGM 5.

This release includes support for Redis Cluster and a new dialect to store data within Redis hashes; java.util.UUID are now using the native uuid type in Apache Cassandra; more queries are now supported using the MongoDB CLI syntax.

This release is also aligned to the Hibernate 5 family and it will work with Hibernate ORM 5, Hibernate Search 5.5 and the latest WildFly 10. Check the previous post for more details about it.

The migration notes contains more information about migrating from earlier versions of Hibernate OGM to 5.x.

Have a look at the change log for a list of everything included in this release.

Redis Cluster support

Enabling the support for Redis Cluster is a matter of setting the following property to true:

hibernate.ogm.redis.cluster = true

When this property is enabled, data will be stored across Redis cluster nodes according to the Redis key distribution model on the hash slot of the key of each entity.

Check the documentation for more details about the configuration options for Redis in Hibernate OGM.

Redis hash mapping

When using this mapping, data is stored using key-values pairs using Redis hashes. The benefit of this approach is that it allows partial updates.

You can enable this dialect setting the following property:

hibernate.ogm.datastore.grid_dialect = org.hibernate.ogm.datastore.redis.RedisHashDialect

This will map the following entity:

@Entity
public class News {

    @Id
    private String id;

    @Version
    @Column(name="version")
    private int version;

    private String title;

    private String description;

    //getters, setters ...
}

with the following properties:

version     = 1
title       = On the merits of NoSQL
description = This paper discuss why NoSQL will save the world for good

A huge thanks to community member Mark Paluch, responsible for both these great improvements in the Redis area. Note that these features are both experimental for the time being.

Additional MongoDB native CLI queries support

Thanks to the contribution of Thorsten Möller, Hibernate OGM now supports more type of queries using the MongoDB CLI syntax: findOne, findAndModify, insert, remove and update.

Here an example showing how you can use them:

OgmSession session = ...

String nativeQuery = "db.OscarWilde.findAndModify({"
        + "'query': {'author': 'oscarwilde'}, "
        + "'update': { '$set': { 'author': 'Oscar Wilder' } }, "
        + "'new': true "
        + "})";

Query query = session.createNativeQuery( nativeQuery ).addEntity( OscarWilde.class );
List<OscarWilde> result = query.list();

You can find more details in the documentation about experimental support of native MongoDB queries.

What’s coming next?

We are working on the Neo4j remote dialect and we are focused on releasing a stable version of Hibernate OGM 5.

Where can I get it?

You can get Hibernate OGM 5.0.0.CR1 via Maven etc. using the following coordinates:

  • org.hibernate.ogm:hibernate-ogm-core:5.0.0.CR1 for the Hibernate OGM core module

  • org.hibernate.ogm:hibernate-ogm-<%BACKEND%>:5.0.0.CR1 for the NoSQL backend you want to use, with _<%BACKEND%> being one of "mongodb", "redis", "neo4j", etc.

Alternatively, you can download archives containing all the binaries, source code and documentation from SourceForge.

How can I get in touch?

You can get in touch through the following channels:

We are looking forward to hear your feedback!

It’s 3 days from Christmas and as a present we decided to release the first Beta of Hibernate OGM 5!

The major news in this release is the mapping support for Cassandra 2.2 new data types, proper handling of the @Lob annotation, post-load event support and Infinispan 8.

This release also continue the process of aligning Hibernate OGM to the Hibernate 5 family. After the passage to Hibernate ORM 5 in the previous release, we updated Hibernate Search to the 5.5 version that also includes the power of Apache Lucene 5.

In the previous release post we described the improvements about storing map-typed properties on MongoDB and Redis. We have now applied the same natural mapping on CouchDB.

Check out the Hibernate OGM migration notes to learn more about migrating from earlier versions of Hibernate OGM to 5.x.

Cassandra 2.2 new data types

  • date for properties mapped using @Temporal(TemporalType.DATE)

  • time for properties mapped using @Temporal(TemporalType.TIME)

  • tinyint for java.lang.Byte

  • smallint for java.lang.Short

PostLoad event support

Thanks to David Williams contribution, the @PostLoad annotation will now work with Hibernate OGM.

If you are not familiar with this annotation, it’s part of the JPA spec and it allows to specify callback methods for the corresponding lifecycle event.

@Entity
public class Zoo {

   @Id
   private Integer id;

   @ElementCollection
   private Set<Animal> animals = new HashSet<Animal>();

   private int nrOfAnimals;

   ...

   @PostLoad
   public void postLoad() {
       nrOfAnimals = animals.size();
   }
}

The postLoad() method will be called after all the eagerly fetched fields of the class Zoo have been loaded from the datastore allowing us to inizialize the value of the attribute nrOfElement.

Note that this code follows the JPA spec and it could be use in the same way with Hibernate ORM or any other JPA compliant project.

How can I add support for a new data store?

I’m glad you ask, community member Mark Paluch contributed to the documentation adding a new section that explains the different components involved in the creation of a new backend: How to build support for a data store

What’s coming next?

The major features we are planning to include in the next release are the support for the Neo4j remote server and an alternative dialect for Redis which persists values right into hash fields.

Where can I get it?

You can retrieve Hibernate OGM 5.0.0.Beta1 via Maven etc. using the following coordinates:

  • org.hibernate.ogm:hibernate-ogm-core:5.0.0.Beta1 for the Hibernate OGM core module

  • org.hibernate.ogm:hibernate-ogm-<%BACKEND%>:5.0.0.Beta1 for the NoSQL backend you want to use, with <%BACKEND%> being one of "mongodb", "redis", "neo4j" etc.

Alternatively, you can download archives containing all the binaries, source code and documentation from SourceForge.

As always, we are looking forward to your feedback. The change log tells in detail what’s in there for you. Get in touch through the following channels:

Hibernate Search 5.5 Final is out

Posted by    |       |    Tagged as Hibernate Search Releases

I’m happy to announce the latest final release of Hibernate Search: Hibernate Search 5.5 Final. We mainly consolidated the features included in the latest candidate release and worked on fixing some bugs.

As a reminder on versions:

Hibernate Search now requires at least Hibernate ORM 5.0.0.Final, and at the time of writing only Infinispan 8.0.1.Final supports real time replication of an Apache Lucene 5.3 index.

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-search-orm</artifactId>
   <version>5.5.0.Final</version>
</dependency>
<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-core</artifactId>
   <version>5.0.1.Final</version>
</dependency>
<dependency>
   <groupId>org.infinispan</groupId>
   <artifactId>infinispan-directory-provider</artifactId>
   <version>8.0.1.Final</version>
</dependency>
<dependency>
   <groupId>org.apache.lucene</groupId>
   <artifactId>lucene-core</artifactId>
   <version>5.3.0</version>
</dependency>

WildFly 10, Lucene 5

Last week, we released Hibernate Search 5.4 Final with the minimal set of changes to make it work with Hibernate ORM 5. This version uses Lucene 5.3; if you haven’t upgraded already, we recommend to start with version 5.4.0.Final, first.

Hibernate Search 5.5 will be included in WildFly 10.

Out of the box indexing of java.time types

Hibernate Search is now able to automatically provide a sensible mapping for java.time.Year, java.time.Duration java.time.Instant, java.time.LocalDate, java.time.LocalTime, java.time.LocalDateTime, java.time.LocalTime, java.time.MonthDay, java.time.OffsetDateTime, java.time.OffsetTime, java.time.Period, java.time.YearMonth, java.time.ZoneDateTime, java.time.ZoneId, java.time.ZoneOffset.

That means that it includes an out of the box FieldBridge for each of these types, and allows transparent indexing and querying of properties of these types. You can of course customize the indexing by providing your own FieldBridge, as usual.

This feature is only available if you are running on a Java 8 runtime, although all other features of Hibernate Search are still backwards compatible with Java 7.

Sorting improvements

Since Apache Lucene 5.0 (and including 5.3 as we currently require) we can provide a significant performance improvement if you let us know in advance which fields you intend to use for sorting.

For this purpose a new annotation org.hibernate.search.annotations.SortableField is available. If you start using this annotation in your projects you’ll benefit from improved performance, but for those who don’t want to update their mapping yet we will fallback to the older strategy.

This subject is discussed in detail in this follow-up post.

Encoding null tokens in your index

When using @Field(indexNullAs=) to encode some marker value in the index, the type of the marker is now required to be of a compatible field type as all other values which are indexed in that same field.

This was problematic for `NumericField`s, the ones optimised for range queries on numbers, as we would previously allow you to encode a string keyword like 'null': this is no longer allowed, you will have to pick a number to be used to represent the null value.

As an example for an "age" property you might want to use:

@Field(indexNullAs = "-1")
Integer nullableAge;

How to get this release

Everything you need is available on Hibernate Search’s web site. Download the full distribution from SourceForge, or get it from Maven Central, and don’t hesitate to reach us in our forums or mailing lists.

Hibernate OGM 4.2 Final is out

Posted by    |       |    Tagged as Hibernate OGM

After several months of hard work, I'm happy to announce the next final release of Hibernate OGM: 4.2.

What's new?

Compared to 4.1 Final, this version includes:

You can find more details for each one of them in our previous posts about release 4.2 Beta1 and 4.2 CR1.

A list of all resolved issues is available in the release notes (you can also find the one for 4.2.CR1 and the one for 4.2.Beta1).

How can I get it?

You can download Hibernate OGM 4.2.0.Final from SourceForge or via Maven, Gradle etc., using the following GAV coordinates:

  • org.hibernate.ogm:hibernate-ogm-core:4.2.0.Final for the Hibernate OGM engine and
  • org.hibernate.ogm:hibernate-ogm-<%DATASTORE%>:4.2.0.Final, depending on the backend you want to use.

I’m new to Hibernate OGM, where should I start?

If you are not familiar with Hibernate OGM, most of what you need is available in our web site. There is a getting started guide and the more complete reference documentation. And last but not least, for any help or feedback, reach us via our forum or via IRC.

What’s next?

We have plenty of ideas: migrate to Hibernate ORM 5, custom types, new datastores, denormalization engine, and more. You can influence what we are going to include in the next release letting us hear your voice with feedback, questions or ideas.

Many thanks to all the people that helped us make this release possible.

NoSQL for Hibernate OGM: Querying for your data

Posted by    |       |    Tagged as Hibernate OGM

Welcome to the second part of the NoSQL with Hibernate OGM 101 tutorial series. In part 1 you have seen how to include Hibernate OGM in your Java project and how simple it is to persist entities and switch between different kind of NoSQL datastores.

Now that your datastore contains some data you will probably want to run some queries on it. Fear not, Hibernate OGM will let you get your data in several different ways:

  • using the Java Persistence Query Langage (JP-QL)
  • using the NoSQL native query language of the datastore of your choice (if it has one)
  • using Hibernate Search queries - primarly full-text queries

All of these alternatives will allow you to run a query on the datastore and get the result as a list of managed entities.

Preparing the test class

We are going to add a new class HikeQueryTest. It will populate the datastore with some information about hikes:

public class HikeQueryTest {

    private static EntityManagerFactory entityManagerFactory;

    @BeforeClass
    public static void setUpEntityManagerFactoryAndPopulateTheDatastore() {
        entityManagerFactory = Persistence.createEntityManagerFactory( "hikePu" );

            EntityManager entityManager = entityManagerFactory.createEntityManager();

            entityManager.getTransaction().begin();

            // create a Person
            Person bob = new Person( "Bob", "McRobb" );

            // and two hikes
            Hike cornwall = new Hike(
                "Visiting Land's End", new Date(), new BigDecimal( "5.5" ),
                new HikeSection( "Penzance", "Mousehole" ),
                new HikeSection( "Mousehole", "St. Levan" ),
                new HikeSection( "St. Levan", "Land's End" )
            );
            Hike isleOfWight = new Hike(
                "Exploring Carisbrooke Castle", new Date(), new BigDecimal( "7.5" ),
                new HikeSection( "Freshwater", "Calbourne" ),
                new HikeSection( "Calbourne", "Carisbrooke Castle" )
            );

            // let Bob organize the two hikes
            cornwall.setOrganizer( bob );
            bob.getOrganizedHikes().add( cornwall );

            isleOfWight.setOrganizer( bob );
            bob.getOrganizedHikes().add( isleOfWight );

            // persist organizer (will be cascaded to hikes)
            entityManager.persist( bob );

            entityManager.getTransaction().commit();
           entityManager.close();
    }

    @AfterClass
    public static void closeEntityManagerFactory() {
        entityManagerFactory.close();
    }
}

This methods will make sure that the entity manager factory is created before running the tests and that the datastore contains some data. The data are the same we stored in part 1.

Now that we have some data in place, we can start to write some tests to search for them.

Using the Java Persistence Query Langage (JP-QL)

The JP-QL is a query language defined as part of the Java Persistence API (JPA) specification. It's designed to work with entities and to be database independent.

Taking the entity Hike as an example:

@Entity
public class Hike {

    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid2")
    private String id;

    private String description;
    private Date date;
    private BigDecimal difficulty;

    @ManyToOne
    private Person organizer;

    @ElementCollection
    @OrderColumn(name = "sectionNo")
    private List<HikeSection> sections;
       
      // constructors, getters, setters, ...
}

A JP-QL query to get the list of available hikes ordered by difficulty looks like this:

SELECT h FROM Hike h ORDER BY h.difficulty ASC

Hibernate OGM will parse this query and transform it into the equivalent one in the native query language of the datastore of your choice. In Neo4j, for example, it creates and execute a Cypher query like the following:

MATCH (h:Hike) RETURN h ORDER BY h.difficulty

In MongoDB, using the MongoDB JavaScript API as a query notation, it looks like this:

db.Hike.find({}, { "difficulty": 1})

If you use JP-QL in your application you will be able to switch between datastore without the need to update the queries.

Now that you have an understanding of what’s going on, we can start querying for the data we persisted. We can, for example, get the list of available hikes:

@Test
public void canSearchUsingJPQLQuery() {
    // Get a new entityManager
    EntityManager entityManager = entityManagerFactory.createEntityManager();

    // Start transaction
    entityManager.getTransaction().begin();

    // Find all the available hikes ordered by difficulty
    List<Hike> hikes = entityManager
        .createQuery( "SELECT h FROM Hike h ORDER BY h.difficulty ASC" , Hike.class )
        .getResultList();

    assertThat( hikes.size() ).isEqualTo( 2 );
    assertThat( hikes ).onProperty( "description" ).containsExactly( "Visiting Land's End", "Exploring Carisbrooke Castle" );

    entityManager.getTransaction().commit();
    entityManager.close();
}

If you have used the JPA specification before you will find this code very familiar: it's the same code you would write when working on a relational database using JPA.

You can test this by switching the configuration and dependency between Neo4j and MongoDB: the test will still pass without any change in the code.

The cool thing is that you can use JP-QL queries with datastores which don't have their own query engine. Hibernate OGM's query parser will create full-text queries in this case which are executed via Hibernate Search and Lucene. We will see later how you can do this in more details.

The result of the query is a list of managed entities. This means that changes to the objects will be applied to the data in the database automatically. You also can navigate the resulting object graph, causing lazy associations to be loaded as required.

The support for the JP-QL language is not complete and it might change depending on the backend. We will leave the details to the official Hibernate OGM documentation. At the moment what's supported is:

  • simple comparisons
  • IS NULL and IS NOT NULL
  • the boolean operators AND, OR, NOT
  • LIKE, IN and BETWEEN
  • ORDER BY

In case JP-QL is not a good fit for your use case, we will see how you can execute a query using the native language of the backend of your choice.

Using the native backend query language

Sometimes you might decide to sacrifice portablility in favor of the power of the underlying native query language. For example, you might want to benefit from the abilities of Neo4j's Cypher language for running hierarchical/recursive queries. Using MongoDB, let’s get the hikes passing through “Penzance”:

// Search for the hikes with a section that start from "Penzace" in MongoDB
List<Hike> hikes = entityManager.createNativeQuery("{ $query : { sections : { $elemMatch : { start: 'Penzance' } } } }", Hike.class ).getResultList();

The same code with Neo4j would look like this:

// Search for the hikes with a section that start from "Penzace" in Neo4j
List<Hike> hikes = entityManager.createNativeQuery( "MATCH (h:Hike) -- (:Hike_sections {start: 'Penzance'} ) RETURN h", 
Hike.class ).getResultList();

The important thing to notice is that, like JPA queries, the objects returned by the query are managed entities.

You can also define queries using the annotation javax.persistence.NamedNativeQuery:

@Entity
@NamedNativeQuery(
name = "PenzanceHikes",
query = "{ $query : { sections : { $elemMatch : { start: 'Penzance' } } } }", resultClass = Hike.class )
public class Hike {  }

and then execute it like this:

List<Hike> hikes = entityManager.createNamedQuery( "PenzanceHikes" ).getResultList();

Using Hibernate Search queries

Hibernate Search offers a way to index Java objects into Lucene indexes and to execute full-text queries on them. The indexes do live outside your datastore. This means you can have query capabilities even if they are not supported natively. It also offers a few interesting properties in terms of feature set and scalability. In particular, using Hibernate Search, you can off-load query execution to separate nodes and scale it independently from the actual datastore nodes.

For this example we are going to use MongoDB. You first need to add Hibernate Search to your application. In a Maven project, you need to add the following dependency in the pom.xml:

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

Now, you can select what you want to index:

@Entity
@Indexed
public class Hike {

    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid2")
    private String id;

    @Field
    private String description;

    private Date date;
    private BigDecimal difficulty;

    @ManyToOne
    private Person organizer;

    @ElementCollection
    @OrderColumn(name = "sectionNo")
    private List<HikeSection> sections;
       
    // constructors, getters, setters, ...
}

The @Indexed annotation identifies the classes that we want to index, while the @Field annotation specifies which properties of the class we want to index. Every time a new Hike entity is persisted via the entity manager using Hibernate OGM, Hibernate Search will automatically add it to the index and keep track of changes to managed entities. That way, index and datastore are up to date.

You can now look for the hikes to Carisbrooke using Lucene queries. In this example, we will use the query builder provided by Hibernate Search:

@Test
public void canSearchUsingFullTextQuery() {
    EntityManager entityManager = entityManagerFactory.createEntityManager();

    entityManager.getTransaction().begin();

    //Add full-text superpowers to any EntityManager:
    FullTextEntityManager ftem = Search.getFullTextEntityManager(entityManager);

    // Optionally use the QueryBuilder to simplify Query definition:
    QueryBuilder b = ftem.getSearchFactory().buildQueryBuilder().forEntity( Hike.class ).get();

    // A Lucene query to search for hikes to the Carisbrooke castle:
    Query lq = b.keyword().onField("description").matching("Carisbrooke castle").createQuery();

    //Transform the Lucene Query in a JPA Query:
    FullTextQuery ftQuery = ftem.createFullTextQuery(lq, Hike.class);

    //This is a requirement when using Hibernate OGM instead of ORM:
    ftQuery.initializeObjectsWith( ObjectLookupMethod.SKIP, DatabaseRetrievalMethod.FIND_BY_ID );

    // List matching hikes
    List<Hike> hikes = ftQuery.getResultList();
    assertThat( hikes ).onProperty( "description" ).containsOnly( "Exploring Carisbrooke Castle" );

    entityManager.getTransaction().commit();
    entityManager.close();
}

The result of the code will be a list of hikes mentioning “Carisbrooke castle” in the description.

Hibernate Search is a very powerful tool with many different options, it would take too long to describe all of them in this tutorial. You can check the reference documentation to learn more about it.

Wrap up

That’s all for now.

As you have seen, Hibernate OGM provides you with a range of options to run queries against your datastore, which should cover most of your typical query needs: JP-QL, native NoSQL queries and full-text queries via Hibernate Search / Apache Lucene. Even if you have never worked with NoSQL datastores before, you will be able to experiment with them easily.

You can find the complete example code of this blog post (and the previous one) on GitHub. Just fork it and play with it as you like.

Now that you know how to store and find your entities, we will see in the next part of the series how you can put everything inside an application container like WildFly.

We are eager to know your opinion, feel free to comment or contact us, we will answer your questions and hear your feed-back.;

back to top