Hibernate.orgCommunity Documentation

Chapter 15. Redis (Experimental)

15.1. Configuring Redis
15.1.1. Annotation based configuration
15.2. Storage principles
15.2.1. JSON mapping
15.2.2. Hash mapping
15.2.3. Associations
15.3. Identifiers
15.3.1. Identifier generation strategies
15.4. Transactions
15.5. Queries
15.6. Redis Cluster

Redis is a key-value datastore which stores your data in a variety of data structures. Although there is no one-and-only style how to map data between data structures and Redis, two major styles are are most common:

Note

Support for Redis is considered an EXPERIMENTAL feature as of this release. In particular you should be prepared for possible changes to the persistent representation of mapped objects in future releases.

Also be aware of the fact that partial updates using the JSON dialect are unsupported at the moment Instead always the entire document will be replaced during updates. This means that fields possibly written by other applications but not mapped to properties in your domain model will get lost.

The JSON dialect supports two modes for storing associations: The ASSOCIATION_DOCUMENT mode should be used with care as there is potential for lost updates (OGM-461). It is recommended to use the IN_ENTITY mode (which is the default).

Should you find any bugs or have feature requests for this dialect, then please open a ticket in the OGM issue tracker.

Hibernate OGM uses the lettuce library to talk to Redis, so you need the client libraries to use Hibernate OGM Redis.

The following properties are available to configure Redis support in Hibernate OGM:

Redis datastore configuration properties

hibernate.ogm.datastore.provider
To use Redis as a datastore provider, this property must be set to redis_experimental
hibernate.ogm.datastore.grid_dialect
The dialect type how Hibernate OGM Redis maps entities and associations within Redis. The following two dialects exist: org.hibernate.ogm.datastore.redis.RedisJsonDialect (store entities as JSON documents within Redis keys. Associations are mapped to Redis lists/sets) and org.hibernate.ogm.datastore.redis.RedisHashDialect (store entities as key-value pairs within Redis hashes. Associations are mapped as JSON documents to Redis lists/sets)
hibernate.ogm.datastore.host

The hostname and port of the Redis instance. The optional port is concatenated to the host and separated by a colon. Let’s see a few valid examples:

  • redis.example.com
  • redis.example.com:6379

    Listing multiple initial hosts for fault tolerance is not supported. The default value is 127.0.0.1:6379. If left undefined, the default port is 6379.

hibernate.ogm.datastore.database
The database number to connect to. If left undefined, the default number is 0. Note that Redis databases are identified with a number from 0 to 16.
hibernate.ogm.datastore.password
The password used to connect to the Redis server. This property has no default value.
hibernate.ogm.redis.ssl
Boolean flag to enable SSL connections to Redis. Note that Redis does not support native SSL and SSL is provided by tools like stunnel
hibernate.ogm.redis.connection_timeout
Defines the timeout used by the driver when the connection to the Redis instance is initiated. This configuration is expressed in milliseconds. The default value is 5000.
hibernate.ogm.redis.cluster
Boolean flag to enable Redis Cluster mode. It’s strongly recommended to use simple primary and association keys as composite keys are serialized as JSON which may interfere the slot distribution. Curly braces within keys are used to denote hash tags to group keys within one slot.
hibernate.ogm.redis.ttl
Defines the TTL for entities and associations. TTL can be configured on entity and association level (see Section 15.1.1, “Annotation based configuration” This property has no default value.
hibernate.ogm.error_handler
The fully-qualified class name, class object or an instance of ErrorHandler to get notified upon errors during flushes (see Section 6.3.1, “Acting upon errors during application of changes”)
hibernate.ogm.datastore.redis.association_storage
Defines the way OGM stores association information in Redis. The following two strategies exist for the JSON dialect (values of the org.hibernate.ogm.datastore.document.options.AssociationStorageType enum): IN_ENTITY (store association information within the entity) and ASSOCIATION_DOCUMENT (store association information in a dedicated document per association). IN_ENTITY is the default and recommended option unless the association navigation data is much bigger than the core of the document and leads to performance degradation. The Redis hash dialect supports only the ASSOCIATION_DOCUMENT strategy.
hibernate.ogm.datastore.document.map_storage

Defines the way OGM stores the contents of map-typed associations in Redis. The following two strategies exist (values of the org.hibernate.ogm.datastore.document.options.MapStorageType enum):

  • BY_KEY: map-typed associations with a single key column which is of type String will be stored as a sub-document, organized by the given key; Not applicable for other types of key columns, in which case always AS_LIST will be used
  • AS_LIST: map-typed associations will be stored as an array containing a sub-document for each map entry. All key and value columns will be contained within the array elements The default value is BY_KEY.

Note

When bootstrapping a session factory or entity manager factory programmatically, you should use the constants accessible via RedisProperties when specifying the configuration properties listed above. Common properties shared between stores are declared on OgmProperties. To ease migration between stores, it is recommended to reference these constants directly from there.

Hibernate OGM allows to configure store-specific options via Java annotations. When working with the Redis backend, you can specify how associations should be stored using the AssociationStorage annotation. A strategy for storing the contents of map-typed associations can be defined using the @MapStorage annotation.

(refer to Section 15.2, “Storage principles” to learn more about association storage strategies in general).

The following shows an example:



Redis supports a native TTL/expiry mechanism. Keys can expire at a date or after a certain period. Hibernate OGM allows to specify a TTL value on entities and associations. The TTL is set after persisting the entity using the PEXPIRE command. Every write to Redis will set a new TTL.

The annotation on the entity level expresses that all associations of the Zoo class should be stored in separate assocation documents. This setting applies to the animals and employees associations. Only the elements of the visitors association will be stored in the document of the corresponding Zoo entity as per the configuration of that specific property which takes precedence over the entity-level configuration.

Hibernate OGM tries to make the mapping to the underlying datastore as natural as possible so that third party applications not using Hibernate OGM can still read and update the same datastore. Hibernate OGM facilitates two styles of data mapping within Redis:

The following describe how entities and associations are mapped to Redis data structures by Hibernate OGM.

The JSON mapping dialect maps entities to JSON documents and stores the JSON data within Redis keys. A document is self-contained and does not support partial updates.

Hibernate OGM stores elements annotated with @Embedded or @ElementCollection as nested documents of the owning entity.




The class GrandChild has only one attribute name, this means that Hibernate OGM doesn’t need to store the name of the attribute.

If the nested document has two or more fields, like in the following example, Hibernate OGM will store the name of the fields as well.


The Redis Hash mapping dialect maps entities to key-value pairs. It stores the data within Redis hashes. Hashes support partial updates. While the JSON dialect discards not mapped fields in the entity model the hash dialect does not touch fields that are not mapped to the entity model.

Entities are stored as key-value pairs within Redis hashes. Each entity property will be translated into a hash field and is represented as java.lang.String. The Redis hash dialect supports only flat data structures hence nested entities and associations are represented as JSON documents within the association documents in Redis lists/sets. You can use the name property of the @Table and @Column annotations to rename the collections and the document’s fields if you need to.

Redis has no built-in mechanism for detecting concurrent updates to one and the same document.

The following shows an example of an entity and its persistent representation in Redis.


Redis doesn’t have a concept of "tables"; Instead all values are stored in a hash as key values. The hash key contains the table name and the primary key of the entity. Thus Hibernate OGM needs to add two additional attributes:


Hibernate OGM stores elements annotated with @Embedded or @ElementCollection as nested documents of the owning entity.




The class GrandChild has only one attribute name, this means that Hibernate OGM doesn’t need to store the name of the attribute.

If the nested document has two or more fields, like in the following example, Hibernate OGM will store the name of the fields as well.


Hibernate OGM Redis provides two strategies to store navigation information for associations:

You can switch between the two strategies using:

With this strategy, Hibernate OGM directly stores the id(s) of the other side of the association into a field or an embedded document depending if the mapping concerns a single object or a collection. The field that stores the relationship information is named like the entity property.





In a true one-to-one association, it is possible to share the same id between the two entities and therefore a foreign key is not required. You can see how to map this type of association in the following example:





A map can be used to represents an association, in this case Hibernate OGM will store the key of the map and the associated id.


If the map value cannot be represented by a single field (e.g. when referencing a type with a composite id or using an embeddable type as map value type), a sub-document containing all the required fields will be stored as value.

If the map key either is not of type String or it is made up of several columns (composite map key), the optimized structure shown in the example above cannot be used. In that case the association will be represented by a list of sub-documents, also containing the map key column(s). You can use @MapKeyColumn to rename the field containing the key of the map, otherwise it will default to "<%COLLECTION_ROLE%>_KEY", e.g. "addresses_KEY".

In case you want to enforce the list-style represention also for maps with a single key column of type String you can use the option hibernate.ogm.datastore.document.map_storage to do so.






With this strategy, Hibernate OGM uses separate association data structures to store all navigation information. The association data structure depends on the type of the association:

Each association has 2 parts. The first is the key. The key consists of a prefix, the identifier information of the association owner, and the name of the association table.

Associations:<%ASSOCIATION_TABLE%:<%ASSOCIATION_ID%:<%COLLECTION_ROLE%, e.g. "Associations:AccountOwner:4f5b48ad-f074-4a64-8cf4-1f9c54a33f76:BankAccount".

The second part is the rows field which stores (into an embedded collection) all ids that the current instance is related to.


For a bidirectional relationship, another list is created where ids are reversed. Don’t worry, Hibernate OGM takes care of keeping them in sync:


Note

This strategy won’t affect *-to-one associations or embedded collections.


Using the annotation @JoinTable it is possible to change the value of the document containing the association.




Redis keys are derived from the Entity name and its Id separated by a colon (:). String-based Id’s are used directly within the key, non-string keys are encoded to JSON. You can use any persistable Java type as identifier type, e.g. String or long. Hibernate OGM will convert the @Id property into a part of the key name so you can name the entity id like you want.

Note that you also can work with embedded ids (via @EmbeddedId), Composite Id’s are mapped to a JSON object containing keys and values. Hibernate OGM thus will create a concatenated representation of the embedded id’s properties in this case. The columns are sorted in alphabetical order to guarantee the same order.


You can assign id values yourself or let Hibernate OGM generate the value using the @GeneratedValue annotation.

Two main strategies are supported:

Both strategies will operate in the keys starting with Identifiers containing the last value of the id. The difference between the two strategies is the name of the key containing the values.

The AUTO strategy is the same as the SEQUENCE one.

The next value is obtained using Redis' HINCRBY command that guarantees to create atomic updates to the underlying data structure.

1) TABLE generation strategy



2) SEQUENCE generation strategy



Note

The value stored in Redis for the sequence is not the one the dialect will return as next number in the sequence. Instead, Hibernate OGM will use it as seed to generate the correct value in the sequence.

The Redis dialect does not support transactions for now. Only changes applied to the same document are done atomically. A change applied to more than one document will not be applied atomically. This problem is slightly mitigated by the fact that Hibernate OGM queues all changes before applying them during flush time. So the window of time used to write to Redis is smaller than what you would have done manually.

We recommend that you still 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.

Hibernate OGM is a work in progress and we are actively working on JP-QL query support.

In the mean time, you can use Hibernate Search to query entities stored by Hibernate OGM.

Using Hibernate OGM with Redis Cluster is a matter of enabling Redis Cluster mode (see Section 15.1, “Configuring Redis”). Data stored with Hibernate OGM Redis is distributed across Redis Cluster nodes according to the Redis key distribution model based on the hash slot of the key of each entity.